docs: correct Discord durability boundary

This commit is contained in:
Jason Woltje
2026-08-10 18:51:04 -05:00
parent 11ffe65c97
commit 063de8cd85
5 changed files with 72 additions and 47 deletions
+19 -16
View File
@@ -31,7 +31,9 @@ For an inbound guild message, the current implementation:
The gateway then verifies the HMAC-SHA-256 envelope with `DISCORD_SERVICE_TOKEN`, re-applies the allowlists and binding/role check, requires the conversation ID to match the bound logical agent and channel/thread, and claims the native Discord message ID in a bounded replay cache. The default replay cache is in-process, retains IDs for 15 minutes, and is bounded at 10,000 entries; it is not a durable inbox.
For ordinary chat, the gateway persists and dispatches using `DISCORD_SERVICE_USER_ID`; `DISCORD_SERVICE_TENANT_ID` is used when configured and otherwise ordinary chat falls back to the service user ID as its tenant. Privileged approval and stop additionally require a configured tenant and a paired `mosaicUserId`. The durable session's logical agent must match the binding before approval or stop is accepted. The approval is consumed once against the exact runtime target; the Discord service account is not substituted for the approving paired user.
For ordinary chat, the gateway attempts persistence and dispatch using `DISCORD_SERVICE_USER_ID`; `DISCORD_SERVICE_TENANT_ID` is used when configured and otherwise ordinary chat falls back to the service user ID as its tenant. The Discord external route is not a UUID, while persisted conversation IDs are UUIDs; no current route-to-UUID mapping proves that ordinary Discord persistence succeeds. The gateway may continue dispatch after a persistence/binding failure, so successful live delivery is not durable-history evidence.
Privileged approval and stop additionally require a configured tenant, a paired `mosaicUserId`, and a previously enrolled durable session. The durable session's logical agent must match the binding before approval or stop is accepted. The approval is consumed once against the exact runtime target; the Discord service account is not substituted for the approving paired user.
The trusted `agentConfigId` in each binding is resolved by the gateway. Its provisioned agent name must exactly equal `instanceId`. Discord cannot choose an arbitrary agent, provider, or model in the message payload, and Discord ingress does not use the general routing engine for a new session.
@@ -39,20 +41,20 @@ The trusted `agentConfigId` in each binding is resolved by the gateway. Its prov
The gateway's current plugin factory is in [`plugin.module.ts`](../../../apps/gateway/src/plugin/plugin.module.ts). When `DISCORD_BOT_TOKEN` is present, the following Discord values are required or validated as shown:
| Name | Required/current behavior |
| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DISCORD_BOT_TOKEN` | Enables the Discord plugin and supplies the Discord bot credential. |
| `DISCORD_SERVICE_TOKEN` | Required when the bot is enabled. Authenticates the Socket.IO service handshake and signs/verifies ingress envelopes. Treat as a high-entropy secret. |
| `DISCORD_SERVICE_USER_ID` | Required when the bot is enabled. Provisioned Mosaic service principal used for ordinary Discord persistence and dispatch. |
| `DISCORD_SERVICE_TENANT_ID` | Not required to start ordinary Discord chat, but required for the `/approve` and `/stop <approval>` control path. Use the provisioned tenant for the service boundary. |
| `DISCORD_GATEWAY_URL` | Base gateway URL. The plugin connects to `${DISCORD_GATEWAY_URL}/chat`; the gateway factory default is `http://localhost:14242`. |
| `DISCORD_GUILD_ID` | Optional guild ID used only by the current project-channel provisioning helper. It is not the message authorization allowlist. |
| `DISCORD_ALLOWED_GUILD_IDS` | Required, comma-separated guild IDs. Empty or missing values fail closed during plugin creation. |
| `DISCORD_ALLOWED_CHANNEL_IDS` | Required, comma-separated parent text-channel IDs. Thread messages are checked against their configured parent. |
| `DISCORD_ALLOWED_USER_IDS` | Required, comma-separated Discord user IDs. This allowlist is checked in addition to `pairedUsers`. |
| `DISCORD_INTERACTION_BINDINGS` | Required, non-empty JSON array of configuration-owned bindings. Malformed or empty data fails plugin creation. |
| `DISCORD_MESSAGE_RATE_LIMIT_PER_MINUTE` | Optional positive integer; default is `30` authorized turns per guild/channel/user window. Zero, negative, and non-integer values are rejected. |
| `DISCORD_THREAD_RATE_LIMIT_PER_MINUTE` | Optional positive integer; default is `5` mention-triggered thread routes per guild/channel/user window. Invalid values are rejected. |
| Name | Required/current behavior |
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DISCORD_BOT_TOKEN` | Enables the Discord plugin and supplies the Discord bot credential. |
| `DISCORD_SERVICE_TOKEN` | Required when the bot is enabled. Authenticates the Socket.IO service handshake and signs/verifies ingress envelopes. Treat as a high-entropy secret. |
| `DISCORD_SERVICE_USER_ID` | Required when the bot is enabled. Provisioned Mosaic service principal used for ordinary Discord dispatch and attempted persistence; durable history is not guaranteed. |
| `DISCORD_SERVICE_TENANT_ID` | Not required to start ordinary Discord chat, but required for the `/approve` and `/stop <approval>` control path. Use the provisioned tenant for the service boundary. |
| `DISCORD_GATEWAY_URL` | Base gateway URL. The plugin connects to `${DISCORD_GATEWAY_URL}/chat`; the gateway factory default is `http://localhost:14242`. |
| `DISCORD_GUILD_ID` | Optional guild ID used only by the current project-channel provisioning helper. It is not the message authorization allowlist. |
| `DISCORD_ALLOWED_GUILD_IDS` | Required, comma-separated guild IDs. Empty or missing values fail closed during plugin creation. |
| `DISCORD_ALLOWED_CHANNEL_IDS` | Required, comma-separated parent text-channel IDs. Thread messages are checked against their configured parent. |
| `DISCORD_ALLOWED_USER_IDS` | Required, comma-separated Discord user IDs. This allowlist is checked in addition to `pairedUsers`. |
| `DISCORD_INTERACTION_BINDINGS` | Required, non-empty JSON array of configuration-owned bindings. Malformed or empty data fails plugin creation. |
| `DISCORD_MESSAGE_RATE_LIMIT_PER_MINUTE` | Optional positive integer; default is `30` authorized turns per guild/channel/user window. Zero, negative, and non-integer values are rejected. |
| `DISCORD_THREAD_RATE_LIMIT_PER_MINUTE` | Optional positive integer; default is `5` mention-triggered thread routes per guild/channel/user window. Invalid values are rejected. |
`MOSAIC_AGENT_NAME` and `MOSAIC_AGENT_CONFIG_ID` are not substitutes for a Discord binding. The current Discord binding uses `instanceId` and `agentConfigId` inside `DISCORD_INTERACTION_BINDINGS`; do not invent a different environment-based routing contract.
@@ -114,6 +116,7 @@ The daemon reads its environment from `~/.config/mosaic/gateway/.env` by default
| Unsafe attachment metadata or URL | Gateway rejects the message before acknowledgement/dispatch. Current bounds include at most 10 attachments, HTTPS URLs without credentials, query strings, or fragments, and bounded ID/name/URL/metadata lengths. |
| Missing `DISCORD_SERVICE_TENANT_ID` for approval/stop | The privileged control handler returns without creating or consuming an approval. |
| Agent configuration ID does not resolve or its name differs from `instanceId` | Gateway refuses to create the Discord-bound session. |
| External route cannot be persisted as a UUID conversation | Gateway may still dispatch live output; durable history and restart/resume continuity are not guaranteed and must not be inferred from delivery. |
## Explicitly not current
@@ -128,7 +131,7 @@ The daemon reads its environment from `~/.config/mosaic/gateway/.env` by default
- [`apps/gateway/src/chat/chat.gateway.ts`](../../../apps/gateway/src/chat/chat.gateway.ts) — `/chat` authentication, envelope validation, replay, trusted agent selection, ordinary dispatch, approval, and stop.
- [`apps/gateway/src/chat/chat.gateway-auth.ts`](../../../apps/gateway/src/chat/chat.gateway-auth.ts) — timing-safe service-token and BetterAuth session validation.
- [`apps/gateway/src/plugin/discord-ingress.security.spec.ts`](../../../apps/gateway/src/plugin/discord-ingress.security.spec.ts) — signature, allowlist, replay, attachment, binding, approval, stop, and logical-agent checks.
- [`apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts`](../../../apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts) — the current Discord-to-durable-session control-flow evidence.
- [`apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts`](../../../apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts) — control-flow evidence with explicit durable-session pre-enrollment, not proof of ordinary Discord persistence.
- [`packages/mosaic/src/commands/gateway.ts`](../../../packages/mosaic/src/commands/gateway.ts) and [`gateway/config.ts`](../../../packages/mosaic/src/commands/gateway/config.ts) — verified gateway CLI command names and configuration behavior.
- [Channel protocol architecture](../../DEVELOPER-GUIDE/architecture/channel-protocol.md) — canonical shared-contract and parity boundary.
- [Discord conversation workflow](../../USER-GUIDE/workflows/discord-conversations.md) — end-user behavior.
@@ -32,7 +32,7 @@ The migration from `docs/_old_structure/architecture/channel-protocol.md` is a d
The current source boundaries also distinguish two identities:
1. A channel route carries a configuration-owned logical agent and response destination.
2. The gateway chooses the durable session, provider, model, and runtime session internally.
2. The gateway chooses provider, model, and runtime session internally. Durable-session enrollment is separate and is not proven by the external channel route alone.
A route is therefore not a claim that a channel adapter owns or exposes a harness, provider, model, process, or native runtime-session identity.
@@ -152,15 +152,21 @@ The gateway exposes the `/chat` Socket.IO namespace. A Discord connection authen
This path is intentionally described as compatibility: the gateway receives a signed Discord envelope and reconstructs chat input; it does not currently receive a complete `ChannelIngressDto` from the host registry.
### Persistence and durability boundary
The Discord `conversationId` is an external route string such as `<logical-agent-id>:discord:<channel-or-thread-id>`. Persisted conversations and messages use UUID conversation IDs. No current route-mapping layer was found that resolves the external route to a generated UUID before ordinary Discord writes. The gateway catches persistence/binding failures and may continue dispatch, so live output does not prove durable history or restart/resume continuity.
The focused cross-surface integration test explicitly pre-enrolls a durable session before exercising control flow. It does not prove that a fresh ordinary Discord message creates durable conversation/message rows. Current architecture claims are therefore limited to authenticated routing and live delivery. Durable Discord continuity requires a route-to-UUID mapping, observable persistence failures, ordinary-ingress enrollment where required, and a fresh-database restart test.
### Thread and conversation behavior
| Inbound case | Current route and side effect |
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| Authorized untagged message in a parent channel | Uses the parent channel as the response target; no thread is created. |
| Authorized bot mention in a parent channel | Creates a public thread, or reuses the thread already attached to that message, and routes the response to that thread. |
| Authorized follow-up in an existing thread | Authorizes against the configured parent channel and keeps the existing thread; it does not create a nested thread. |
| `/approve` or `/stop <approval>` | Uses the current parent/thread durable session and does not create a new topic. |
| Requested thread creation fails | Does not dispatch the message, because the requested response target cannot be honored. |
| Inbound case | Current route and side effect |
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| Authorized untagged message in a parent channel | Uses the parent channel as the response target; no thread is created. |
| Authorized bot mention in a parent channel | Creates a public thread, or reuses the thread already attached to that message, and routes the response to that thread. |
| Authorized follow-up in an existing thread | Authorizes against the configured parent channel and keeps the existing thread; it does not create a nested thread. |
| `/approve` or `/stop <approval>` | Uses the current parent/thread route and requires an already enrolled durable session; ordinary chat does not prove enrollment. |
| Requested thread creation fails | Does not dispatch the message, because the requested response target cannot be honored. |
### Discord egress and health
@@ -265,7 +271,7 @@ Discord evidence:
- [`apps/gateway/src/chat/chat.gateway.ts`](../../../apps/gateway/src/chat/chat.gateway.ts) — `/chat` namespace, service/session authentication, signed-envelope reconstruction, trusted binding selection, and raw stream egress.
- [`apps/gateway/src/chat/chat.gateway-auth.ts`](../../../apps/gateway/src/chat/chat.gateway-auth.ts) — Discord service-token and BetterAuth session validation.
- [`apps/gateway/src/plugin/discord-ingress.security.spec.ts`](../../../apps/gateway/src/plugin/discord-ingress.security.spec.ts) — signature, allowlist, replay, binding, attachment, approval, stop, and logical-agent checks.
- [`apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts`](../../../apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts) — focused Discord-to-durable-session integration.
- [`apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts`](../../../apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts) — focused control-flow test with explicit durable-session pre-enrollment; not ordinary persistence evidence.
Hosting and compatibility evidence:
@@ -66,7 +66,7 @@ The Discord adapter derives:
<logical-agent-id>:discord:<response-channel-id>
```
The binding address is derived from the configured guild, parent channel, and logical-agent instance. The route intentionally omits runtime provider, harness, model, process, and native runtime-session identifiers. Gateway durable-session and provider layers own those identities.
The binding address is derived from the configured guild, parent channel, and logical-agent instance. The route intentionally omits runtime provider, harness, model, process, and native runtime-session identifiers. Gateway provider/runtime layers own those identities; durable-session ownership applies only after explicit enrollment and is not implied by the external route.
This is a route-integrity rule, not proof that the gateway has a universal channel session API. A future adapter must derive its route from trusted configuration and native channel/thread identity; it must not accept a caller-selected logical agent or runtime target.
@@ -94,10 +94,10 @@ The gateway-hosted plugin is currently constructed without a direct `ChannelIngr
2. Normal sends emit a signed `message` envelope; approval and stop emit `discord:approve` and `discord:stop` envelopes.
3. The HMAC-SHA-256 signature covers the ordered Discord payload using `DISCORD_SERVICE_TOKEN`.
4. The gateway verifies the service token/signature, allowlists, binding/operation role, stable conversation ID, attachment bounds, and replay key before dispatch.
5. The gateway selects the binding's trusted `agentConfigId`, verifies its name equals the logical-agent instance, and creates/resumes the conversation without generic provider routing for Discord ingress.
5. The gateway selects the binding's trusted `agentConfigId` and verifies its name equals the logical-agent instance. It attempts normal conversation binding/persistence before dispatch, but the external route is not a UUID and no route-to-UUID mapping currently proves durable ordinary-chat history.
6. Agent output currently returns as raw Socket.IO `agent:start`, `agent:text`, and `agent:end` events. The plugin buffers the text and calls its typed Discord egress at stream end.
This compatibility path carries enough normalized identity to preserve current security and routing behavior, but it is not a gateway-produced `ChannelIngressDto`/`ChannelEgressDto` flow through a shared host registry.
This compatibility path carries enough normalized identity to preserve current security and routing behavior, but it is not a gateway-produced `ChannelIngressDto`/`ChannelEgressDto` flow through a shared host registry. The gateway can continue live dispatch after persistence failure; adapter authors must not claim durable continuity until external routes map to UUID conversations and fresh-message restart tests pass.
### Egress and health
@@ -172,7 +172,7 @@ These commands do not require starting Gateway, Discord, Telegram, Matrix, a que
- [`apps/gateway/src/chat/chat.gateway.ts`](../../../apps/gateway/src/chat/chat.gateway.ts) — service/session auth, signed envelope validation, replay, trusted agent selection, and raw stream events.
- [`apps/gateway/src/chat/chat.gateway-auth.ts`](../../../apps/gateway/src/chat/chat.gateway-auth.ts) — timing-safe Discord service-token and BetterAuth session checks.
- [`apps/gateway/src/plugin/discord-ingress.security.spec.ts`](../../../apps/gateway/src/plugin/discord-ingress.security.spec.ts) — gateway security and privileged-operation tests.
- [`apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts`](../../../apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts) — current Discord durable-session integration.
- [`apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts`](../../../apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts) — control-flow test with explicit durable-session pre-enrollment; not ordinary Discord persistence evidence.
- [`apps/gateway/src/plugin/plugin.interface.ts`](../../../apps/gateway/src/plugin/plugin.interface.ts), [`plugin.module.ts`](../../../apps/gateway/src/plugin/plugin.module.ts), and [`plugin.service.ts`](../../../apps/gateway/src/plugin/plugin.service.ts) — lifecycle-only host registry.
- [`plugins/telegram/src/index.ts`](../../../plugins/telegram/src/index.ts) and [`plugins/telegram/package.json`](../../../plugins/telegram/package.json) — raw Telegram behavior and no-test script.
- [Canonical channel protocol architecture](../architecture/channel-protocol.md) — shared contract and explicit current/draft boundary.
@@ -10,12 +10,12 @@ This workflow assumes an administrator has configured the Discord bot, gateway c
## Current versus planned
| Surface | Status | What you can rely on |
| ----------------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| Discord guild messages | **Current** | Authorized messages route to the configured logical agent; parent-channel and thread behavior below is implemented and tested. |
| Telegram | **Not shared-contract parity** | A raw legacy plugin exists, but its current source has no equivalent documented authorization, pairing, route, or focused package tests. |
| Matrix | **Not implemented as a channel workflow** | No current gateway channel adapter and test boundary establishes a Matrix conversation workflow. |
| Shared channel registry | **Not implemented** | The gateway's current registry hosts lifecycle wrappers; it does not provide universal channel routing or health. |
| Surface | Status | What you can rely on |
| ----------------------- | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| Discord guild messages | **Current live routing** | Authorized messages route to the configured logical agent; parent/thread delivery is tested, but ordinary durable history is not guaranteed. |
| Telegram | **Not shared-contract parity** | A raw legacy plugin exists, but its current source has no equivalent documented authorization, pairing, route, or focused package tests. |
| Matrix | **Not implemented as a channel workflow** | No current gateway channel adapter and test boundary establishes a Matrix conversation workflow. |
| Shared channel registry | **Not implemented** | The gateway's current registry hosts lifecycle wrappers; it does not provide universal channel routing or health. |
## Start in a configured parent channel
@@ -59,7 +59,13 @@ The stable conversation address is formed from the configured logical agent, cha
<logical-agent-id>:discord:<response-channel-id>
```
It does not contain Claude, Codex, Pi, OpenCode, a model, a provider, a process, or a native runtime-session ID. The gateway owns the durable session and runtime selection behind that route, so changing the runtime/provider does not require a new Discord address.
It does not contain Claude, Codex, Pi, OpenCode, a model, a provider, a process, or a native runtime-session ID. The gateway owns runtime selection behind that route, so changing the runtime/provider does not require a new Discord address.
### Durability limitation
Treat the current Discord path as **live routing and delivery**, not guaranteed durable conversation history. The Discord conversation address above is an external route string, while persisted conversation/message rows use UUID conversation IDs. No current external-route-to-UUID mapping was found. The gateway can continue dispatching after a persistence/binding failure, so a reply may appear in Discord without durable history or restart/resume continuity.
Do not rely on Discord as the sole record of a conversation. Durable history requires an implementation that maps the external route to a UUID, surfaces persistence failure, and proves fresh-message persistence and restart recovery in an integration test.
## Attachments
@@ -76,7 +82,7 @@ The current Discord text controls are:
/stop <approval>
```
They remain on the current parent/thread durable session and do not create a new topic. Approval and stop are privileged operations: the paired user must have the `admin` role and a provisioned `mosaicUserId`, the gateway must have a tenant configured for the control path, and the durable session must still belong to the bound logical agent. A stop must present the exact approval reference created for that target; approval consumption is one-time.
They remain on the current parent/thread route and do not create a new topic. Approval and stop require an already enrolled durable session; ordinary Discord chat does not prove that enrollment occurred. These are privileged operations: the paired user must have the `admin` role and a provisioned `mosaicUserId`, the gateway must have a tenant configured for the control path, and the enrolled durable session must still belong to the bound logical agent. A stop must present the exact approval reference created for that target; approval consumption is one-time.
If these checks fail, the control operation is denied or produces no successful control result. Do not assume that being able to read a channel grants control authority.
@@ -97,7 +103,7 @@ Check these possibilities with the administrator:
5. The bot is not connected to Discord or the gateway Socket.IO `/chat` namespace.
6. A mentioned topic could not create/fetch its thread.
7. The gateway rejected the signed envelope, route, attachment, or replayed native message ID.
8. `/approve` or `/stop <approval>` was attempted without the required admin pairing, tenant, durable session, or exact approval.
8. `/approve` or `/stop <approval>` was attempted without the required admin pairing, tenant, pre-enrolled durable session, or exact approval.
These failures are intentionally fail-closed; an unauthorized or unverifiable message should not create a thread or agent side effect.
@@ -118,5 +124,5 @@ Those are parity/design gaps, not alternate user workflows.
- [`plugins/discord/src/index.ts`](../../../plugins/discord/src/index.ts) — native Discord routing and delivery implementation.
- [`plugins/discord/src/index.test.ts`](../../../plugins/discord/src/index.test.ts) — parent, mention, existing-thread, authorization, attachment, rate, egress, and health tests.
- [`apps/gateway/src/plugin/discord-ingress.security.spec.ts`](../../../apps/gateway/src/plugin/discord-ingress.security.spec.ts) — gateway signature, replay, binding, attachment, approval, and stop tests.
- [`apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts`](../../../apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts) — current durable-session Discord control-flow test.
- [`apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts`](../../../apps/gateway/src/__tests__/integration/tess-cross-surface.integration.test.ts) — Discord control-flow test with explicit durable-session pre-enrollment; it is not fresh-message persistence evidence.
- [User Guide](../README.md)
+18 -8
View File
@@ -55,11 +55,11 @@ Shared indexes, navigation, audit records, integration review, and final commits
### Final review lanes
| Lane | Assignment | State |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `docs-nav-review` | Independently audit current-page ownership, reachability, relative links, lifecycle labels, and sitemap accuracy. | Launching. |
| `docs-safety-review` | Independently review new current/held pages against source/tests and database/runtime safety constraints. | Launching. |
| `docs-stop-review` | Confirm that remaining unmigrated groups require authority decisions or coupled source/test migrations, and identify any missed safe slice. | Launching. |
| Lane | Assignment | State |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `docs-nav-review` | Independently audit current-page ownership, reachability, relative links, lifecycle labels, and sitemap accuracy. | Complete — findings remediated: artifact indexes added, quarantine links removed, stale sitemap copy corrected, mission label no longer overrides control state. |
| `docs-safety-review` | Independently review new current/held pages against source/tests and database/runtime safety constraints. | Complete — Discord durability blocker found; all affected pages now limit claims to live routing/delivery and disclose missing route-to-UUID persistence evidence. |
| `docs-stop-review` | Confirm that remaining unmigrated groups require authority decisions or coupled source/test migrations, and identify any missed safe slice. | Complete — historical mission bundle migrated; remaining Fleet, Federation, Kanban, Tess/API, and deployment groups are authority- or source/test-coupled. |
## Progress
@@ -84,6 +84,8 @@ Shared indexes, navigation, audit records, integration review, and final commits
- [x] Complete and integrate the four implementation-agent slices after independent scope and evidence review.
- [x] Complete wave 2 audience, testing, RFC, and dashboard migrations and connect every page to its owning index and sitemap.
- [x] Replace the stale sitemap link inventory with fully resolvable current navigation and an authority-gated backlog summary.
- [x] Complete independent navigation, safety, and stop-condition reviews; remediate every autonomous finding.
- [x] Migrate the bounded historical mission archive and repair its two broken sibling links.
## Initial findings
@@ -97,13 +99,14 @@ Shared indexes, navigation, audit records, integration review, and final commits
- `docs/openapi-tess.yaml` parses as OpenAPI 3.1 with 17 paths, but remains a legacy root-level Tess-scoped contract rather than the full API SSOT.
- The baseline `.gitignore` ignored `docs/reports/`, conflicting with the new documentation contract and lint-staged. The blanket rule is now removed so canonical evidence can be tracked normally.
- The scaffold slice adds `USER-GUIDE/README.md`, `ADMIN-GUIDE/README.md`, `ADMIN-GUIDE/security/README.md`, `DEVELOPER-GUIDE/README.md`, `DEVELOPER-GUIDE/architecture/README.md`, and `API/README.md`; legacy pages remain unchanged.
- `SITEMAP.md` now contains 40 resolvable current relative links and no stale legacy targets. Authority-gated Fleet, Federation, Kanban, Tess/API, and deployment groups are summarized without presenting quarantine paths as current navigation.
- `SITEMAP.md` now contains 43 resolvable current relative links and no stale legacy targets. Authority-gated Fleet, Federation, Kanban, Tess/API, and deployment groups are summarized without presenting quarantine paths as current navigation.
- `docs/PERFORMANCE.md` had no live source/test dependency or internal links; it moved unchanged to `docs/reports/qa/p8-003-performance-optimization.md`. The admin index and current sitemap now classify it as historical evidence, not an operator runbook.
- `PRD-TUI_Improvements.md` and `TASKS-TUI_Improvements.md` had no live source/test dependencies beyond their internal relative link; both moved unchanged to `docs/archive/tui/`, and `docs/archive/README.md` labels them historical.
- The empty `docs/QUICKSTART.md` placeholder was replaced by `docs/USER-GUIDE/getting-started/quickstart.md`, based on verified installer, wizard, CLI, and runtime-safety behavior. The page explicitly excludes held PostgreSQL/source-checkout routes.
- The SSO guide now documents Authentik/WorkOS/Keycloak discovery, OIDC callbacks, Keycloak SAML fallback, partial-config failures, and the absence of frontend feature flags. The root guide and stale `.env.example` flags were removed.
- The lease-broker acceptance suites directly consumed two quarantined `docs/architecture/` paths; promoting the protocol, security, mutator-gate, and compaction-revocation contracts to `DEVELOPER-GUIDE/architecture/` and updating those consumers restored the intended contract family without changing runtime behavior.
- The #756 Discord code-review, security-review, and documentation-checklist reports had no source/test consumers and moved byte-identically to their canonical report categories. `docs/reports/README.md` labels their historical evidence boundary.
- Independent safety review found that Discord external route strings are not proven to map to UUID conversation rows. Current pages now promise live routing/delivery only, disclose that persistence can fail while dispatch continues, and require pre-enrollment for privileged durable-session controls.
## Method
@@ -153,5 +156,12 @@ Shared indexes, navigation, audit records, integration review, and final commits
| Lease-broker verification | PASS — safe static/test workflow is current; startup, recovery, mutation, service management, and cleanup remain held |
| Optional egress RFC | PASS — proposal remains draft/non-operative; model and runtime-provider boundaries are separated and candidates are not integrated |
| Web dashboard guide | PASS — current routes, views, chat persistence, and absent project/task creation controls are documented from source/tests |
| Sitemap refresh | PASS — 40/40 relative links resolve; legacy link farm replaced by a non-linked authority-gated backlog summary |
| Canonical link audit | BLOCKED ONLY BY CONTROL DOCS — 273 links scanned, 17 unresolved; all are in maintainer/orchestrator-owned `PRD.md`, `TASKS.md`, or `MISSION-MANIFEST.md` |
| Sitemap refresh | PASS — 43/43 relative links resolve; legacy link farm replaced by a non-linked authority-gated backlog summary |
| Canonical link audit | BLOCKED ONLY BY CONTROL DOCS — 296 links scanned, 17 unresolved; all are in maintainer/orchestrator-owned `PRD.md`, `TASKS.md`, or `MISSION-MANIFEST.md` |
| Navigation review | PASS AFTER REMEDIATION — plan/scratchpad indexes added, current quarantine links removed, lifecycle/status copy aligned |
| Safety review | PASS AFTER REMEDIATION — Discord pages no longer claim unproven ordinary persistence or restart continuity |
| Stop-condition review | AUTONOMOUS COMPLETE — historical mission bundle migrated; remaining groups require authority or coupled source/test work |
| Repository pre-push checks | PASS — `pnpm preflight`, `pnpm typecheck`, `pnpm lint`, and `pnpm format:check` with `DATABASE_URL` unset |
| Root test suite | BLOCKED/FAILED SAFELY — Fleet tests require missing `docs/fleet/`; gateway isolation test inherited a daemon DSN and failed authentication before cleanup DML. Not retried. |
| Focused final tests | PASS — types 71, Discord 44, web 33, focused gateway 32, and lease-broker/mutator acceptance 57; `DATABASE_URL` unset, no services started |
| Historical mission archive | PASS — 11 completed/superseded records moved under `archive/missions/`, indexed, and two broken sibling links repaired |