Every Email table used, seeded or explained; setup card and help #19

Merged
KofTwentyTwo merged 3 commits from feature/tables-populated-defaults into develop 2026-10-14 22:31:48 +00:00
KofTwentyTwo commented 2026-10-14 22:13:45 +00:00 (Migrated from github.com)

Why

Owner requirement: every qbit table is populated, used, and explains itself when empty.

Audit per table

table used seeded empty-state help
email_brand renderer (EmailBrands), API readiness, unsubscribe neutral, non-default, only when no brand exists yes
email_template outbox, renderer, EmailApi.ensureTemplate, EmailBuiltIns no: built-in secure-message created on first use and when the home opens; others registered by qbits yes
email_template_version renderer, versions, actions no: created with templates yes
email_provider dispatcher, service, readiness, home no: host connection (server + secret variable NAMES) yes
email_provider_sender_address service, API no: optional yes
email_message, message_attempt, webhook_inbox, event, suppression dispatcher, inbox processor, tracking no: runtime data yes

Half-wired

  • email_template.owner_qbit: written by EmailApi.ensureTemplate but never read, and the built-in did not set it. Fixed: built-in names qbit-email; messages from a template record its owner as sender_qbit unless the request names one (EmailSetupTest.theTemplatesOwnerQbitIsTheDefaultSender); field is read-only with help.
  • email_provider.default_slot: hidden, non-editable column that enforces one default provider through a unique key; no reader needed. Left as is.
  • email_message.bodyEncrypted and retentionDays do not exist in this repo (no such columns, DDL, or metadata). Body encryption lives in EmailBodyEncryption and retention uses the config's bodyRetentionDays in email_retention. Nothing to fix.

Added

email-defaults.changelog.sql (sql-check preconditions only, -- rollback empty, tested through real Liquibase: second update runs nothing, edits survive, host brand untouched, missing table MARK_RAN, rollback keeps host rows, seeded brand passes contrast checks and changes no rendering); help/qbit-email.yaml + EmailHelp (STAND-IN core#1198); Setup card using EmailApi.readiness and the sender's provider/brand resolution; EmailTablesGuardrailTest; README, UPGRADE.md, CHANGELOG.

Tests

./mvnw verify green (314 tests, checkstyle, JaCoCo). EmailHomePolishTest expectations updated for the new first section.

Not done

  • No seeded provider: it is the host's own connection.
  • No "Create defaults" action: the one seedable row ships in the changelog.
  • Existing built-in templates created earlier keep an empty Owner Qbit.

🤖 Generated with Claude Code

## Why Owner requirement: every qbit table is populated, used, and explains itself when empty. ## Audit per table | table | used | seeded | empty-state help | |---|---|---|---| | email_brand | renderer (EmailBrands), API readiness, unsubscribe | `neutral`, non-default, only when no brand exists | yes | | email_template | outbox, renderer, EmailApi.ensureTemplate, EmailBuiltIns | no: built-in secure-message created on first use and when the home opens; others registered by qbits | yes | | email_template_version | renderer, versions, actions | no: created with templates | yes | | email_provider | dispatcher, service, readiness, home | no: host connection (server + secret variable NAMES) | yes | | email_provider_sender_address | service, API | no: optional | yes | | email_message, message_attempt, webhook_inbox, event, suppression | dispatcher, inbox processor, tracking | no: runtime data | yes | ## Half-wired - `email_template.owner_qbit`: written by `EmailApi.ensureTemplate` but never read, and the built-in did not set it. Fixed: built-in names `qbit-email`; messages from a template record its owner as `sender_qbit` unless the request names one (`EmailSetupTest.theTemplatesOwnerQbitIsTheDefaultSender`); field is read-only with help. - `email_provider.default_slot`: hidden, non-editable column that enforces one default provider through a unique key; no reader needed. Left as is. - `email_message.bodyEncrypted` and `retentionDays` do not exist in this repo (no such columns, DDL, or metadata). Body encryption lives in `EmailBodyEncryption` and retention uses the config's `bodyRetentionDays` in `email_retention`. Nothing to fix. ## Added `email-defaults.changelog.sql` (sql-check preconditions only, `-- rollback empty`, tested through real Liquibase: second update runs nothing, edits survive, host brand untouched, missing table MARK_RAN, rollback keeps host rows, seeded brand passes contrast checks and changes no rendering); `help/qbit-email.yaml` + `EmailHelp` (STAND-IN core#1198); Setup card using `EmailApi.readiness` and the sender's provider/brand resolution; `EmailTablesGuardrailTest`; README, UPGRADE.md, CHANGELOG. ## Tests `./mvnw verify` green (314 tests, checkstyle, JaCoCo). `EmailHomePolishTest` expectations updated for the new first section. ## Not done - No seeded provider: it is the host's own connection. - No "Create defaults" action: the one seedable row ships in the changelog. - Existing built-in templates created earlier keep an empty Owner Qbit. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.