Skip to content

Instantly share code, notes, and snippets.

@jollyjoker992
Last active October 13, 2025 04:13
Show Gist options
  • Save jollyjoker992/a72a48ce44b6697e078d61d907fba08a to your computer and use it in GitHub Desktop.
Save jollyjoker992/a72a48ce44b6697e078d61d907fba08a to your computer and use it in GitHub Desktop.
FF Registry Draft Design

Orbit-2 Curation: Registry + Feed (Worker) • Final Technical Design v1.0

Purpose: Define a complete, copy-ready architecture for Orbit-2’s endorsement (star) flow, bridging the Registry (trust ledger) and Feed (discovery) layers. Integrates webhook delivery, backfill sync, and Cloudflare materialization.


0) High-Level Architecture

TBD

  • Registry (Band 8) — canonical ledger of signed facts.
  • Workers (Band 3) — read-side materialization via KV/Queue.
  • Feed (Band 3) — read-only discovery API; joins star data from KV.

1) Registry Design

1.1 Tables (Postgres)

CREATE TABLE subjects (
  id BIGSERIAL PRIMARY KEY,
  origin TEXT NOT NULL, -- e.g., "feed.ff" | "feed.objkt" | "onchain.eth"
  type TEXT NOT NULL, -- e.g., "playlist" | "asset" | "device" | "user"
  ref TEXT NOT NULL, -- stable external ID, e.g., playlist ID or on‑chain token id
  digest_b64 TEXT, -- optional: base64 of hash binding to exact version
  created_at TIMESTAMPTZ DEFAULT now(),
  UNIQUE (origin, type, ref, coalesce(digest_b64,''))
);

CREATE TYPE fact_status AS ENUM ('active','revoked','expired','quarantined');

CREATE TABLE facts (
  id BIGSERIAL PRIMARY KEY,
  kind TEXT NOT NULL, -- e.g., 'endorsement.star', 'rights.grant', 'identity.link'
  subject_id BIGINT NOT NULL REFERENCES subjects(id),
  issuer_did TEXT NOT NULL, -- did:key:... | did:ff:... | did:pkh:...
  body_json JSONB NOT NULL, -- canonical body for human/machine semantics
  body_hash_b64 TEXT NOT NULL, -- base64(sha256(RFC8785(body_json)))
  sig_b64 TEXT NOT NULL, -- base64(ed25519(...) or EIP-191, etc.)
  alg TEXT NOT NULL, -- 'ed25519' | 'eip191' | 'bbs+'
  status fact_status NOT NULL DEFAULT 'active',
  issued_at TIMESTAMPTZ NOT NULL,
  created_at TIMESTAMPTZ DEFAULT now(),
  UNIQUE (kind, subject_id, issuer_did, body_hash_b64)
);

CREATE INDEX idx_facts_subject_kind ON facts (subject_id, kind) WHERE status='active';
CREATE INDEX idx_facts_issuer ON facts (issuer_did) WHERE status='active';

CREATE TABLE fact_revocations (
  id BIGSERIAL PRIMARY KEY,
  fact_id BIGINT NOT NULL REFERENCES facts(id),
  issuer_did TEXT NOT NULL,
  reason TEXT,
  sig_b64 TEXT NOT NULL,
  created_at TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE signers (
  did TEXT PRIMARY KEY,
  roles TEXT[] NOT NULL, -- e.g., {'curator','institution'}
  added_by TEXT NOT NULL,
  added_at TIMESTAMPTZ DEFAULT now(),
  revoked_at TIMESTAMPTZ
);

1.2 Star Logic (binary toggle)

  • endorsement.star = binary flag per curator per subject.
  • Active fact: curator starred the playlist.
  • Revoked fact: curator un-starred.
  • Only one active per (issuer_did, subject_id, kind).

1.3 API

  • POST /facts → create new fact; validates signature and role (curator).
  • POST /facts/{id}/revoke → mark revoked (un-star).
  • GET /facts?kind=endorsement.star&origin=feed.ff&type=playlist&ref=pl_123 → list active facts with pagination.
  • GET /facts?since_id=... → delta feed for backfill.
  • GET /signers?role=curator → list
  • POST /signers (admin) → add/roles
  • DELETE /signers/{did} (admin) → revoke
  • Webhook on every insert/update: POST to Cloudflare registry-hook with HMAC header.

1.4 Webhook Payload

{
  "id":123,
  "kind":"endorsement.star",
  "subject":{"origin":"feed.ff","type":"playlist","ref":"pl_123"},
  "issuer_did":"did:key:z6...",
  "status":"active",
  "issued_at":"2025-10-13T03:00:00Z"
}

Header: X-Signature: sha256=<base64(HMAC_SHA256(body, secret))>


2) Cloudflare Workers (Feed-side)

2.1 registry-hook

  • Validates HMAC signature and Date header.
  • Enqueues body to Queue facts-ingest.
  • 204 response if accepted (idempotent via X-Idempotency-Key).

2.2 facts-consumer

Consumes from facts-ingest and writes to KV.

On status = active

KV.put(`star:${playlist_id}`, `${playlist_id}`); // Query playlist has been starred.
KV.put(`star:created:asc:{playlist_created}:${playlist_id}`, `${playlist_id}`); // query starred playlist sorted by timestamp in ascending
KV.put(`star:created:desc:{playlist_created_desc}:${playlist_id}`, `${playlist_id}`); // query starred playlist sorted by timestamp in descending

On status = revoked

KV.delete(`star:${playlist_id}`);
KV.delete(`star:created:asc:{playlist_created}:${playlist_id}`);
KV.delete(`star:created:desc:{playlist_created_desc}:${playlist_id}`);

2.3 Optinal registry-backfill (Cron)

  • Runs every 1 min.
  • Fetches /facts?since_id=<last> from Registry.
  • Applies same materialization rules.
  • Updates high-water mark KV.put('facts_highwater', id).

3) Feed Server Integration

3.1 API

  • GET /playlists?star=true → Lookup star:created:asc:{playlist_created} to list starred playlists by playlist created time
  • GET /playlists/:id → Lookup star:${playlist_id} to check if the playlist has been starred.

Example response:

{
   "dpVersion": "1.0.0",
   "id": "503e271c-7d96-4d80-ae10-ae2ba658d535",
   "slug": "sean-s-feral-file-classics-9962",
   "title": "Sean’s Feral File Classics",
   "star" : true,
   "created": "2025-08-12T09:56:41.713Z",
   "items": []
}

Feed never writes stars; it reflects current KV state.


4) End-to-End Flow

  1. Curator taps Star in app. (Or send from CLI)
  2. App signs fact (Ed25519) and POSTs to Registry.
  3. Registry verifies and inserts fact → webhook fired.
  4. Worker queues + updates KV.
  5. Feed reads reflect immediately.
  6. Curator taps again → revoke fact → KV flag removed.

5) Data Consistency & Recovery

  • facts table = source of truth; Workers are derived view.
  • Backfill job replays facts to heal KV divergence. (Optional, could be defered)
  • Registry ensures at most one active fact per keypair, preventing duplicates.

6) Security

Path Auth Notes
App → Registry JWT + signature (Ed25519) Each star request signed.
Registry → Worker HMAC secret Stored as Cloudflare Secret.
Worker → Registry (backfill) HMAC or mTLS Internal only.

Replay protection: X-Idempotency-Key + evt: KV markers.


7) Deployment & Ops

Component Platform Storage Observability
Registry AWS (EKS/ECS) Postgres Prometheus + Grafana
Workers Cloudflare KV + Queues Cloudflare Dashboards
Feed Cloudflare KV (read-only join) Metrics + Logs

Backups: nightly Postgres pg_dump; KV optional snapshot weekly.


8) Orbit-2 Scope (Kinds)

endorsement.star

  • Authorized role: curator (must exist in signer_whitelist).

  • Body schema:

    {"issued_at": {"type": "string", "format": "date-time"}, "reason": {"type": "string", "maxLength": 512}}
  • Materialization: binary toggle per curator; maintain short stars_recent list.

Future-ready (Orbit-3): new kinds like rights.grant or identity.link reuse same schema; only differ in verifier and KV writer.


9) Testing Plan

Layer Test Type Tools
Registry Unit + API contract tests Go test + Postman collections
Webhook HMAC verification tests Jest / Wrangler test
Workers KV state transitions cf-workers-test lib
End-to-end Simulated curator flow k6 load tests

Target SLOs: POST /facts < 250 ms, webhook dispatch < 50 ms, Feed join < 10 ms.


10) Summary

  • Stars are binary flags per curator/playlist.
  • Registry holds the signed source of truth.
  • Feed Workers mirror via webhook/backfill, storing KV presence only.
  • Feed joins this state in read APIs.
  • Fully Orbit-3 compatible; extensible to rights/licensing kinds.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment