Federation runtime: opt-in configuration
This guide follows current main (3.0.0-rc.1), including controls that an older
installed release may lack. Start with private federation
and review participant compatibility before configuring a deployment.
Stages C/D provide opt-in durable publication and trust enforcement, not a released customer federation product. The wire namespace is unpublished. Do not enable this against customer data before the E and release gates pass. Native Spaces alpha is not used.
Enable deliberately
codifix service run starts no federation tasks by default. An administrator may
set CODIFIX_FEDERATION_CONFIG to an absolute JSON file path. Each service
process runs one configured instance/space. IDs are stable, non-nil UUIDs selected at
enrollment, not regenerated on restart. Use separate PostgreSQL databases for
each instance and the gateway. The general service refuses the gateway role;
use the dedicated executable described below.
An instance configuration has these fields (replace all examples with enrolled identities and an explicitly configured test deployment):
{
"role": "instance",
"space": "00000000-0000-0000-0000-000000000001",
"authority": "00000000-0000-0000-0000-000000000002",
"instance": "00000000-0000-0000-0000-000000000003",
"project": "00000000-0000-0000-0000-000000000004",
"principal": "00000000-0000-0000-0000-000000000005",
"gateway": "https://gateway.federation.example.com",
"token_file": "/run/secrets/codifix-gateway-token",
"receipt_keys": [{
"generation": 1,
"first_sequence": 1,
"public_key": "<independently enrolled gateway audit did:key>"
}]
}The project/principal must exist locally. Starting the worker neither grants remote capability nor enrolls a memory. The first Stage E application API now exposes centrally authenticated local grants, preview/review, retained context and status over this configured runtime. Review opts the selected stream into future content/state updates using only the reviewed evidence references, with explicit standing consent and retry-safe submission. A fresh explicit review is needed to change that evidence. The worker re-resolves each review owner's local policy before processing their queue; it never borrows its configured principal's role. Web/CLI/TUI expose enrollment, review and proposal controls. Trusted in-process APIs remain available; do not expose them without the local authentication/policy boundary.
Multiple projects in one instance (current main)
The existing top-level project, principal and expertise_* fields remain the
primary binding. An optional projects array adds explicit local project bindings;
it does not create additional instances or synchronization cursors:
{
"projects": [{
"project": "00000000-0000-0000-0000-000000000006",
"principal": "00000000-0000-0000-0000-000000000007",
"expertise_principal": "00000000-0000-0000-0000-000000000008",
"expertise_browser": true,
"expertise_output_destinations": ["local_human"]
}]
}Merge this fragment into the instance configuration. Each additional binding has
its own expertise_callers, expertise_output_destinations,
expertise_model_destinations and optional expertise_model; omitted fields use
their safe defaults, never inherit another project's policy. At most 256 projects
including the primary are accepted. Project IDs and configured answering service
identities must be unique. Configure current exact-project permissions and local
space grants separately; listing a project here grants no authority.
All bindings share one ordered instance/space receive stream. Publication checks each originating project's current principal/review owner independently. A single mailbox worker resolves addressed collections locally to exactly one configured project and its dedicated answerer. An ambiguous collection ID is denied rather than answered with another project's knowledge. HTTP paths still select the exact local project. Separate instances/databases remain the isolation boundary between knowledge areas.
Cloud MCP callers need an operator-bound identity and output-destination policy
in that project's expertise_callers, plus separately reviewed collection consent
for that destination. The local_human default does not authorize cloud disclosure.
The gateway configuration is separate. Start only
codifix-federation-gateway /absolute/path/gateway.json, with a dedicated,
pre-provisioned database and a non-owner restricted SQL login. The binary never
runs migrations, the local app, MCP, watchers or model providers. See the
private topology and grants.
{
"space": "00000000-0000-0000-0000-000000000001",
"authority": "00000000-0000-0000-0000-000000000002",
"listen": "127.0.0.1:4055",
"database_url_file": "/run/secrets/gateway-database-url",
"pds": "https://pds.federation.example.com",
"repository": "did:web:space.federation.example.com",
"signing_key": "<enrolled did:key public signing key>",
"token_file": "/run/secrets/codifix-pds-token",
"audit_key_file": "/run/secrets/gateway-audit-key",
"receipt_keys": [{
"generation": 1,
"first_sequence": 1,
"public_key": "<independently enrolled gateway audit did:key>"
}],
"policy": { "external_models": [] },
"credentials": [
{
"instance": "00000000-0000-0000-0000-000000000002",
"token_file": "/run/secrets/codifix-authority-token"
},
{
"instance": "00000000-0000-0000-0000-000000000003",
"token_file": "/run/secrets/codifix-gateway-token"
}
]
}Gateway bearer credentials identify enrolled instances, not human authors.
An authority credential can submit explicit membership records at /v1/accept;
merely listing a member token does not grant Pull or Publish. /v1/pull requires
current Pull membership and returns a fresh nonce-bound signed page with the
contiguous published prefix, independent publication receipts and current policy.
The client supplies after, limit (1–32) and a random UUID nonce.
PDS credentials must never be distributed to participant instances. The listener
is HTTP and requires a reviewed private-network/TLS termination arrangement;
the outbound clients require HTTPS. Prevent all raw PDS/CAR/firehose bypasses.
The isolation harness exercises those
controls; setting this file does not itself install a network or TLS edge.
signing_key is now mandatory: replace the placeholder with the repository's
canonical compressed did:key public signing key, enrolled through a trusted
administration channel together with the repository DID and space. Missing or
malformed keys prevent gateway startup. The public key is not a PDS access token
or private signing key. Do not copy a key from an untrusted record or silently
trust the first key returned by a server. There is no discovery or automatic
key replacement. PDS key changes require an explicitly verified upstream migration.
Gateway receipt keys are independent: append a generation with the exact next
unpublished sequence, distribute trust to receivers and restart with matching
audit secret and replacement tokens. Existing readers/writers are fenced. See
key rollover and recovery.
Token/database URL files must be private (0600 on Unix), 32–4096 bytes; audit keys
are exactly 64 hexadecimal characters representing a 32-byte scalar. Never reuse
a PDS signing key as an audit key. Configuration rejects
unknown fields, invalid IDs and unsafe URL shapes. Endpoints are pinned origins,
not discovered from imported records; redirects and environment proxies are
disabled. Optional gateway_ca_file (instance) and pds_ca_file (gateway) select
a trusted PEM root instead of built-in roots, retaining hostname/certificate
verification. No insecure TLS option exists.
disposable_test_mode: true permits fixture HTTP only in debug builds;
release service builds reject it. No automatic session refresh is implemented:
expired PDS credentials block work until an operator replaces the private token
file, restarts the role and explicitly retries blocked work. Do not skip a blocked
publication to make a later cursor appear healthy.
F1 private expertise opt-in
F1 stays disabled unless the gateway explicitly configures a compatible
expertise_fleet. An instance may separately set expertise_principal
to a separate, internal, project-scoped principal. It must have current project
read/export permissions, the local space's AnswerExpertise grant and an explicit
grant for the reviewed collection. Global roles, global permissions and group
identities are rejected. Merely naming a principal does not grant access.
Provision that identity through the explicitly confirmed
codifix auth expertise-answerer installation command,
not fixture SQL, a service token or the local-owner administrator. The command
creates only local read/export permissions and protected audit. Remote
membership, local space and collection grants remain separate; no worker or
model is enabled automatically.
The optional worker answers queued questions and validates retained answer delivery in independent loops. Ordinary query retrieval is never used; model synthesis is separately disabled unless explicitly configured below. Both loops poll every two seconds and stop with the federation worker lifecycle. Answer work has a 12-second cycle limit within the gateway's 30-second lease, with renewal at ten seconds if still active. Failed/expired attempts remain recoverable through the gateway, subject to the original question deadline. Each read needs a fresh gateway challenge, valid for at most 15 seconds. The origin locks current permissions and source eligibility while checking the exact stored excerpt and authorizing its release. Offline origins therefore cannot authorize new delivery; status reads and exact submission retries never return cached answer bodies.
Approvals contain identifiers/digests, not repeated private payloads. They are
single-use and bound to a live addressed request; gateway restart, expiry and
replay cannot create reusable access. The gateway commit authorizes release, not
proof of physical delivery. An already-authorized in-flight transfer cannot be
recalled, and the two databases do not form one atomic transaction. Existing
24-hour payload expiry still applies; holds do not extend ordinary read access.
This does not activate an existing installation or establish customer readiness.
Use TLS and leave disposable_test_mode false for any later approved internal
installation. Cleartext fixture mode remains prohibited in release builds.
Migration 0052 adds origin-private immutable result storage. The result commits before gateway completion; a new transaction rechecks service authority, reviewed sources and exact citations before sending. Recovery may recompute deterministic excerpts, but cannot replace an already stored result with different bytes or silently substitute newer source versions. No exactly-once provider claim is made: uncertain provider attempts cannot be automatically reinvoked. Stored results retain 24-hour payloads and 30-day metadata; holds do not extend read access. Owning runtimes perform retention maintenance every minute. Adding this option does not create consent, grants or enrollment.
Browser discovery and questions
expertise_browser: true separately enables project/space capability listing,
question preparation/submission and result reads. A current browser session,
project read/export permission and explicit local AskExpertise grant are
required; mutations additionally require CSRF and Origin headers. Read-only mode
currently denies these remote operations. CLI/TUI and MCP require explicit
operator bindings described below; ordinary bearer tokens remain denied.
Prepare accepts request_id, capability (publisher and id UUIDs), the
question (at most 4 KiB UTF-8), and an optional explicitly approved synthesis
model_destination. Synchronize first so the capability is in verified
retained history. It returns the exact QuestionReview, including authenticated
identity, instance, revision, digest, destination and 120-second expiry. Inspect
all fields before confirming. Preparation itself neither persists consent nor
sends the question. Submit accepts { "review": <exact returned review>, "confirmed_digest": <review.digest> }; consent commits before network I/O and
current authority is checked again. Network failure may leave consent committed:
retry that same review/ID before expiry, never silently replace it with a new
question. Stale reviews require deliberate preparation and review again.
Submission returns gateway status metadata only, not an answer or proof of
completed execution. GET capabilities lists advertisements permitted for the
operator-bound caller's output and answer modes with a limit of 1–32.
GET capabilities/{publisher}/{record} returns one complete, currently permitted
advertisement using the same checks. Follow next_after using both
after_publisher and after_record; a filtered empty page can still have a cursor.
GET questions/{id} returns status and, when authorized, the retained answer.
Only the original consenting principal can read it, including when another
principal is an administrator. The 120-second execution deadline does not remove
a completed result: retained reads remain possible within the 24-hour payload
window. Holds preserve storage, not access or permission to restart an expired
question. Each answer read requires fresh origin approval and current local and
gateway authorization; an unavailable origin cannot release a cached answer.
Reads can wait for that approval, and all responses are no-store.
Web/CLI/TUI/MCP support explicit review and private question/result operations. See the experimental OpenAPI contract for paths and request shapes.
Collection review and withdrawal
The same explicit browser opt-in exposes POST collections/draft,
POST collections/activate and POST collections/withdraw. These require
current project read, curate and export permissions, browser CSRF protection and
an explicit local space grant. Activation additionally requires local and observed
gateway Publish and AnswerExpertise capabilities; withdrawal requires Publish.
They do not enroll instances or create the answering service identity's separate
collection grant. Optional synthesis requires explicit reviewed model destinations
and the separate operator configuration described below.
The same operations accept an explicitly bound local-human service token.
expertise_callers in the instance's operator-owned federation JSON is an array
of { "principal": "UUID", "token": "TOKEN-ID-UUID", "output_destination": "local_human" }. IDs are identifiers, not secret token values. Bind the exact
token and principal; replacement tokens require new explicit bindings. At most
64 distinct token bindings are accepted. Current token expiry/revocation and
project permissions are rechecked during operations.
For assistant access, use a separate token and an opaque destination ID such as
company_assistant. The gateway's policy.external_models, the origin's
expertise_output_destinations, and the reviewed collection must all permit that
ID. Instance output destinations default to ["local_human"]; no URL, credential
or executable endpoint belongs in an advertisement. Changing operator policy
requires restarting/reloading the explicitly configured runtime; origin workers
recheck it before answering and before each release.
MCP offers codifix_expertise_discover, codifix_expertise_prepare,
codifix_expertise_ask and codifix_expertise_result. The bridge marks every call
as onward model disclosure, and the service denies local-human credentials on
this path. Submission additionally requires [mcp] read_only = false and exact
review confirmation. The operator, not the assistant, must verify that the token
is installed only in the intended destination. The marker can restrict access
but cannot authorize a destination. Ordinary codifix_query is unchanged.
The dedicated gateway JSON accepts an optional expertise_fleet array of
["INSTANCE-UUID", 3] pairs for every enrolled credential, including authority.
It validates fleet/history compatibility before enabling expertise; absence
keeps expertise disabled. It does not grant membership or collection access.
Watched-agent addressed questions
Addressed ATProto questions are a separate opt-in from the human F1 mailbox.
The gateway requires both the complete expertise_fleet above and a complete
addressed_expertise_fleet containing ["INSTANCE-UUID", 1] for every
configured credential, including the authority. The 1 is the addressed-record
schema, not the publication schema. Enable this only after all participants and
the private PDS proxy have been upgraded; an omitted or partial fleet fails
closed. The proxy must allow the gateway's fenced deleteRecord request so
expired addressed records can be removed after verified signed-key absence.
Participants still receive no PDS credentials or raw repository access.
For each watched Codex or Claude installation, create a separate project-scoped
service token and bind its exact principal and token IDs in the owning
instance's expertise_callers. Set a fixed non-local
output_destination (for example codex_openai or claude_anthropic) and an
agent_ask object containing a positive revision, daily_limit of 1–20 and
an allowed_capabilities list of exact publisher/collection record keys. A
binding is not collection consent: the reviewed collection must separately
allow that requester instance and output destination, and current memberships
must include the expertise capabilities. Use distinct tokens/destinations for
Codex and Claude; never bind an assistant to local_human.
For a split schema-owner/runtime-role installation, the runtime role needs
SELECT, INSERT, UPDATE on federation_agent_expertise_intents and
SELECT, INSERT, UPDATE on federation_agent_expertise_daily. The submit path
uses SELECT ... FOR UPDATE on the intent row, which PostgreSQL denies without
UPDATE privilege even though the handler does not change that row. Grant
only these new tables; no grant on gateway addressed records is implied.
The bundled codifix-federation-expertise skill teaches watched agents to
discover, submit one bounded question and read its cited result. Installing the
skill does not enable the service, expand collection consent or permit a paid
model call. Agent answers are deterministic only. The gateway stores private
addressed bodies for at most 24 hours of participant access; a hold may retain
bytes for audit, and backups or previously delivered copies cannot be recalled.
For an approved TLS installation, expose only the exact /v1/expertise path
through the fixed-upstream gateway edge in addition to the existing routes;
never expose the PDS, raw repository or database interfaces. Customer release
gates remain separate from this default-off internal-use configuration.
The owning gateway runtime cleans expired mailbox payloads/receipts every minute;
instance runtimes clean project-private question/result payloads on the same
interval. Holds are respected; reads enforce TTL independently of cleanup.
Draft accepts a CollectionBlueprint: collection UUID, reviewed name, description
and topics, explicit requesting instance IDs, modes: ["deterministic"] by default,
empty model_destinations by default, explicitly reviewed output_destinations (default
["local_human"], limited by operator policy) and selected canonical
IDs with explicitly selected evidence. The returned draft displays the exact
current memory versions, evidence, authorship, disclosure policy and digest.
Inspect every field: preparing it creates neither standing consent nor publication.
Activate accepts { "draft": <exact returned draft>, "confirmed_digest": <draft.review_digest> }. Changed source versions or altered review bytes fail.
Consent, its audit and the advertisement outbox intent commit together. A 202
with submission: "queued" is local acceptance only, not gateway acceptance or
PDS publication. Retry the exact request after an ambiguous response; do not
silently generate a new review. Only advertisement metadata enters the outbox;
the collection snapshot stays in the origin database.
Withdraw accepts request_id, collection, expected_revision and
confirmed: true. It disables local standing consent while atomically queuing
the withdrawal advertisement. Exact retries retain the same intent. It cannot
recall already delivered or already authorized in-flight bytes. All responses
are no-store. Browser service-grant inspection and reviewed changes are available
after collection inspection. The disposable real-service browser rehearsal covers
these controls; it does not activate an existing installation.
GET collections/{collection}/grants?principal=<UUID> reads a stored local grant
(enabled: null means no matching grant). POST to the same path accepts
principal, enabled and confirmed: true. Current browser read/AuthManage
permissions and a local space grant are required; mutations require CSRF.
Enabling requires an active internal target with no global/group authority and
current project read/export access. Revocation remains possible for a disabled
target. These operations do not configure workers or confer space capabilities.
After an uncertain change, inspect and review current policy again; grants are not
replayable publication intents. All responses are no-store.
GET collections?limit=32 inspects local collection metadata, including withdrawn
heads. Follow next_after with after=<collection UUID>; limits are 1–32 and
pages use UUID ordering, not publication ordering. Pages are not a frozen snapshot.
GET collections/{collection} returns the exact stored head snapshot,
advertisement, reviewer and request ID. Both reads use the same conservative
browser, current read/curate/export and local-grant policy; read-only mode remains
denied. They make no gateway request.
These are local review tools, not retrieval or answer authorization. active
means stored standing consent only: sources may since have changed, permissions
may have been revoked, and publication may still be queued. Detail preserves the
reviewed source bytes even after a newer source version exists or the collection
was withdrawn. Do not use it to answer remote questions. Prepare and activate a
new explicit review to change the collection.
Observe and recover
Optional F1 synthesis
Deterministic excerpts remain the default. Synthesis is a separate tool-free
path; it never uses ordinary query context, source paths or the full-content LLM
audit. Four permissions must intersect: gateway external_models, the
collection's reviewed model_destinations, the requester's
expertise_model_destinations, and the responder's expertise_model.
Onward output consent remains separate, including for deterministic MCP answers.
The instance JSON's expertise_model is absent by default. An example fragment
for a fake-provider rehearsal is:
{"expertise_model":{"provider":"ollama","model":"f1-fake","daily_calls":20,"daily_tokens":800000,"max_output_tokens":800}}This is not a command to start a model or activate a deployment. The automated
rehearsal uses only a temporary loopback fake provider. The exact provider/model
must match the service's existing LLM settings; configure a nonempty stable
cluster.service_id for the attempt journal even when clustering is disabled.
Missing credentials or mismatched model settings fail without substitution.
Advertisements contain provider IDs, never endpoint URLs.
The gateway reserves one call and a conservative 40,000-token allowance before
invocation. Limits are at most 20 calls and 800,000 reserved tokens per responder
per UTC day; output is capped at 800 tokens. Successful calls do not refund the
conservative reservation; unknown usage is never credited back. The serialized
request body plus output-token allowance must fit that reservation. An
eight-second provider timeout stays within the origin execution lease; the
question deadline remains 120 seconds. Redirects are forbidden and provider
responses are bounded at 64 KiB. Environment proxies are disabled for this
restricted path. No tools or fallback providers are offered.
Transport ambiguity becomes uncertain, not an automatic retry. Another question
can incur repeat billing.
Structured responses reference unique one-based indexes into selected reviewed
citations. Codifix reconstructs attribution from those exact citations; invented
indexes and malformed answers produce failed. This checks provenance, not
factual correctness or every real-model prompt-injection behavior. Operational
journals retain identifiers, fingerprints, reservations and fixed outcome
reasons—not prompts, source contents or provider error bodies.
The storage APIs expose separate DeliveryStatus observations:
| Observation | Meaning |
|---|---|
| Queued | Local intent committed; gateway has not accepted it |
| Accepted | Gateway committed authorization, reducer result, order and PDS work |
| Published | Verified exact URI/CID/signed inclusion and independent receipt committed with the published prefix |
| Replicated | One named receiver verified receipts and committed them with inbox, projection and cursor |
intent_status, GatewayStore::status and ReplicaStore::status report their
own observation; none implies every participant has received the record. Frozen
federation_source_changes with prepared = false are also queued work, awaiting
conversion to record envelopes. Operational SQL inspection must be scoped to the
administrator's configured space/instance/project and avoid dumping payloads:
- Source:
federation_source_outboxrecordsattempts,available_at,blocked,last_errorand acceptance receipt.retry_source_workrechecks local authority. - Gateway:
federation_publish_outboxrecords lease, attempt and blocked state;GatewayStore::retry_blockedrestarts the same immutable head after remediation. - Receiver:
federation_replicasrecordssync_failures,retry_at,sync_errorand its applied cursor. Worker warnings are sanitized; they do not include tokens.
Local PostgreSQL work stays usable while the gateway/PDS/peer is unavailable.
Receiver receipts and inbox/projection/cursor commits are atomic. A gap or corrupt batch
does not advance the cursor. An authorized recovery path can call
InstanceSync::resynchronize to fetch a complete paginated history and atomically
rebuild the projection, but it cannot truncate or fork the known prefix. This
low-level API requires the caller to recheck local read permission, just like
catch_up and snapshot reads; the normal cycle does this itself.
Reference replay is O(history), with a 16 MiB full-resync limit and 32 records per page. Backoff and source/PDS retry budgets are durable; exhausted or invalid work needs intervention. This is not a scalable checkpoint implementation or a complete disaster-recovery system. Revocation denies later gateway access/publication but does not erase offline copies. Administrators and admitted recipients can read shared plaintext. Actual deployment security review and complete production backup recovery remain gates; the reducer's Lean proofs do not prove these runtime or operational guarantees.
Use and retain shared data deliberately
Imports stay separate from automatic local search, curation and model pipelines.
The guarded InstanceSync::retained_context API requires current local read
permission and a space grant; it excludes current tombstones/archived streams and
keeps reviewed evidence and origin/author/version attribution as untrusted data.
answer_shared additionally intersects local export permission, configured local
provider IDs, every selected record's frozen publication policy, and fresh signed
gateway policy/Pull access. All provider sets default to deny; offline/revoked
calls fail before invoking a provider. No commercial provider is enabled by this
configuration. Shared-context forwarding is distinct from the optional F1
tool-free synthesis workflow above.
An authority token may POST {"action":"hold","reason":"<owner decision>"},
release_hold, or request_erasure to /v1/retention. These append operational
decisions. physical_erasure_authorized is always false: releasing a hold does
not approve deleting protocol history, pending work, backups or other people's
copies. Immutable guards protect retained records, receipts, reviews and intents.
Actual legal retention periods and whole-space decommission require a separately
approved policy/procedure. Revocation cannot recall already delivered bytes;
already-authorized in-flight operations may finish.
Repository trust check and its limits
Before PDS work is acknowledged, the gateway obtains a full CAR from the fixed
PDS getRepo endpoint and checks SHA-256 block CIDs, the canonical v3 commit,
enrolled DID, low-S secp256k1/P-256 signature, complete canonical MST and the exact
publication key/bytes. No URLs are derived from DIDs or record contents. Matching
JSON alone, invalid signatures and oversized/incomplete proofs cannot advance
the published state. Bad proofs persist as invalid-receipt failures and require
operator remediation; there is no unsigned fallback or automatic overwrite.
This bounded implementation accepts one-root full CARs up to 16 MiB, 32,768 physical blocks, 1 MiB per framed block, 4 KiB commit/header, 8,192 records/nodes and 64 tree edges. All blocks must have canonical DAG-CBOR/SHA-256 CIDs. Duplicate blocks and arbitrary block order are supported; incremental CARs, blobs and native Spaces are not this verification contract. Verification/downloads are serialized per publisher and CPU work runs outside the async I/O executor. Full snapshot verification costs O(repository) per publication and is not yet the scalable production synchronization path. Hitting a limit blocks work; do not raise limits or bypass verification without assessment.
The proof establishes inclusion in a signed snapshot, not factual correctness,
current membership, history freshness or a transferable human-review receipt.
The five-minute future-revision tolerance is a clock sanity check, not replay
defense; application order still comes from the transactional gateway sequence.
Membership/revocation checks remain in the gateway domain. Receivers now verify
independent audit receipts, their chain, key windows and fresh signed pages.
Retained receipts are re-verified on offline snapshot reads. See the
full security contract.
Previously persisted Published observations are not retroactively certified;
do not treat pre-D state as cryptographic evidence or promote it to a customer
deployment without a reviewed verification/migration procedure.
For synthetic verification, see the PDS harness and the transaction contract.