JJijibora
Docs & Product Guide
On this page (22 sections)

Backend Implementation Backlog — Sovereign OS / Jamii Console

Date: 9 Nov 2026
Branch: program-backlog
Status: Draft for implementation
Scope: Backend APIs and modules only. Frontend/UI work is tracked separately.

How to read this backlog

Each item has:

  • ID — unique reference (BL-001, BL-002, …)
  • Priority — P0 (blocking), P1 (needed for MVP), P2 (nice to have)
  • Status — TODO / IN PROGRESS / DONE / BLOCKED
  • Files — exact file paths to create or modify
  • Acceptance criteria — what "done" looks like; all must pass node --test and run-gtm-live-observe.mjs --require-live
  • Dependencies — must be completed before this item

Mandatory constraints (from AGENTS.md — Sovereign OS / Cosmic Circuit and D-15):

  • No bespoke tables. Everything maps into claim, truth_node/edge, resource/edge, integration_entity.
  • Declarative-first: lookups, thresholds, packs, maps live in NATS KV (SOVEREIGN_LOOKUPS/SOVEREIGN_SCENARIOS). Runtime never reads disk.
  • Fail-closed: infrastructure errors → 502/503/422/throw. Never synthetic "OPTIMAL"/"APPROVED".
  • Soft≠LIVE honesty: live_gate_met/invent_refuse_live are real probe results.
  • All modules must pass node --test and run-gtm-live-observe.mjs --require-live before merge.

Phase 1 — Core Claim & Property APIs (Blocking)

BL-001 — GET /v1/communities/:orgId/properties — List properties for an org

FieldValue
IDBL-001
PriorityP0
StatusDONE
Filesapps/agent-bff/src/property-playbook.js (listProperties()), apps/agent-bff/src/building-reflex-routes.js (route mount)
Depends onNone

What to build:

  • listProperties(input) in property-playbook.js: queries claim table where claim_type = "property" and subject_id = orgId, returns claim_id, claim_type, cns_name, state, metadata, created_at, with ?state, ?limit, ?offset filters
  • Route: GET /v1/communities/:orgId/properties in building-reflex-routes.js
  • Must return empty array [] when no properties exist (honest empty state)

Acceptance criteria:

  • Returns 200 with { data: [...], limit, offset }
  • Returns empty array [] when no properties
  • 422 when orgId missing
  • 503 when SurrealDB unavailable
  • Test added to __tests__/building-reflex-sourcing-mars.test.js (or new test file)

BL-002 — GET /v1/community/properties/:id — Get single property detail

FieldValue
IDBL-002
PriorityP0
StatusDONE
Filesapps/agent-bff/src/property-playbook.js (getProperty()), apps/agent-bff/src/building-reflex-routes.js (route mount)
Depends onBL-001

What to build:

  • getProperty(input) in property-playbook.js: SELECT * FROM claim WHERE claim_id = $id AND claim_type = "property" LIMIT 1
  • Route: GET /v1/community/properties/:id in building-reflex-routes.js
  • Returns 404 when claim not found

Acceptance criteria:

  • Returns 200 with { data: { claim_id, claim_type, cns_name, state, metadata, created_at } }
  • Returns 404 when claim not found
  • 422 when id missing
  • 503 when SurrealDB unavailable

BL-003 — POST /v1/community/sourcing/offers/:id/accept — Accept a sourcing offer

FieldValue
IDBL-003
PriorityP0
StatusDONE
Filesapps/agent-bff/src/community-sourcing.js (acceptOffer()), apps/agent-bff/src/building-reflex-routes.js (route mount)
Depends oningestOffer() (already implemented in community-sourcing.js)

What to build:

  • acceptOffer(input) in community-sourcing.js: validates the offer claim exists, creates a binding claim, transitions the requirement to BOUND
  • Route: POST /v1/community/sourcing/offers/:offerId/accept in building-reflex-routes.js
  • Must emit canonical envelope via ontology.normalizeSourcingRequirement()

Acceptance criteria:

  • Returns 201 with { ok: true, created: true, claim_id: <bindingId>, cns_name: <bindingCNS>, organization_id, provider_id }
  • Returns 404 if offer not found
  • Returns 422 if required fields missing
  • Returns 503 when SurrealDB unavailable
  • Emits platform.criteria.v1.sourcing.requirement event via outbox

BL-004 — GET /v1/community/:domain/:id — Generic claim detail

FieldValue
IDBL-004
PriorityP1
StatusDONE
Filesapps/agent-bff/src/jijibora-event-ontology.js (getClaim()), apps/agent-bff/src/building-reflex-routes.js (route mount)
Depends onNone

What to build:

  • getClaim(input) in jijibora-event-ontology.js: SELECT * FROM claim WHERE claim_id = $id LIMIT 1, returns canonical envelope shape
  • Route: GET /v1/community/:domain/:id in building-reflex-routes.js

Acceptance criteria:

  • Returns 200 with { ok: true, claim_id, cns_name, state, metadata, created_at, envelope, subject }
  • Returns 404 when claim not found
  • 422 when id missing
  • 503 when SurrealDB unavailable

BL-005 — POST /v1/community/:domain/:id/note — Operator note on a claim

FieldValue
IDBL-005
PriorityP1
StatusDONE
Filesapps/agent-bff/src/jijibora-event-ontology.js (appendNote()), apps/agent-bff/src/building-reflex-routes.js (route mount)
Depends onBL-004

What to build:

  • appendNote(input) in jijibora-event-ontology.js: appends a note to claim.metadata.notes array, emits canonical envelope
  • Route: POST /v1/community/:domain/:id/note in building-reflex-routes.js

Acceptance criteria:

  • Returns 200 with { ok: true, claim_id, note_id, created_at }
  • Returns 404 when claim not found
  • Returns 422 when note field missing
  • Note is append-only (append to array, never overwrite)

Phase 2 — Billing & OpenMaint Facades

BL-006 — Kill Bill billing facade — GET /v1/billing/subscriptions, POST /v1/billing/invoices

FieldValue
IDBL-006
PriorityP1
StatusDONE
Filesapps/agent-bff/src/killbill-routes.js (new), apps/agent-bff/src/index.js (mount)
Depends onbilling-routes.js exists; commerce-killbill.js exists

What to build:

  • Create apps/agent-bff/src/killbill-routes.js: thin proxy to Kill Bill bridge
    • GET /v1/billing/subscriptions → proxies to Kill Bill
    • POST /v1/billing/invoices → proxies to Kill Bill
  • Mount in apps/agent-bff/src/index.js
  • Must fail closed when Kill Bill is unreachable (503)

Acceptance criteria:

  • Returns 200 with Kill Bill response passthrough
  • Returns 503 when Kill Bill unreachable
  • 401/403 when unauthenticated

BL-007 — OpenMaint facade — GET /v1/properties/:id/work-orders, POST /v1/properties/:id/work-orders

FieldValue
IDBL-007
PriorityP1
StatusDONE
Filesapps/agent-bff/src/openmaint-routes.js (new), apps/agent-bff/src/index.js (mount)
Depends onNone

What to build:

  • Create apps/agent-bff/src/openmaint-routes.js: thin proxy to OpenMaint
    • GET /v1/properties/:id/work-orders → proxies to OpenMaint
    • POST /v1/properties/:id/work-orders → proxies to OpenMaint
  • Mount in apps/agent-bff/src/index.js
  • Must fail closed when OpenMaint is unreachable (503)

Acceptance criteria:

  • Returns 200 with OpenMaint response passthrough
  • Returns 503 when OpenMaint unreachable
  • 401/403 when unauthenticated

Phase 3 — Route Mounting & Route Completeness

BL-008 — Mount building-reflex-routes.js in index.js

FieldValue
IDBL-008
PriorityP0
StatusDONE
Filesapps/agent-bff/src/index.js
Depends onBL-001 through BL-007

What to build:

  • Add const brRoutes = require('./building-reflex-routes'); and mount call in apps/agent-bff/src/index.js
  • Currently building-reflex-routes.js exists but is NOT mounted in index.js (verified: not in the require/mount section)

Acceptance criteria:

  • node --check apps/agent-bff/src/index.js passes
  • All building-reflex routes respond (not 404) when BFF is running
  • run-gtm-live-observe.mjs passes (28/28)

BL-009 — Add missing tests for A1–A7 APIs

FieldValue
IDBL-009
PriorityP1
StatusDONE
Filesapps/agent-bff/src/__tests__/ (new test files or extend existing)
Depends onBL-001 through BL-007

What to build:

  • Test file apps/agent-bff/src/__tests__/property-playbook.test.js for BL-001, BL-002
  • Test file apps/agent-bff/src/__tests__/sourcing-offer.test.js for BL-003
  • Test file apps/agent-bff/src/__tests__/generic-claim.test.js for BL-004, BL-005
  • Test file apps/agent-bff/src/__tests__/billing-facade.test.js for BL-006
  • Test file apps/agent-bff/src/__tests__/openmaint-facade.test.js for BL-007

Acceptance criteria:

  • All new tests pass: node --test apps/agent-bff/src/__tests__/*.test.js
  • Mock querySurreal to simulate SurrealDB responses (fail-closed, no synthetic success)

Phase 4 — Backend Observability & Reliability

BL-010 — Add CNS interface catalog entries for new endpoints

FieldValue
IDBL-010
PriorityP1
StatusDONE
Filesdatabase/seeds/cns/cns_interface_catalog_*.surql
Depends onBL-001 through BL-007

What to build:

  • Add CNS interface entries for property, sourcing offer accept, and generic claim endpoints in cns_interface_catalog_building_reflex_sourcing_mars.surql
  • Each entry: cns_path, version, major_version, interface_type, communication_pattern, input_schema, output_schema

Acceptance criteria:

  • JSON parses: node -e "JSON.parse(require('fs').readFileSync('...','utf8'))" for all .surql files
  • CNS seed imports without error (surreal import)

BL-011 — Add outbox anchors for all new write endpoints

FieldValue
IDBL-011
PriorityP1
StatusDONE
Filesapps/agent-bff/src/property-playbook.js, apps/agent-bff/src/community-sourcing.js
Depends onBL-001 through BL-005

What to build:

  • Every state-changing endpoint (complete, bind, accept, create) must write to nats_outbox before returning
  • Use ontology.buildOutboxEnqueue(envelope, subject) pattern
  • Fail closed: if outbox insert fails, return 503

Acceptance criteria:

  • Every write endpoint returns outbox object in response
  • outbox.record_key, outbox.subject, outbox.payload present
  • run-gtm-live-observe.mjs passes

Phase 5 — Release & Observability

BL-012 — Restart agent-bff from current tree & verify all routes

FieldValue
IDBL-012
PriorityP0
StatusDONE
FilesNone (ops)
Depends onBL-001 through BL-011

What to build:

  • Stop the stale agent-bff process (PID 20816, started 11/6)
  • Start apps/agent-bff/src/index.js from current tree
  • Verify all new routes respond (not 404)

Acceptance criteria:

  • GET http://127.0.0.1:3030/health returns 200
  • GET http://127.0.0.1:3030/v1/community/health returns 200
  • New routes return 200/404/422 (not 404 for missing route)

BL-013 — Run full verification suite

FieldValue
IDBL-013
PriorityP0
StatusDONE
FilesNone (ops)
Depends onBL-001 through BL-012

What to build:

  • Run node --test apps/agent-bff/src/__tests__/*.test.js — all must pass
  • Run node scripts/run-gtm-live-observe.mjs --require-live — live_gate_met:true
  • Run node scripts/check-criteria-subject-consistency.mjs — PASS
  • Run node scripts/check-mars-freeze.mjs — PASS

Acceptance criteria:

  • 20+ tests pass, 0 fail
  • live_gate_met:true
  • Subject consistency: 0 failures
  • Mars freeze: PASS

Phase Order

Phase 1: BL-001 → BL-005  (Core claim & property APIs)
Phase 2: BL-006 → BL-007  (Billing & OpenMaint facades)
Phase 3: BL-008 → BL-009  (Route mounting & tests)
Phase 4: BL-010 → BL-011  (CNS catalog + outbox anchors)
Phase 5: BL-012 → BL-013  (Restart & verify)

Estimated effort

PhaseItemsEstimated effort
Phase 1BL-001 to BL-0052–3 days
Phase 2BL-006 to BL-0071–2 days
Phase 3BL-008 to BL-0091 day
Phase 4BL-010 to BL-0111 day
Phase 5BL-012 to BL-0131 day
Total13 items6–9 days

Done criteria for the entire backlog

  • node --test apps/agent-bff/src/__tests__/*.test.js → all pass (20+ tests)
  • node scripts/run-gtm-live-observe.mjs --require-live → live_gate_met:true
  • node scripts/check-criteria-subject-consistency.mjs → PASS
  • node scripts/check-mars-freeze.mjs → PASS
  • All 13 items marked DONE in this document