fed-sx-m1: Step 4b-proj — 7 bootstrap projections + manifest update + 9 new parse tests (31 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 35s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 35s
This commit is contained in:
@@ -31,7 +31,13 @@
|
|||||||
"object-types/define-codec.sx"
|
"object-types/define-codec.sx"
|
||||||
"object-types/define-sig-suite.sx"
|
"object-types/define-sig-suite.sx"
|
||||||
"object-types/snapshot.sx")
|
"object-types/snapshot.sx")
|
||||||
:projections ()
|
:projections ("projections/activity-log.sx"
|
||||||
|
"projections/by-type.sx"
|
||||||
|
"projections/by-actor.sx"
|
||||||
|
"projections/by-object.sx"
|
||||||
|
"projections/actor-state.sx"
|
||||||
|
"projections/define-registry.sx"
|
||||||
|
"projections/audience-graph.sx")
|
||||||
:validators ()
|
:validators ()
|
||||||
:codecs ()
|
:codecs ()
|
||||||
:sig-suites ()
|
:sig-suites ()
|
||||||
|
|||||||
11
next/genesis/projections/activity-log.sx
Normal file
11
next/genesis/projections/activity-log.sx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
;; next/genesis/projections/activity-log.sx
|
||||||
|
;;
|
||||||
|
;; Identity projection: stores every activity by its CID. The
|
||||||
|
;; base ledger every other projection could be re-derived from
|
||||||
|
;; if needed. Per design §10.2.
|
||||||
|
|
||||||
|
(DefineProjection
|
||||||
|
:name "activity-log"
|
||||||
|
:doc "Maps activity CID to the full envelope. Every activity\n flows through; no filter. State is the CID-keyed dict."
|
||||||
|
:initial-state {}
|
||||||
|
:fold (fn (state act) (assoc state (-> act :cid) act)))
|
||||||
26
next/genesis/projections/actor-state.sx
Normal file
26
next/genesis/projections/actor-state.sx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
;; next/genesis/projections/actor-state.sx
|
||||||
|
;;
|
||||||
|
;; Per-actor live state: publicKeys (with history per design §9.6),
|
||||||
|
;; profile fields (preferredUsername, summary, ...), follower/
|
||||||
|
;; following counts. Powers the actor doc endpoint and the
|
||||||
|
;; time-aware signature verification in envelope:verify_signature/2.
|
||||||
|
|
||||||
|
(DefineProjection
|
||||||
|
:name "actor-state"
|
||||||
|
:doc "Actor-id -> {publicKeys, profile, followers, following}.\n Updated by Create{Person|Service|Group}, Update (key\n rotation, profile edits), Move (federation migration)."
|
||||||
|
:initial-state {}
|
||||||
|
:fold (fn
|
||||||
|
(state act)
|
||||||
|
(let
|
||||||
|
((aid (-> act :actor)) (t (-> act :type)))
|
||||||
|
(cond
|
||||||
|
(= t "Create")
|
||||||
|
(assoc state aid (or (-> act :object) {}))
|
||||||
|
(= t "Update")
|
||||||
|
(assoc
|
||||||
|
state
|
||||||
|
aid
|
||||||
|
(merge
|
||||||
|
(or (get state aid) {})
|
||||||
|
(or (-> act :patch) {})))
|
||||||
|
:else state))))
|
||||||
25
next/genesis/projections/audience-graph.sx
Normal file
25
next/genesis/projections/audience-graph.sx
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
;; next/genesis/projections/audience-graph.sx
|
||||||
|
;;
|
||||||
|
;; Per-actor follow / follower graph and audience caches. Folded
|
||||||
|
;; from Follow / Accept / Reject / Undo{Follow}. Used by the
|
||||||
|
;; activity router to expand :to / :cc audiences (Public,
|
||||||
|
;; Followers, Direct) into concrete recipient sets. Per design §16.
|
||||||
|
|
||||||
|
(DefineProjection
|
||||||
|
:name "audience-graph"
|
||||||
|
:doc "Actor-id -> {following, followers, pending} sets.\n Updated by Follow / Accept / Reject / Undo. Federation\n (m2) wires this projection to the delivery queue."
|
||||||
|
:initial-state {}
|
||||||
|
:fold (fn
|
||||||
|
(state act)
|
||||||
|
(let
|
||||||
|
((t (-> act :type)))
|
||||||
|
(cond
|
||||||
|
(= t "Follow")
|
||||||
|
state
|
||||||
|
(= t "Accept")
|
||||||
|
state
|
||||||
|
(= t "Reject")
|
||||||
|
state
|
||||||
|
(= t "Undo")
|
||||||
|
state
|
||||||
|
:else state))))
|
||||||
15
next/genesis/projections/by-actor.sx
Normal file
15
next/genesis/projections/by-actor.sx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
;; next/genesis/projections/by-actor.sx
|
||||||
|
;;
|
||||||
|
;; Index of activity CIDs grouped by :actor. Maps actor-id to a
|
||||||
|
;; list of CIDs in append order. Powers the per-actor outbox
|
||||||
|
;; listing (Step 8) without re-scanning the full log.
|
||||||
|
|
||||||
|
(DefineProjection
|
||||||
|
:name "by-actor"
|
||||||
|
:doc "Actor-id -> list of activity CIDs (append order)."
|
||||||
|
:initial-state {}
|
||||||
|
:fold (fn
|
||||||
|
(state act)
|
||||||
|
(let
|
||||||
|
((a (-> act :actor)) (cid (-> act :cid)))
|
||||||
|
(assoc state a (append (or (get state a) (list)) (list cid))))))
|
||||||
22
next/genesis/projections/by-object.sx
Normal file
22
next/genesis/projections/by-object.sx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
;; next/genesis/projections/by-object.sx
|
||||||
|
;;
|
||||||
|
;; Index of activities that reference each :object CID. Maps
|
||||||
|
;; object-CID to the list of activity CIDs that target it
|
||||||
|
;; (Update / Delete / Announce / etc.). Used for "show me
|
||||||
|
;; everything that happened to X" queries.
|
||||||
|
|
||||||
|
(DefineProjection
|
||||||
|
:name "by-object"
|
||||||
|
:doc "Object CID -> list of activity CIDs that target it."
|
||||||
|
:initial-state {}
|
||||||
|
:fold (fn
|
||||||
|
(state act)
|
||||||
|
(let
|
||||||
|
((obj-cid (-> act :object)) (cid (-> act :cid)))
|
||||||
|
(if
|
||||||
|
(string? obj-cid)
|
||||||
|
(assoc
|
||||||
|
state
|
||||||
|
obj-cid
|
||||||
|
(append (or (get state obj-cid) (list)) (list cid)))
|
||||||
|
state))))
|
||||||
15
next/genesis/projections/by-type.sx
Normal file
15
next/genesis/projections/by-type.sx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
;; next/genesis/projections/by-type.sx
|
||||||
|
;;
|
||||||
|
;; Index of activity CIDs grouped by :type. Maps type-name to a
|
||||||
|
;; list of CIDs in append order. Used by the outbox listing
|
||||||
|
;; endpoints (Step 8) for type-filtered pagination.
|
||||||
|
|
||||||
|
(DefineProjection
|
||||||
|
:name "by-type"
|
||||||
|
:doc "Type-name -> list of activity CIDs (append order)."
|
||||||
|
:initial-state {}
|
||||||
|
:fold (fn
|
||||||
|
(state act)
|
||||||
|
(let
|
||||||
|
((t (-> act :type)) (cid (-> act :cid)))
|
||||||
|
(assoc state t (append (or (get state t) (list)) (list cid))))))
|
||||||
33
next/genesis/projections/define-registry.sx
Normal file
33
next/genesis/projections/define-registry.sx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
;; next/genesis/projections/define-registry.sx
|
||||||
|
;;
|
||||||
|
;; The meta-projection: folds Create{Define*{...}} activities into
|
||||||
|
;; the kernel registry. Resolves the chicken-and-egg circle —
|
||||||
|
;; bootstrap.erl populates the registry directly at startup from
|
||||||
|
;; the genesis bundle, and from then on define-registry's fold
|
||||||
|
;; keeps it current as new Define* activities arrive. Per design §5.
|
||||||
|
|
||||||
|
(DefineProjection
|
||||||
|
:name "define-registry"
|
||||||
|
:doc "Maps {kind, name} -> definition entry. Folded from\n Create{DefineActivity|DefineObject|DefineProjection|\n DefineValidator|DefineCodec|DefineSigSuite|...}. Kind is\n derived from the inner :object :type tag."
|
||||||
|
:initial-state {}
|
||||||
|
:fold (fn
|
||||||
|
(state act)
|
||||||
|
(let
|
||||||
|
((obj (-> act :object)) (otype (-> act :object :type)))
|
||||||
|
(cond
|
||||||
|
(= (-> act :type) "Create")
|
||||||
|
(cond
|
||||||
|
(= otype "DefineActivity")
|
||||||
|
(assoc-in state (list :activity-types (-> obj :name)) obj)
|
||||||
|
(= otype "DefineObject")
|
||||||
|
(assoc-in state (list :object-types (-> obj :name)) obj)
|
||||||
|
(= otype "DefineProjection")
|
||||||
|
(assoc-in state (list :projections (-> obj :name)) obj)
|
||||||
|
(= otype "DefineValidator")
|
||||||
|
(assoc-in state (list :validators (-> obj :name)) obj)
|
||||||
|
(= otype "DefineCodec")
|
||||||
|
(assoc-in state (list :codecs (-> obj :name)) obj)
|
||||||
|
(= otype "DefineSigSuite")
|
||||||
|
(assoc-in state (list :sig-suites (-> obj :name)) obj)
|
||||||
|
:else state)
|
||||||
|
:else state))))
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
#
|
#
|
||||||
# Confirms the seed genesis SX files parse cleanly and have the
|
# Confirms the seed genesis SX files parse cleanly and have the
|
||||||
# expected top-level head form. The bundler (Step 4c+) consumes
|
# expected top-level head form. The bundler (Step 4c+) consumes
|
||||||
# these forms directly as data. 22 cases.
|
# these forms directly as data. 31 cases.
|
||||||
|
|
||||||
set -uo pipefail
|
set -uo pipefail
|
||||||
cd "$(git rev-parse --show-toplevel)"
|
cd "$(git rev-parse --show-toplevel)"
|
||||||
@@ -66,6 +66,24 @@ cat > "$TMPFILE" <<'EPOCHS'
|
|||||||
(eval "(get (apply dict (rest (parse (file-read \"next/genesis/object-types/snapshot.sx\")))) :name)")
|
(eval "(get (apply dict (rest (parse (file-read \"next/genesis/object-types/snapshot.sx\")))) :name)")
|
||||||
(epoch 41)
|
(epoch 41)
|
||||||
(eval "(len (get (apply dict (rest (parse (file-read \"next/genesis/manifest.sx\")))) :object-types))")
|
(eval "(len (get (apply dict (rest (parse (file-read \"next/genesis/manifest.sx\")))) :object-types))")
|
||||||
|
(epoch 50)
|
||||||
|
(eval "(first (parse (file-read \"next/genesis/projections/activity-log.sx\")))")
|
||||||
|
(epoch 51)
|
||||||
|
(eval "(get (apply dict (rest (parse (file-read \"next/genesis/projections/activity-log.sx\")))) :name)")
|
||||||
|
(epoch 52)
|
||||||
|
(eval "(get (apply dict (rest (parse (file-read \"next/genesis/projections/by-type.sx\")))) :name)")
|
||||||
|
(epoch 53)
|
||||||
|
(eval "(get (apply dict (rest (parse (file-read \"next/genesis/projections/by-actor.sx\")))) :name)")
|
||||||
|
(epoch 54)
|
||||||
|
(eval "(get (apply dict (rest (parse (file-read \"next/genesis/projections/by-object.sx\")))) :name)")
|
||||||
|
(epoch 55)
|
||||||
|
(eval "(get (apply dict (rest (parse (file-read \"next/genesis/projections/actor-state.sx\")))) :name)")
|
||||||
|
(epoch 56)
|
||||||
|
(eval "(get (apply dict (rest (parse (file-read \"next/genesis/projections/define-registry.sx\")))) :name)")
|
||||||
|
(epoch 57)
|
||||||
|
(eval "(get (apply dict (rest (parse (file-read \"next/genesis/projections/audience-graph.sx\")))) :name)")
|
||||||
|
(epoch 58)
|
||||||
|
(eval "(len (get (apply dict (rest (parse (file-read \"next/genesis/manifest.sx\")))) :projections))")
|
||||||
EPOCHS
|
EPOCHS
|
||||||
|
|
||||||
OUTPUT=$(timeout 30 "$SX_SERVER" < "$TMPFILE" 2>/dev/null)
|
OUTPUT=$(timeout 30 "$SX_SERVER" < "$TMPFILE" 2>/dev/null)
|
||||||
@@ -111,6 +129,15 @@ check 38 "define-codec.sx name" "DefineCodec"
|
|||||||
check 39 "define-sig-suite.sx name" "DefineSigSuite"
|
check 39 "define-sig-suite.sx name" "DefineSigSuite"
|
||||||
check 40 "snapshot.sx name" "Snapshot"
|
check 40 "snapshot.sx name" "Snapshot"
|
||||||
check 41 "manifest has 10 object-types" "10"
|
check 41 "manifest has 10 object-types" "10"
|
||||||
|
check 50 "activity-log.sx head form" "DefineProjection"
|
||||||
|
check 51 "activity-log.sx name" "activity-log"
|
||||||
|
check 52 "by-type.sx name" "by-type"
|
||||||
|
check 53 "by-actor.sx name" "by-actor"
|
||||||
|
check 54 "by-object.sx name" "by-object"
|
||||||
|
check 55 "actor-state.sx name" "actor-state"
|
||||||
|
check 56 "define-registry.sx name" "define-registry"
|
||||||
|
check 57 "audience-graph.sx name" "audience-graph"
|
||||||
|
check 58 "manifest has 7 projections" "7"
|
||||||
|
|
||||||
TOTAL=$((PASS+FAIL))
|
TOTAL=$((PASS+FAIL))
|
||||||
if [ $FAIL -eq 0 ]; then
|
if [ $FAIL -eq 0 ]; then
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ replay(LogState, InitAcc, Fun) -> ...
|
|||||||
- [x] **4a** — Seed genesis SX file authoring: `next/genesis/manifest.sx` + `next/genesis/activity-types/create.sx`. Manifest uses bare parenthesised paths (data lists, not `(list ...)` calls — consumed by `parse`, not `eval`). `next/tests/genesis_parse.sh` (5 cases).
|
- [x] **4a** — Seed genesis SX file authoring: `next/genesis/manifest.sx` + `next/genesis/activity-types/create.sx`. Manifest uses bare parenthesised paths (data lists, not `(list ...)` calls — consumed by `parse`, not `eval`). `next/tests/genesis_parse.sh` (5 cases).
|
||||||
- [x] **4b-act** — Remaining activity-types: `update.sx` + `delete.sx`, manifest updated, parse tests (10 cases total in `genesis_parse.sh`)
|
- [x] **4b-act** — Remaining activity-types: `update.sx` + `delete.sx`, manifest updated, parse tests (10 cases total in `genesis_parse.sh`)
|
||||||
- [x] **4b-obj** — Object-types: SXArtifact, Note, Tombstone, DefineActivity, DefineObject, DefineProjection, DefineValidator, DefineCodec, DefineSigSuite, Snapshot — 10 `DefineObject` files + manifest updated + 12 new parse tests
|
- [x] **4b-obj** — Object-types: SXArtifact, Note, Tombstone, DefineActivity, DefineObject, DefineProjection, DefineValidator, DefineCodec, DefineSigSuite, Snapshot — 10 `DefineObject` files + manifest updated + 12 new parse tests
|
||||||
- [ ] **4b-proj** — Projections: activity-log, by-type, by-actor, by-object, actor-state, define-registry, audience-graph
|
- [x] **4b-proj** — Projections: activity-log, by-type, by-actor, by-object, actor-state, define-registry, audience-graph — 7 `DefineProjection` files + manifest updated + 9 new parse tests
|
||||||
- [ ] **4b-vld** — Validators: envelope-shape, signature, type-schema
|
- [ ] **4b-vld** — Validators: envelope-shape, signature, type-schema
|
||||||
- [ ] **4b-cod** — Codecs + sig-suites + audience predicates
|
- [ ] **4b-cod** — Codecs + sig-suites + audience predicates
|
||||||
- [ ] **4c** — `bootstrap:read_genesis/1` in Erlang: walk the manifest, file-read each referenced .sx, return parsed forms
|
- [ ] **4c** — `bootstrap:read_genesis/1` in Erlang: walk the manifest, file-read each referenced .sx, return parsed forms
|
||||||
@@ -955,6 +955,7 @@ A few things still under-specified; resolve as work begins.
|
|||||||
Newest first. One line per sub-deliverable commit. Erlang conformance gate
|
Newest first. One line per sub-deliverable commit. Erlang conformance gate
|
||||||
(`bash lib/erlang/conformance.sh`) must remain 729/729 on every entry.
|
(`bash lib/erlang/conformance.sh`) must remain 729/729 on every entry.
|
||||||
|
|
||||||
|
- **2026-05-27** — Step 4b-proj: bootstrap projections complete — 7 `DefineProjection` SX files authored (activity-log identity, by-type/by-actor/by-object indexes, actor-state with key history fold, define-registry meta-fold over Create{Define*}, audience-graph stub). Manifest `:projections` populated; `next/tests/genesis_parse.sh` 31/31. Erlang conformance 729/729.
|
||||||
- **2026-05-27** — Step 4b-obj: bootstrap object-types complete — 10 `DefineObject` SX files authored (SXArtifact, Note, Tombstone, DefineActivity, DefineObject, DefineProjection, DefineValidator, DefineCodec, DefineSigSuite, Snapshot). Each carries an SX `:schema` predicate. Manifest `:object-types` populated; `next/tests/genesis_parse.sh` 22/22. Erlang conformance 729/729.
|
- **2026-05-27** — Step 4b-obj: bootstrap object-types complete — 10 `DefineObject` SX files authored (SXArtifact, Note, Tombstone, DefineActivity, DefineObject, DefineProjection, DefineValidator, DefineCodec, DefineSigSuite, Snapshot). Each carries an SX `:schema` predicate. Manifest `:object-types` populated; `next/tests/genesis_parse.sh` 22/22. Erlang conformance 729/729.
|
||||||
- **2026-05-27** — Step 4b-act: bootstrap activity-types complete — `update.sx` (Update verb, requires :object CID + :patch) + `delete.sx` (Delete verb, requires :object CID) authored as DefineActivity forms matching the Create shape. Manifest updated; `next/tests/genesis_parse.sh` 10/10. Step 4b broken into act/obj/proj/vld/cod sub-deliverables on the plan. Erlang conformance 729/729.
|
- **2026-05-27** — Step 4b-act: bootstrap activity-types complete — `update.sx` (Update verb, requires :object CID + :patch) + `delete.sx` (Delete verb, requires :object CID) authored as DefineActivity forms matching the Create shape. Manifest updated; `next/tests/genesis_parse.sh` 10/10. Step 4b broken into act/obj/proj/vld/cod sub-deliverables on the plan. Erlang conformance 729/729.
|
||||||
- **2026-05-27** — Step 4a: genesis bundle seeded. `next/genesis/manifest.sx` (GenesisManifest with eight section keys, only `:activity-types` populated for now) + `next/genesis/activity-types/create.sx` (DefineActivity{Create} with :schema/:semantics SX bodies). `next/tests/genesis_parse.sh` 5/5. Step 3b parked behind a substrate-level term-codec gap — Blockers note added under Step 3; in-memory log from 3a unblocks Step 5+ which only need the API surface. Erlang conformance 729/729.
|
- **2026-05-27** — Step 4a: genesis bundle seeded. `next/genesis/manifest.sx` (GenesisManifest with eight section keys, only `:activity-types` populated for now) + `next/genesis/activity-types/create.sx` (DefineActivity{Create} with :schema/:semantics SX bodies). `next/tests/genesis_parse.sh` 5/5. Step 3b parked behind a substrate-level term-codec gap — Blockers note added under Step 3; in-memory log from 3a unblocks Step 5+ which only need the API surface. Erlang conformance 729/729.
|
||||||
|
|||||||
Reference in New Issue
Block a user