Prepare supervised email-connect SMTP foundation and projection
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a18e2d-f513-7742-b8e7-12af0b744ff3
This commit is contained in:
parent
f7c01d4000
commit
e77f3989b4
8 changed files with 914 additions and 3 deletions
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
128
docs/email-connect-smtp-foundation-review-2026-10-31.md
Normal file
128
docs/email-connect-smtp-foundation-review-2026-10-31.md
Normal 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.
|
||||
|
|
@ -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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue