Prepare supervised email-connect SMTP foundation and projection
Some checks failed
CI Smoke / host-smoke (push) Waiting to run
CI Smoke / container-smoke (push) Waiting to run
CCR intake gate / gate (push) Has been cancelled

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a18e2d-f513-7742-b8e7-12af0b744ff3
This commit is contained in:
codex 2026-10-31 12:00:57 +01:00
parent f7c01d4000
commit e77f3989b4
8 changed files with 914 additions and 3 deletions

View file

@ -4,7 +4,9 @@ CCR-2026-0056 proposes one additional reader of the existing platform SMTP entry
RPF-WP-0068 tracks preparation, foundation/binding proof, attended admission and
native consumer delivery. The parent requirement is CSOC-WP-0015-T02.
**Source preparation is complete; execution is not ready.** The dedicated service
**The complete controller is now prepared** in
[the foundation packet](email-connect-smtp-foundation-review-2026-10-31.md).
Its41 SMTP tests pass. **Execution still awaits review/approval.** The dedicated service
account/store/projection have only passed server dry-run. Native binding is not
confirmed, the CCR is proposed, and no new policy or role has been installed.

View file

@ -0,0 +1,128 @@
# Email-connect platform SMTP foundation review
Prepared for CCR-2026-0056 and RPF-WP-0068, supporting CSOC-WP-0015-T02.
This is a concrete review packet, not evidence of live installation.
## Decision scope
Admit email-connect as a third reader of the existing platform SMTP mailbox,
alongside telemetry and Authelia. Create exactly one service account, namespace
SecretStore and ExternalSecret in email-connect. The scoped Kubernetes role reads
the whole exact OpenBao KV record at
`platform/data/workloads/railiance-telemetry/smtp`; ESO projects only SMTP_PASSWORD
into the new Secret's `password` key. OpenBao does not enforce field-level access.
The role has no default policy, a maximum 15-minute lifetime and only the exact
service-account/namespace binding with audience openbao.
This does not change the email-connect deployment or sender, create a caller,
send email, scan a mailbox, activate backup monitoring, rotate the shared password,
or grant suppression authority. Those live obligations remain in CSOC-WP-0015.
The user already selected platform-root, with Bernd as human operator, for replies
and bounces. This new reader requires its own admission review.
The source-backed foundation proposal is:
`sha256:f8da6c831160e1c6354ce54f936809d2d4fb48eb45eb23484dc0bcdfe0bb52f0`
Reproduce it without credentials or network operations:
```bash
python3 /home/worsch/railiance-platform/scripts/email_connect_smtp_foundation.py
```
The digest binds the controller, all three resources including server defaults,
cluster/namespace/application identities, fixed kubeconfig path and admission
digest. The latter binds the CCR's functional scope, policy and seven dependency
files. Changes to execution code or scope require a new proposal. Approval and
native binding evidence do not change functional scope.
## Preconditions and approval boundary
CCR-2026-0056 remains **proposed**, with native binding unconfirmed. The
[credential workflow](credential-change-approval.md) states: “Only `approved`
requests may be applied.” Its shared-reader lane requires platform review;
automatic single-reader approval does not apply. Its client workflow also states:
“The **founder** resolves the State Hub decision” and “Clients do not run
`sync-decision` on their own CCRs.” No review, approval or sync is impersonated here.
The completed packet is ready for that platform/consumer review and founder
decision. After the owner workflow has made the exact CCR approved, the founder
can run the attended command below. The controller creates and verifies the
dedicated service account, then uses canonical confirm-binding itself before
admitting the OpenBao role. The operator need not falsely confirm an absent SA.
## Attended command after approval
Run in the founder's terminal; this is not an agent execution instruction.
The OpenBao relay must be available at port18200 and the fixed primary kubeconfig
must be present. `warden plan` resolves this operation to
openbao-platform-admin-login with one interactive OIDC/MFA login.
```bash
mkdir -m 700 /home/worsch/email-connect-smtp-admission-20261031
BAO_ADDR=http://127.0.0.1:18200 VAULT_ADDR=http://127.0.0.1:18200 \
warden access openbao-platform-admin-login --exec -- \
python3 /home/worsch/railiance-platform/scripts/email_connect_smtp_foundation.py \
--execute \
--expect-digest sha256:f8da6c831160e1c6354ce54f936809d2d4fb48eb45eb23484dc0bcdfe0bb52f0 \
--receipt /home/worsch/email-connect-smtp-admission-20261031/receipt.jsonl
```
The directory creation is intentionally exclusive. If it already exists, inspect
its contents and prior receipts before proceeding; do not remove or overwrite
evidence. Do not run the second command if the first failed. The helper separately
requires a private caller-owned directory and a new receipt path.
The child must be silent because Warden rejects child output. It records a private
mode0600 append-only JSON Lines journal, fsynced before changes. Share only the
last complete receipt and Warden outcome; never login tokens or provider values.
The expected final child status is `foundation_admitted_projection_ready`.
Warden must also report successful session revocation and cleanup.
## What execution verifies
Before mutation, pinned OpenBao and Kubernetes cluster/namespace identities,
platform-admin without root, current deployment identity/generation and absence
of all three new objects and the target Secret are required. Objects are created
exclusively; none is applied over an existing object. No automatic rollback or
retry follows a partial result.
The new service account disables automount. Its new short-lived JWT passes native
TokenReview for its UID, full service-account name and openbao audience. Only then
does canonical confirm-binding run. Guarded admission preserves the shared mailbox,
telemetry/Authelia roles and policies, and existing agent denial. It authenticates
to SMTP using certificate-verified STARTTLS without submitting mail.
Actual workload OpenBao login must have only the dedicated policy and bounded TTL,
read its exact record, and deny metadata, siblings and mutation capabilities.
Wrong service account and wrong audience must fail. The workload token is revoked
and lookup must fail afterward. This does not claim an independently exercised
same-name/wrong-namespace fixture; exact namespace binding is checked in role
metadata and the positive namespace identity is pinned.
Both store and projection must report Ready with exact reviewed specs; the new
Secret must name the new ExternalSecret as controller owner. Secret checks use
PartialObjectMetadata content negotiation through a private Unix-socket proxy,
with no full-object fallback. Secret values are neither requested nor journaled.
Existing application/configuration/old projection fingerprints must remain equal.
If execution fails, retain the journal and inspect its last phase and native state.
There may be a created SA, admitted role or projection even if no final success
was written. Do not rerun blindly, revoke unrelated readers, rotate the mailbox or
roll out the application while outcome is uncertain.
## Validation and remaining work
41 synthetic SMTP tests pass, including12 controller cases and15 admission cases.
They exercise ordering, drift refusal, target collisions, binding refusal, partial
creation, privacy/exclusive journals, interruption, native token capability and
revocation checks, and metadata-only response enforcement/proxy cleanup.
All three resources passed a fresh native server dry-run. A read-only native
metadata query confirmed the target Secret absent. No credential was fetched by
the agent and no production resource was installed.
Evidence: `docs/evidence/email-connect-smtp-foundation-preparation-2026-10-31.json`.
After the attended return, verify receipt and native state, record CCR verification
and rotation inventory, and hand the custody result to CSOC-WP-0015-T02. The sender
rollout, actual delivered-message authentication, inbox access, authoritative return
handling, suppression admission and retention remain separate unfinished work.

View file

@ -0,0 +1,111 @@
{
"schema": "platform.email-connect-smtp-foundation-preparation.v1",
"prepared_at": "2026-10-31T10:59:04.381919+00:00",
"proposal": {
"proposal_digest": "sha256:f8da6c831160e1c6354ce54f936809d2d4fb48eb45eb23484dc0bcdfe0bb52f0",
"proposal": {
"schema": "platform.email-connect-smtp-foundation-proposal.v1",
"foundation": {
"schema": "platform.email-connect-smtp-foundation.v1",
"cluster_uid": "a553c742-0115-43d4-99a4-a5ca56fe0786",
"namespace_uid": "5678c5d7-e4f5-4a62-8f24-1c6e1d906319",
"deployment_uid": "2e98e52a-a2d1-4c52-9ac8-6efbc0a18e72",
"deployment_generation": 74,
"resources": [
{
"apiVersion": "v1",
"automountServiceAccountToken": false,
"kind": "ServiceAccount",
"metadata": {
"name": "email-connect-platform-smtp-eso",
"namespace": "email-connect"
}
},
{
"apiVersion": "external-secrets.io/v1",
"kind": "SecretStore",
"metadata": {
"name": "openbao-email-connect-platform-smtp",
"namespace": "email-connect"
},
"spec": {
"provider": {
"vault": {
"auth": {
"kubernetes": {
"mountPath": "kubernetes",
"role": "email-connect-platform-smtp-eso",
"serviceAccountRef": {
"audiences": [
"openbao"
],
"name": "email-connect-platform-smtp-eso"
}
}
},
"path": "platform",
"server": "http://openbao.openbao.svc:8200",
"version": "v2"
}
}
}
},
{
"apiVersion": "external-secrets.io/v1",
"kind": "ExternalSecret",
"metadata": {
"name": "email-connect-platform-smtp",
"namespace": "email-connect"
},
"spec": {
"data": [
{
"remoteRef": {
"conversionStrategy": "Default",
"decodingStrategy": "None",
"key": "workloads/railiance-telemetry/smtp",
"metadataPolicy": "None",
"property": "SMTP_PASSWORD"
},
"secretKey": "password"
}
],
"refreshInterval": "1h",
"secretStoreRef": {
"kind": "SecretStore",
"name": "openbao-email-connect-platform-smtp"
},
"target": {
"creationPolicy": "Owner",
"deletionPolicy": "Retain",
"name": "email-connect-platform-smtp",
"template": {
"engineVersion": "v2",
"mergePolicy": "Replace",
"type": "Opaque"
}
}
}
}
]
},
"admission_digest": "sha256:14a051abc35d94b9fbfbc8b47f19f9ba7bc95c779ea98fbb9083072386e72160",
"kubeconfig": "/home/worsch/.kube/config-railiance01",
"controller_sha256": "4f1355c0cd48368fa1ae4dcb0138296b3880359329a4ace35dee51783b0ff13f"
},
"ccr_status": "proposed"
},
"validation": {
"smtp_tests_passed": 41,
"smtp_tests_failed": 0,
"server_dry_run_resources": 3,
"native_target_secret_absent": true,
"target_metadata_only_api": true
},
"test_source_sha256": "afdb7877637ced8a1d755bea1b609378b9b74603f3561762ed1dcb38ddd8d82c",
"approved": false,
"executed": false,
"resources_installed": false,
"email_sent": false,
"secrets_read_by_agent": false
}