fed-sx-m2: Step 6c — auto-Accept on Follow ingestion + 9 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 37s

Per design §13.2 the v2 Follow policy is open-world: every
successfully-ingested Follow triggers an Accept publish from the
target actor. Enabled per-Cfg via {auto_accept_follows, true} so
manual-moderation deployments can leave it off; default off.

http_server.erl run_inbox_pipeline gained maybe_auto_accept/3:

  maybe_auto_accept(TargetAtom, Activity, Cfg) ->
      case field(auto_accept_follows, Cfg) of
          true ->
              case envelope:get_field(type, Activity) of
                  {ok, follow} ->
                      Req = [{type, accept}, {object, Activity}],
                      nx_kernel:publish_to(TargetAtom, Req);
                  _ -> ok
              end;
          _ -> ok
      end.

The publish routes through the full outbox pipeline (envelope
construct + HMAC sign + log append + outbox projection broadcast).
When the target's outbox :projections list shares the same
follower_graph projection that inbox broadcasts into, the bilateral
relationship fold-converges automatically — alice.followers = [bob]
and bob.following = [alice], both pending lists clear. No extra
test scaffolding needed because outbox:publish already runs the
broadcast hook from Step 7c.

Bad-sig and non-Follow ingestion short-circuit before the Accept
attempt (the validation pipeline rejects before run_inbox_pipeline's
ok branch fires).

9/9 in next/tests/auto_accept.sh:
  - auto_accept on: alice's outbox tip advances to 1
  - alice's outbox entry has :type = accept
  - follower_graph converges to {alice.followers=[bob],
    bob.following=[alice]}
  - both sides' pending lists clear after the Accept fold
  - auto_accept off (default): outbox stays empty; pending_inbound
    still gets populated from the Step 6b inbox-projection path,
    but alice.followers stays empty until human moderation acts
  - non-Follow ingestion (Create{Note}) with auto_accept on: no
    Accept published
  - bad-sig Follow with auto_accept on: no Accept (sig short-circuit
    in pipeline before maybe_auto_accept runs)

Step 6 fully closed (6a follower_graph projection, 6b inbox -> projection
broadcast wiring, 6c auto-Accept publish).

Conformance 761/761. 89/89 across 7 Step-6-adjacent suites
(inbox, inbox_peer_resolution, follower_graph, follow_lifecycle,
auto_accept, http_publish, nx_kernel_multi).
This commit is contained in:
2026-06-06 22:46:52 +00:00
parent 1d83120918
commit ee8a396ccd
3 changed files with 193 additions and 7 deletions

View File

@@ -450,13 +450,21 @@ tracks the state. `Undo{Follow}` reverses it.
no-op path, bad-sig short-circuit (projection stays clean),
multi-peer accumulation, end-to-end Follow+Accept projection
convergence (Accept fed in via projection:async_fold for v2).
- [ ] **6c** — Auto-Accept publish. On Follow ingestion, the
receiving kernel constructs an `Accept{actor: target, object:
Follow}` envelope, signs it with the target's key, and
publishes via `nx_kernel:publish_to/2`. Per design §13.2 the
policy is open-world (auto-accept every Follow); manual
moderation (held in a pending list, accepted via /admin/) is
v3.
- [x] **6c** — Auto-Accept publish. New `maybe_auto_accept/3` in
`http_server.erl` fires after a successful inbox ingestion if
Cfg carries `{auto_accept_follows, true}` AND the activity's
`:type` is `follow`. The handler constructs an
`Accept{actor: target, object: OriginalFollow}` request and
routes it through `nx_kernel:publish_to/2`, which goes through
the full outbox pipeline (envelope construct + HMAC sign + log
append + outbox projection broadcast). When the target's
outbox `:projections` list includes the same follower_graph
projection the inbox uses, the Accept fold-converges the
bilateral relationship — `alice.followers = [bob]` and
`bob.following = [alice]` — without any test scaffolding.
Default is off; manual-moderation deployments leave the flag
unset. Bad-sig / non-Follow ingestion short-circuits before
the Accept attempt. 9/9 in `auto_accept.sh`.
**Acceptance:** `bash next/tests/follow_lifecycle.sh` passes 14+ cases.
@@ -829,6 +837,22 @@ proceed.
Newest first.
- **2026-06-06** — Step 6c (closes Step 6): auto-Accept publish on
Follow ingestion. New `maybe_auto_accept/3` in `http_server.erl`
fires after successful inbox append + projection broadcast:
if Cfg has `{auto_accept_follows, true}` and the activity is a
`Follow`, construct `[{type, accept}, {object, OriginalFollow}]`
and route through `nx_kernel:publish_to/2`. The publish goes
through the full outbox pipeline (construct + sign + log +
projection broadcast), so when the target's outbox `:projections`
share the same follower_graph projection that inbox broadcasts
into, the bilateral relationship fold-converges automatically
(`alice.followers = [bob]`, `bob.following = [alice]`, both
pending lists clear). Default off; bad-sig / non-Follow
ingestion short-circuits before the Accept attempt. 9/9 in
`auto_accept.sh`. Conformance 761/761. Step 6 fully closed
(6a + 6b + 6c).
- **2026-06-06** — Step 6b: wire follower_graph fold to the
inbox handler. New `broadcast_to_inbox_projections/2` in
`http_server.erl` casts every successfully-ingested activity