Skip to content

feat(sidecar): JSON-family storage backend — plain / JSON-LD / NDJSON (V-L2-F3, #146)#148

Merged
hyperpolymath merged 2 commits into
mainfrom
claude/gracious-curie-HS03A
May 30, 2026
Merged

feat(sidecar): JSON-family storage backend — plain / JSON-LD / NDJSON (V-L2-F3, #146)#148
hyperpolymath merged 2 commits into
mainfrom
claude/gracious-curie-HS03A

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

V-L2-F3: JSON-family sidecar storage backend (#146)

Implements a real json sidecar store covering plain JSON, JSON-LD, and NDJSON, with full parity to the runtime operations the SQLite path implements today. Re-opens the capability that #112/#144 dropped — at the maintainer's request — now deliberately scoped and built rather than aspirational.

Manifest

  • [sidecar].storage = "json" is accepted again; new [sidecar].format = plain (default) | ld | ndjson.
  • New sidecar::StorageKind::resolve(storage, format) is the single source of truth (Sqlite | Postgres | Json(JsonFormat)); the old SqlDialect::from_storage is folded into it. validate/doctor, generate, drift, and gc all defer to it, so they agree on the accepted set and reject typos / bad formats consistently.

Store (src/sidecar/json.rs)

  • One SidecarData model mirrors the verisimdb_* tables; the format is purely a codec, so every octad operation is written once and is format-independent:
    • plain — the model as a keyed object;
    • ld@context + @graph of typed (@type/@id) nodes (genuine linked data);
    • ndjson — one {"_table": …} record per line.
  • Provenance: linear append, append_fork, verify_chain, fork_points — reusing abi::ProvenanceEntry::compute_hash, so hashing is byte-identical to the SQLite backend.
  • Temporal: append_version (monotonic, exactly-one-current enforced in code), read_current, read_at, rollback_to.
  • Drift: reuses the storage-agnostic tier1::drift::temporal_drift_score.
  • GC: purges provenance / superseded-temporal / lineage by age (keeps the current version).
  • Crash-safe writes (temp file + atomic rename); logical append-only, single-writer model (the one documented difference from SQLite's lock-based serialization).

Commands

  • generate emits a format-appropriate scaffold sidecar_schema.{json,jsonld,ndjson} (DDL-parity for SQL); drift and gc dispatch to the JSON store; postgres drift/gc remain explicit "not yet implemented".

Verification

  • 141 lib unit tests (incl. 22 new sidecar tests exercising provenance/temporal/drift/gc + codec round-trips across all three formats) + all integration tests pass.
  • cargo clippy --all-targets -- -D warnings and cargo fmt --check clean.
  • Manual CLI smoke test confirmed validate (new sidecar-storage-supported check), generate (plain/ld/ndjson scaffolds incl. JSON-LD @context/@graph), gc, and drift all work against a json manifest, and that a bad format is rejected with a clear message.

Acceptance (#146)

  • storage = "json" + format = plain|ld|ndjson parse, validate, round-trip; bad format rejected clearly.
  • StorageKind::resolve is the single resolver; validate/doctor accept json, reject typos.
  • JSON store passes provenance (incl. fork + tamper), temporal (monotonic + one-current + rollback), drift, and gc tests across all three formats.
  • generate emits a format-appropriate scaffold; drift and gc honour the json store.
  • SidecarConfig docs + manifest template document json and format.

Closes #146.

https://claude.ai/code/session_01S2xDQQU5o85N3xTpeFUSfN


Generated by Claude Code

V-L2-F3. Re-opens the JSON sidecar capability dropped in #112/#144, now as
a deliberately-scoped family with full parity to the runtime operations the
SQLite path implements today.

Manifest:
- `[sidecar].storage = "json"` is accepted again; new `[sidecar].format`
  selects the encoding: plain (default) | ld (JSON-LD) | ndjson.
- New `sidecar::StorageKind::resolve(storage, format)` is the single source
  of truth (Sqlite | Postgres | Json(JsonFormat)); `SqlDialect::from_storage`
  is folded into it. `validate`/`doctor`, `generate`, `drift`, `gc` defer to
  it, so they agree on the accepted set and reject typos/bad formats.

Store (src/sidecar/json.rs):
- One `SidecarData` model mirrors the verisimdb_* tables; the format is purely
  a codec over it, so octad operations are written once and are
  format-independent. JSON-LD emits @context + @graph of typed (@type/@id)
  nodes; NDJSON emits one `{"_table":…}` record per line; plain is the model.
- Provenance (linear append, fork, verify_chain, fork_points) reuses
  `abi::ProvenanceEntry::compute_hash`, so hashing is identical across
  backends. Temporal (append_version, read_current, read_at, rollback_to)
  enforces monotonicity + exactly-one-current in code. Temporal drift reuses
  the storage-agnostic `tier1::drift::temporal_drift_score`. GC purges
  provenance/temporal(superseded)/lineage by age.
- Writes are crash-safe (temp file + atomic rename); logical append-only,
  single-writer model documented.

Commands:
- `generate` emits a format-appropriate scaffold (sidecar_schema.{json,jsonld,
  ndjson}) for SQL→DDL parity; `drift` and `gc` dispatch to the json store.

Tests: provenance (incl. fork + tamper), temporal (monotonic/one-current/
read_at/rollback), drift (matches the SQLite worked example), and gc mirror
the SQLite suite across all three formats; resolver + codec + scaffold round
-trips covered. Full suite green; clippy -D warnings and fmt clean.

Closes #146.

https://claude.ai/code/session_01S2xDQQU5o85N3xTpeFUSfN
@hyperpolymath hyperpolymath marked this pull request as ready for review May 30, 2026 22:58
#147 (test-only postgres validate + gc fixture) landed on main after this
branch was pushed. Incorporated by keeping #147's postgres-storage validate
test and reconciling the gc rejection test with #148's dispatch (postgres gc
now reports "not yet implemented"; the json family is supported).

https://claude.ai/code/session_01S2xDQQU5o85N3xTpeFUSfN
@hyperpolymath hyperpolymath merged commit 67291a1 into main May 30, 2026
10 of 19 checks passed
@hyperpolymath hyperpolymath deleted the claude/gracious-curie-HS03A branch May 30, 2026 23:03
hyperpolymath added a commit that referenced this pull request May 30, 2026
… (V-L2-F3) (#152)

Reconcile the decision record with main after a merge race: V-L2-F3 (#146,
#148) reversed the V-L2-F2 json drop and implemented a JSON-family sidecar
backend. Adds ADR-0012 (supersedes ADR-0011), nets the CHANGELOG to
"Added: JSON-family backend", and lists json in the README example.
Docs only.

https://claude.ai/code/session_01Ux144vBDdySvLUqUrCgkT4
Comment thread src/sidecar/json.rs
@@ -0,0 +1,1291 @@
// SPDX-License-Identifier: PMPL-1.0-or-later
@github-actions
Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 81 issues detected

Severity Count
🔴 Critical 2
🟠 High 7
🟡 Medium 72

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Action perpolymath/standards/.github/workflows/governance-reusable.yml@main\n needs attention",
    "type": "unpinned_action",
    "file": "governance.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action actions/checkout@v4 needs attention",
    "type": "unpinned_action",
    "file": "rust-ci.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action dtolnay/rust-toolchain@stable needs attention",
    "type": "unpinned_action",
    "file": "rust-ci.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action Swatinem/rust-cache@v2 needs attention",
    "type": "unpinned_action",
    "file": "rust-ci.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action actions/checkout@v4 needs attention",
    "type": "unpinned_action",
    "file": "rust-ci.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action dtolnay/rust-toolchain@master needs attention",
    "type": "unpinned_action",
    "file": "rust-ci.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Action Swatinem/rust-cache@v2 needs attention",
    "type": "unpinned_action",
    "file": "rust-ci.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in boj-build.yml",
    "type": "missing_timeout_minutes",
    "file": "boj-build.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in casket-pages.yml",
    "type": "missing_timeout_minutes",
    "file": "casket-pages.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in casket-pages.yml",
    "type": "missing_timeout_minutes",
    "file": "casket-pages.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

V-L2-F3: implement JSON-family sidecar storage backend (plain JSON / JSON-LD / NDJSON)

3 participants