Files
stack/docs/reports/security/756-security-review.md
T
veronica f0d2dd9920 docs(W4): stamp kind and status front matter on 104 live documents
Applies the document contract from
docs/plans/2026-08-20_stack-docs-flatten-and-alignment.md section 3, partially:
`kind` and `status` only. `parent` is deliberately held until the flatten in
section 4 lands, so that 127 documents do not have to be re-pointed by hand
when docs/fleet/NORTH_STAR.yaml moves to docs/NORTH_STAR.yaml.

Scope, measured on origin/next at 63069149:

  127 live docs   = all *.md under docs/ minus docs/archive/ minus docs/_old_structure/
  104 stamped     here
   19 held        operator judgement (plan section 9), worklist in the same PR
    3 held        the SUPERSEDED TASKS.md stamps, which cite the moving path
    1 untouched   docs/fleet/FLEET-DOCTRINE.md, already stamped in W1

Kinds applied: 54 guide, 34 record, 9 spec, 6 tracking, 1 projection.
Every row carries a confidence and a one-line rationale in the worklist.

Two collisions with the existing state, both flagged rather than resolved:

1. docs/README.md:150-160 already documents a front-matter convention
   (title/type/audience/status/source_of_truth) with its own allowed values.
   It is applied to 4 of 127 files. Its `status` vocabulary is
   current|draft|deprecated|historical; the new contract's is active|superseded-by.
   The key collides. This commit lets the new contract win and rewrites
   `status: current` to `status: active` on those 4 files, keeping their other
   legacy keys untouched. No code reads any of them: `git grep source_of_truth`
   outside docs/ returns nothing. docs/README.md still prescribes the old
   convention and is an operator row, so it is not edited here.

2. Two of the plan's 20 operator rows are YAML files, not markdown
   (docs/fleet/examples/roster-v2.yaml, docs/openapi-tess.yaml), and the
   contract's front-matter form has no defined meaning for a .yaml document.
   That gap also applies to docs/fleet/NORTH_STAR.yaml, the source of truth
   itself. Raised in the worklist.

A third row from the plan, docs/fleet/north-star.md, no longer exists: W1
renamed it to docs/fleet/FLEET-DOCTRINE.md.

Verification: 104/104 parse with the expected kind and status in front matter;
the check was shown to reject a wrong kind before it was trusted. The diff
removes 4 lines total, all of them `status: current`.
2026-08-20 19:30:25 -05:00

5.3 KiB

kind, status
kind status
record active

Security Review — Issue #756

Scope: final current uncommitted Discord plugin, shared channel contract, gateway ingress, AgentService, and plugin registration delta
Snapshot: plugins/discord/src/index.ts SHA-256 5ee6b6aa4e2ff349f137f76b918d02c1254e12066cb48b136048e57bef36fdb2
Verdict: APPROVE

Final remediation verification

Area Current evidence Result
Attachment confidentiality and integrity Ingress accepts bounded attachment metadata only when URL is HTTPS, query-free, fragment-free, and credential-free. Count, aggregate size, field length, MIME, and finite non-negative size validation apply before dispatch; sizeBytes is signed and retained. Pass
Trusted agent selection Each binding names a required trusted agentConfigId; gateway resolves that config server-side and requires its configured name to equal the binding logical-agent ID. Client/provider input cannot select the agent for Discord ingress. Pass
Privileged operation routing Gateway revalidates the binding and requires the signed conversation identity to match the configured logical agent before approve/stop actions. Paired admin identity and one-time approval checks remain enforced. Pass
Egress containment and delivery Egress requires an aligned message/route, configured parent or exact observed thread target, and cleans response routes after completion, errors, typed-ingress failure, or bounded-map pressure. Pass
Side-effect limits Per guild/authorized-parent/user rolling message and thread limits execute before thread creation or dispatch. Pass

Security controls reviewed

  • Default-deny guild, parent-channel, user, configured pairing, and role checks precede rate consumption and all side effects.
  • Gateway independently enforces Discord service authentication, HMAC integrity, allowlists, binding/role checks, attachment validation, and replay-ID rejection.
  • Thread authorization uses only the Discord thread parent; category parents cannot authorize ingress.
  • Agent-visible attachment references are explicitly labeled untrusted; binary content is not embedded. Persisted attachment name/URL values are redacted.
  • Egress uses deterministic nonces, bounded transient retry, typed terminal errors, and does not send to forged targets.
  • No secrets or message content were added to plugin logs.

Verification evidence

Command Result
pnpm --filter @mosaicstack/discord-plugin test PASS — 44 tests; v8 coverage: 92.18% statements/lines, 86.55% branches, 100% functions
pnpm --filter @mosaicstack/discord-plugin typecheck PASS
pnpm --filter @mosaicstack/types typecheck PASS
pnpm --filter @mosaicstack/gateway typecheck PASS
pnpm --filter @mosaicstack/gateway exec vitest run src/plugin/discord-ingress.security.spec.ts src/agent/__tests__/agent-service-ownership.test.ts PASS — 29 tests
git diff --check PASS

No unresolved critical, high, medium, or low security findings were identified in the reviewed final delta.