docs: gate mail registry and specify external content keys

This commit is contained in:
Della
2026-10-21 16:45:21 -05:00
parent b096a16cce
commit b0844a5ce7
3 changed files with 11 additions and 7 deletions
+2
View File
@@ -5197,3 +5197,5 @@ Before: managed project/thread verbs had no Console conversation area. After: fi
2026-10-21T21:37:07Z | Della mos-1220 / Vikunja 460 phase B cross-review | Before: independent plans Della 191dff32f and Ludwig 4a27b73ac delivered. After: docs/plans/2026-10-21_email-review-by-della.md reviews all 218 Ludwig plan lines, records ten findings, five grafts, six retained strengths, nine disagreements and eleven merged Jason questions. Ludwig review 143415779 read in full after ludwig-0002 arrived; reconciliation records new mail-access action, no agent reroute and correction of Della dataRoot credential example. Original plan unchanged. Planning only, no product/MVP/queue/live change.
2026-10-21T21:43:02Z | Della mos-1223 / Vikunja 460 phase C synthesis | Before: independent plans/reviews complete, Mos selected Della base. After: docs/plans/2026-10-21_email-plan.md merges Ludwig grafts and accepted corrections, with 16 post-v1 rows (eight READY, eight WAIT/optional), eleven deduplicated Jason questions, per-row test paths and explicit Q210 non-v1 scheduling. Original Della plan/review preserved; Ludwig originals remain on their branch. Static checks cover graft/row/question/citation anchors and original blobs. No source code, suite, mailbox, secret file, service, MVP or queue change. Candidate goes to Ludwig before Sage landing/queue handoff, copying Mos.
2026-10-21T21:45:20Z | Della mos-1223 / ludwig-0004 focused corrections | Before: b096a16cc left content-key location implicit and E05 core registration marked ready. After: merged plan 399 lines fixes external configDir secret key/lifecycle namespace outside dataRoot backup/restore, E01 schema and E03 missing/expired-key restore tests, and E05/E06 test-local registry readiness with core kinds.mjs registration gated on approved E01/Q4. Sixteen rows and eleven questions retained; originals unchanged. Focused static checks and queue guard apply, no product/live changes. Reviewer will check changed lines only.
+1
View File
@@ -1435,3 +1435,4 @@ are never rewritten or removed; corrections are new entries.
2026-10-21T21:12:18Z | Della (GPT-6.1-Sol, mos-1213) | Vikunja 460 independent post-v1 email plan, della/email-plan from c3d88840c | 341-line proposal, 13 post-v1 rows, six Jason questions, 42 pinned citation anchors verified. Canonical queue next della: nothing. Planning only, no live mail/service/MVP/queue change; phase B/C with Mos, no Ludwig plan read. Commit and branch push authorized by dispatch.
2026-10-21T21:37:07Z | Della (GPT-6.1-Sol, mos-1220) | Vikunja 460 phase B email cross-review, della/email-plan | Ludwig plan 4a27b73ac and review 143415779 read in full. Cross-review has ten findings and eleven merged questions; original Della plan unchanged. Canonical queue next della: nothing. Static verification only; review push followed by direct della-0002 handoff to both threads under Q210. Phase C base choice remains with Mos.
2026-10-21T21:43:02Z | Della (GPT-6.1-Sol, mos-1223) | Vikunja 460 phase C merged email plan, della/email-plan | Mos-selected base plus Ludwig grafts; original plans/reviews unchanged. Sixteen post-v1 rows, eight READY and eight WAIT/optional; eleven Jason questions. Canonical queue next della: nothing. Docs-only checks. Commit/push then immediate della-0003 handoff to Ludwig/Mos; Sage landing/queueing follows approval.
2026-10-21T21:45:20Z | Della (GPT-6.1-Sol, mos-1223 / ludwig-0004) | merged email plan focused review fixes | External content-key/expiry location and restore tests specified; fake registry work READY, production registry gated on PRD approval/Q4. Merged plan 399 lines, original plans/reviews unchanged. Commit/push and focused Ludwig review before Sage handoff.
+8 -7
View File
@@ -44,7 +44,6 @@ effects (`action_executor.py:30,69,159`) and source category writes (`connectors
`poller.py:359`). Drop direct model calls and content logs (`classifiers/llm.py:79,105,109,123`), replacing
decisions through Q207. Do not import deployment manifests, credential settings, existing accounts or data.
Graph already selects `body` and normalizes HTML (`connectors/m365.py:27,129`), although `body_text` is empty.
Do not describe the prior connector as body-free.
**F4 Stack enforcement:** S `packages/harness/src/tools.mjs:1` already maps typed tools through the runner
socket with broker checks. Its MCP bridge carries no capability (`packages/harness/src/mcp-server.mjs:1,34`).
@@ -188,7 +187,9 @@ attachment instructions trustworthy.
**D7 Storage.** Proposed `<dataRoot>/mail/<business>/` contains encrypted content blobs, SQLite
observation/outbox state, encrypted cursors, local drafts and append-only event evidence. No mail content
enters git or images. Service-only directories are 0700, files 0600. Use scoped keyed fingerprints for private
dedup fields. Separate content keys from provider slots. Keep tokens, delta URLs and authentication errors out
dedup fields. Content keys live at `<configDir>/secrets/mosaic-stack/mail-content/<business>/<key-id>`,
outside dataRoot and its backup set, separate from provider slots, with 0600/no-symlink checks.
Protected key expiry/retirement metadata also stays outside the mail-backup restore domain. Keep tokens, delta URLs and authentication errors out
of ordinary logs. Default durable records hold opaque IDs, state, versions and counts, not bodies, subjects,
recipient lists or attachment names. Content access is explicit and audited.
@@ -315,12 +316,12 @@ to Sage after Ludwig approves this plan, with the v1 path and protected files pr
| Row / gate | Deliverable and dependencies | Acceptance tests (proposed filenames, not run here) |
| --- | --- | --- |
| E01 **post-v1 READY**; Jason: none for draft | PRD addendum draft, source/data/access/service schemas in `docs/prd/`, `packages/mail/schemas/`. Policy activation awaits E02/Q4; content policy awaits E13/Q6. | `packages/mail/tests/schema.test.mjs`: unknown fields, wildcards, secret values, incomplete scopes and mismatched principal/source rejected; disabled schema compatible with v1. Every requirement maps to a row. |
| E01 **post-v1 READY**; Jason: none for draft | PRD addendum draft, source/data/access/service and external content-key location/lifecycle schemas in `docs/prd/`, `packages/mail/schemas/`. Core mail-source registration/policy activation awaits approved addendum/Q4; content policy awaits E13/Q6. | `packages/mail/tests/schema.test.mjs`: unknown fields, wildcards, secret values, incomplete scopes and mismatched principal/source rejected; key location excludes dataRoot/backups, mode/symlink checks, disabled schema compatible with v1. Every requirement maps to a row. |
| E02 **post-v1 WAIT Q4** | Protected slot reader, source-service enrollment/credential lifecycle and separate `mail.access` grant action in `packages/{bus,business}/`. After E01 and approved PRD. No real credential enrollment in this build row. | `packages/bus/tests/mail-grants.test.mjs`, `packages/bus/tests/mail-principal.test.mjs`: non-chief/nonhuman approval, modified targets, expiry, duplicate consume, hand grants, failed issuance undo, manual mode, immediate revoke/in-flight fencing and secret sentinel leakage. Reject repo/dataRoot slots; existing grant tests pass. |
| E03 **post-v1 READY**; Jason: none | Durable scoped ledger, encrypted state, leases, cursor/continuation, outbox and quota accounting in `packages/mail/src/{store,intake,service}.mjs`. After E01. No dependency on live grants. | `packages/mail/tests/intake.test.mjs`, `packages/mail/tests/store.test.mjs`: crash every staging/delivery boundary, concurrent owners, missing/reused Message-ID, source-scoped identity collisions, 1,000/100-MiB quotas, disk/audit failure, restart and zero-connection disabled startup. No skips or duplicate recipient effects. |
| E03 **post-v1 READY**; Jason: none | Durable scoped ledger, encrypted state, leases, cursor/continuation, outbox and quota accounting in `packages/mail/src/{store,intake,service}.mjs`. After E01. No dependency on live grants. | `packages/mail/tests/intake.test.mjs`, `packages/mail/tests/store.test.mjs`: crash every staging/delivery boundary, concurrent owners, missing/reused Message-ID, source-scoped identity collisions, 1,000/100-MiB quotas, disk/audit failure, restart and zero-connection disabled startup. Missing/expired key fails closed; restored backup with expired key returns unavailable, never plaintext. No skips or duplicate recipient effects. |
| E04 **post-v1 READY**; Jason: none, Q7 advisory | Bounded MIME parsing/metadata quarantine in `packages/mail/src/{parse,attachments}.mjs`. After E01; independently of grants. Review license/advisories and exact-pin maintained MIME dependency. | `packages/mail/tests/parse.test.mjs`, `packages/mail/tests/parser-corpus.test.mjs`: multipart, bad charset, missing IDs, S/MIME, 30-MiB input, depth/part/text limits, traversal, hidden HTML, comments, bidi/zero-width display tricks, archive and encrypted attachment quarantine. Fuzz corpus; no expansion/execution/network, no content logs. |
| E05 **post-v1 READY**; Jason: none for fake source | `mail-source` registry/descriptor plus Graph module in `packages/plugins/{src/kinds.mjs,mail-source/m365/}`. After E01/E03/E04; first kind lands with its first module. Q1 selects eventual pilot, not offline work. | `packages/mail/tests/m365.test.mjs`, `packages/mail/tests/source-contract.test.mjs`: fake Graph delta/paging, immutable moves, token/cursor expiry, 401 single refresh, 429/5xx scheduling, restart, denied mailbox, additive-scope check and alias/plus/Bcc provenance. No body-free claim about old code, no source writes. Existing plugin suite passes. |
| E06 **post-v1 READY**; Jason: none, Q7 advisory | IMAP module `packages/plugins/mail-source/imap/`. After E05's shared contract; review/license/exact-pin maintained IMAP dependency. | `packages/mail/tests/imap.test.mjs`: local fake TLS server, certificate denial, selected-folder scope denial, BODY.PEEK/no Seen or STORE/EXPUNGE, IDLE drop/poll fallback, renumbering, UIDVALIDITY/move reconciliation and alias/plus/Bcc/forged-header provenance. Ambiguity holds effects. |
| E05 **post-v1 READY** offline; core registration **WAIT Q4** | Graph descriptor/module in `packages/plugins/mail-source/m365/` against test-local registry `packages/mail/tests/fixtures/mail-source-registry.mjs`. After E01/E03/E04. `packages/plugins/src/kinds.mjs` stays unchanged until E01 addendum approval/Q4; core entry lands together with or after that approved addendum, with its first production module. Q1 selects pilot, not offline work. | `packages/mail/tests/m365.test.mjs`, `packages/mail/tests/source-contract.test.mjs`: fake Graph delta/paging, immutable moves, token/cursor expiry, 401 single refresh, 429/5xx scheduling, restart, denied mailbox, additive-scope check and alias/plus/Bcc provenance. No source writes; test-local registry works with unchanged core registry before approval. Existing plugin suite passes. |
| E06 **post-v1 READY**; Jason: none, Q7 advisory | IMAP module `packages/plugins/mail-source/imap/`. After E05's test-local shared contract; no core registration before approved E01/Q4. Review/license/exact-pin maintained IMAP dependency. | `packages/mail/tests/imap.test.mjs`: local fake TLS server, certificate denial, selected-folder scope denial, BODY.PEEK/no Seen or STORE/EXPUNGE, IDLE drop/poll fallback, renumbering, UIDVALIDITY/move reconciliation and alias/plus/Bcc/forged-header provenance. Ambiguity holds effects. |
| E07 **post-v1 READY**; Jason: none for pure evaluation | Address/rule evaluator `packages/mail/src/{addresses,rules,route}.mjs`. After E01/E03/E04; no org-file activation or delivery privilege. | `packages/mail/tests/rules.test.mjs`, `packages/mail/tests/routing.test.mjs`: port all 36 prior rule cases; bounded operators, rule version/order, previews never execute, history import window, recipient ambiguity, multiple recipients, retired agents, repeated identical mail and no content logs. |
| E08 **post-v1 WAIT Q4/Q5** | Approved org route writer and narrow service delivery API/principal in `packages/{bus,business}/`, `packages/mail/src/delivery.mjs`. After E02/E03/E07. No agent route writer/reroute. | `packages/bus/tests/mail-delivery.test.mjs`, `packages/bus/tests/mail-routes.test.mjs`: exact human approval and versioned changes, fixed actor/business, recipient receipt idempotency, spoofed principal refused, route addition grants no read, revoke before dispatch fences content, no human-input impersonation. |
| E09 **post-v1 WAIT Q4** | Mediated typed/MCP tools, per-message thread view and local drafts in `packages/{bus,harness}/`, `packages/mail/src/access.mjs`. After E02/E08. | `packages/harness/tests/mail-tools.test.mjs`, `packages/mail/tests/access.test.mjs`: same schema/results/refusals on all supported harnesses, separate metadata/body/attachment/draft rights, page caps, thread filtering, cross-business ID denial, revoke/cache races, manual mode, local ack/draft and absence of send/reroute tools. |
@@ -351,7 +352,7 @@ expansion of this add-on.
sources and Stack-local drafts/acknowledgments.
4. **Q4 Service/access grants:** approve protected source-service credential ownership, distinct
per-agent/user `mail.access` approval and the closed mail decision schema? Recommend yes through reviewed
per-agent/user `mail.access` approval, mail-source kind and closed mail decision schema? Recommend yes through reviewed
post-v1 PRD/vocabulary changes, chief/human approval, exact targets/rights/expiry/revoke. New access action
stays a hard wait until the approved PRD explicitly routes it. Provider credential creation remains
distinct.