# =============================================================================
# NextXus YamlDB v1.1 — Formal Schema Reference
# =============================================================================
# This file is auto-generated on backend startup. It is the authoritative
# specification of every collection and every field stored under /app/data/.
# A third-party engineer should be able to reconstruct a compatible reader
# from this file alone, without reading any NextXus source code.
# =============================================================================

format: NextXus YamlDB v1.1
encoding: UTF-8 YAML 1.2
integrity:
  per_file:
    algorithm: SHA-256
    location: /MANIFEST.yaml
  chain:
    algorithm: SHA-256
    payload: |
      json.dumps(canonical_entry, sort_keys=True, separators=(',', ':')).encode('utf-8')
      where canonical_entry includes: id, status, content, source, submitted_by,
      agent_zero_score, agent_zero_rationale, c_graded, ring_of_12 (sorted),
      audit_trail, timestamp, prev_hash.

collections:

  ledger:
    description: Append-only public record of accepted verifications.
    append_only: true
    primary_key: id
    indexes: [id, status, consensus_band]
    file_naming: "<sortable-ts>_<id8>.yaml — lexicographically sortable so listdir order equals chronological order."
    fields:
      id:                   { type: string, format: uuid-v4, required: true }
      status:               { type: string, enum: [accepted, rejected], required: true }
      content:              { type: string, required: true, max_length: 8000 }
      source:               { type: string, required: false }
      submitted_by:         { type: string, required: false }
      agent_zero_score:     { type: number, required: true, range: [0.0, 1.0] }
      agent_zero_rationale: { type: string, required: true }
      gate_threshold:       { type: number, default: 0.95 }
      ring_of_12:           { type: array, items_count: 12, item_fields: [perspective, grade, rationale] }
      c_graded:             { type: number, required: true, range: [0.0, 10.0] }
      consensus_band:       { type: string, enum: ["A — Verified Consensus", "B — Strong Support", "C — Qualified Support", "D — Disputed", "F — Rejected by Ring"] }
      timestamp:            { type: string, format: iso-8601-utc, required: true }
      audit_trail:          { type: array, items_type: string }
      prev_hash:            { type: string, format: sha256-hex, nullable: true }
      entry_hash:           { type: string, format: sha256-hex, required: true }
      amends:               { type: string, format: uuid-v4, nullable: true, description: "If set, this entry amends a prior entry with that id." }
      access_code:          { type: string, nullable: true, description: "Which press pass paid for this entry (transparency)." }
      source_node:          { type: string, enum: [local, federation], default: local }

  rejected:
    description: Public transparency log — every Agent Zero rejection preserved.
    append_only: true
    primary_key: id
    indexes: [id, status]
    fields: Same as `ledger` (status will always be `rejected`, ring_of_12 will be empty []).

  amendments:
    description: Parent → child amendment links.
    append_only: true
    primary_key: id
    indexes: [id]
    fields:
      id:        { type: string, format: uuid-v4, required: true }
      parent_id: { type: string, format: uuid-v4, required: true }
      child_id:  { type: string, format: uuid-v4, required: true }
      timestamp: { type: string, format: iso-8601-utc, required: true }

  access_codes:
    description: Press passes and Gumroad-issued tokens (mutable counters).
    append_only: false  # uses_remaining decrements on each accepted verification
    primary_key: code
    indexes: [code]
    fields:
      code:           { type: string, required: true }
      label:          { type: string, required: false }
      max_uses:       { type: integer, required: true, range: [1, 1000] }
      uses_remaining: { type: integer, required: true, range: [0, 1000] }
      created_at:     { type: string, format: iso-8601-utc }
      last_used_at:   { type: string, format: iso-8601-utc, nullable: true }
      active:         { type: boolean, default: true }
      source:         { type: string, enum: [press_pass, gumroad] }
      gumroad_sale_id: { type: string, nullable: true }
      gumroad_email:  { type: string, nullable: true }

migration:
  to_json: GET /api/ledger/export.json
  to_csv:  GET /api/ledger/export.csv
  to_yaml: GET /api/ledger/export.yaml
  to_postgres: |
    # YAML maps cleanly onto a JSONB column in Postgres:
    CREATE TABLE nextxus_ledger (id UUID PRIMARY KEY, doc JSONB NOT NULL);
    -- then for each ledger/*.yaml file:
    -- INSERT INTO nextxus_ledger (id, doc) VALUES ('<id>', '<yaml-as-json>'::jsonb);

resilience_notes: |
  - This format has zero runtime dependencies. A human with `cat`, `less`, or
    Notepad can read every record without a database, a driver, a daemon, or
    a service. If NextXus disappears tomorrow, the ledger remains readable.
  - YAML 1.2 (yaml.org/spec/1.2.2) was finalized in 2009 and is implemented
    in every mainstream language. The format pre-dates current AI bubbles
    and outlives current vendor cycles.
  - On a system migration, the entire data directory can be `tar`'d and
    moved unchanged. There is no schema upgrade ritual — old files describe
    themselves (see schema.yaml at this root and the preamble in every file).
  - The MANIFEST.yaml file is reconstructable from disk at any time via:
        python -m yamldb_cli rebuild-manifest
