Skip to content

id(serve): no production caller for ServerConfig — load it in id serve and consume [policy] (pull gate, freshness) + provisioning #5119

Open

Description

@dezren39

Finding

ServerConfig is fully built and parsed — and nothing in production ever loads it. The config half of #798 landed in PR #1801 (merged 39e8410, 2026-10-29): a [policy] table with freshness_window_seconds + pull_policy, [budgets], typed accessors, and startup-failing parse errors. Since then the remainder of #798 (consumption by id serve / sync sessions) has stayed blocked, and a fresh check at main 3b8d3215d808 (2026-11-03T20:15Z, task 2657 resume) shows why: there is still no production consumption point to wire the config into. This issue is that missing integration work, split out of #798 so the block has a name.

Evidence (fresh, main 3b8d3215d808)

  • ServerConfig::load (pkgs/id/src/server_config/mod.rs:178) has no caller outside server_config's own tests (parse.rs). Code search for server_config:: hits only server_config/{mod,parse,provision}.rs and a doc mention in pull_policy.rs.
  • id serve (pkgs/id/src/commands/serve.rs, 3038 lines) has no server-config flag and never references server_config; its resolve_config is the unrelated CLI bootstrap/topic defaults.
  • The only production PullGate construction is event_sync::open_gate() — hard-coded PullPolicy::Open over a NoWorlds membership stub — called at serve.rs:1256 for the node's own event-store sync. event_sync.rs documents why: "there is no world whose membership this store belongs to." Every PullPolicy::Members gate in the tree is in tests (log_sync.rs, event_store/sync.rs, pull_policy.rs). pull_policy.rs:22-23 still states it plainly: "id serve does not read it yet, and no session builds a gate from config."
  • The freshness consumer does not exist in production either: seitan::admit (the only caller of the Freshness window) is referenced only by seitan's own tests and a design spike under doc/. Freshness is constructed in production nowhere outside server_config::freshness() itself, which nothing calls.
  • Provisioned::apply (startup provisioning from the same config) likewise has no production caller — the whole file is dead at runtime, not just the [policy] table.

Scope

  • id serve learns to load a server config (path flag in the existing CLI style; absent = today's behaviour, code defaults everywhere) and fails startup on a parse error, matching ServerConfig::parse's contract.
  • Serve builds its sync pull gate(s) from config.pull_policy(); where a gate's store has no world membership (the event_sync own-store case), the design must say what members means there — refuse-all, refuse-startup-with-a-clear-error, or a membership source — and not silently serve open.
  • The invite-admission path that consumes config.freshness() is wired where seitan admission is actually served, or that consumer is built as part of this work.
  • Startup provisioning (Provisioned::apply) runs from the loaded config.
  • Once landed, id phase-8/platform-completion: freshness-window and pull-policy config are not wired into server/world settings or CLI defaults #798's remainder closes: pull policy + freshness consumed from config, and doc/2026-10-14T_platform_completion/acceptance-brief.md line 76 checked off.

Acceptance criteria

Out of scope

🤖 Agent note · filed

Activity

  1. added
    kind/featureNew feature or capability request
    source/queue-workerFiled or worked by the queue/worker pilot
    priority/normalOrdinary priority (the default)
    queue/queuedHas a queued task in the Supabase agent queue
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    effort/lLarge: multi-day or open-ended; expect staged check-ins
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 3, 2026
  2. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor
  3. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · triaged

    Verification (fresh at main 5b0aeb593c0c9bfcf14c2c9980fee82e484ac7e6, laptop primary)

    Every claim in this issue re-verified; the integration is still entirely missing:

    • ServerConfig::load has no production caller: searching ServerConfig::load / server_config:: across pkgs/id/src hits only server_config/{mod,parse,provision}.rs and a doc mention at pull_policy.rs:22.
    • pkgs/id/src/commands/serve.rs has zero server_config / ServerConfig references. The only production PullGate is crate::event_sync::open_gate() at serve.rs:1284 — event_sync.rs:74 hard-codes PullPolicy::Open over the NoWorlds stub ("local-events").
    • seitan::admit (seitan/admit.rs:155) is referenced only inside seitan/ itself and by server_config's Freshness plumbing; serve runs no seitan admission at all today. Freshness is constructed in production nowhere outside server_config::freshness(), which nothing calls.
    • Provisioned::apply appears only in server_config/mod.rs and server_config/provision.rs — no production caller.
    • pull_policy.rs:22-23 still says it plainly: "id serve does not read it yet, and no session builds a gate from config."
    • doc/2026-10-14T_platform_completion/acceptance-brief.md line 76 (the id phase-8/platform-completion: freshness-window and pull-policy config are not wired into server/world settings or CLI defaults #798 close-out item) is still unchecked.

    (Line drift since filing: the open_gate() call moved from serve.rs:1256 to serve.rs:1284.)

    Scoped slices, in order

    Slice 1 — serve loads the config (foundation; unblocks everything). A server-config path flag on id serve in the existing CLI style; absent flag = today's behaviour exactly (code defaults, no file read). A malformed file fails startup with the ServerConfig::parse error named. Provisioned::apply runs at startup from the loaded config. Covers acceptance criterion 2 and the no-config half of criterion 1. Routed: task 8839 (queue repo-health-code-pilot, small_fix, dedupe key repo-health:v1:fix:developing-today/code:issue:5119 — already queued when this triage enqueued against it; packet preserved in the goal's shift-tools as packet-5119-slice1.json).

    Slice 2 — pull gate from config. Serve builds its sync gate(s) from config.pull_policy() instead of the hard-coded open_gate(). The world-less own-store case needs its decision made in this slice, not discovered in it — recommendation: under pull_policy = "members", a store with no membership source refuses startup with a clear error naming exactly that, rather than silently serving open (which would defeat the configured policy) or silently refusing every pull at runtime (which is undebuggable). Covers acceptance criterion 1 (a members config demonstrably refuses a non-member pull in a test). Depends on slice 1.

    Slice 3 — freshness consumer. Wire config.freshness() into the seitan admission path. Scoping caveat found in triage: serve currently exposes no seitan admission entry point, so this slice includes naming/building that consumer where invite admission is actually served (start from seitan/accept.rs + seitan/admit.rs), not just passing a value. Test at the configured window, not the 5-minute DEFAULT_WINDOW. Covers acceptance criterion 3. Depends on slice 1; independent of slice 2.

    Slice 4 — #798 close-out. Verify #798's remaining acceptance items against slices 1–3, check off acceptance-brief line 76, and close #798 or re-scope its remainder explicitly. Depends on slices 1–3.

    Ordering / blockers

    Slice 1 → (slice 2 ∥ slice 3) → slice 4. No external blockers; the only open decision is slice 2's world-less-store behaviour, with the recommendation above recorded for the implementer — it does not need Drew unless the implementer wants a different default than fail-closed-at-startup.

  4. 1 remaining item

  5. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 3, 2026
  6. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · slice 1b scoped (follow-on to slice 1)

  7. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done (slice 1)

  8. added
    queue/queuedHas a queued task in the Supabase agent queue
    and removed
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/idPackage/app: id (pkgs/ or apps/ in this repo)effort/lLarge: multi-day or open-ended; expect staged check-inskind/featureNew feature or capability requestpriority/normalOrdinary priority (the default)source/queue-workerFiled or worked by the queue/worker pilot

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions