Layer declaration (gate-house). INTENT.md now carries the declaration in its own voice with layer.yaml as the machine-readable form, adapted from ops-warden's reference. railiance-platform is Staff: operating OpenBao is not a claim to the Tooling layer, because §4 is explicit that no operator-of-third-party-Tooling shape exists and that someone running it stays a declared gap. Six direct Tooling contacts are mapped by capability rather than by file — one §5.2 conduit, one §5.1 diagnostic, four §5.3 gaps with intended owners and review dates — and the uncatalogued contacts are listed so the check is total. We are PEP-shaped and the unreachable-engine stance map is NOT published; that is recorded as an open obligation to build against v0.8, not left silent. Placement admission. canned-prompts was added as a PostgresConsumer on platform-pg-2 in rapp-postgres 1b68b4c without a placement owner here, which is exactly the cross-repo drift the assurance check exists to catch; the check had been failing on it. Registered with its real boundary evidence, corrected the stale test expectation that pinned the overflow cell at one consumer, and updated the SCOPE occupancy line to 2/4. Also records owner input received today: key-cape's issuer view on CCR-2026-0020's presenting actor, and their confirmation that codex-railiance-platform correctly stays tenant:coulomb, so the flagged T02 discrepancy is closed as not-a-defect. The whynot-design npm field is NOT changed. Two dated live receipts here name NPM_AUTH_TOKEN as the field, including an attended founder fetch; that is recorded against the counterparty claim rather than either side being flipped before the session settles it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WLUjpv3ssxNRAEPPgLFnEB Assistant: claude-code Assistant-Model: opus Assistant-Process: 1275505@bnt-lap001 Assistant-Session: 97265baa-f08f-4032-b290-a1e2965a69c5
538 lines
20 KiB
Markdown
538 lines
20 KiB
Markdown
# Workload KV Access Lanes
|
|
|
|
This document records concrete OpenBao workload KV paths that external access
|
|
front doors can reference without storing or vending secret values themselves.
|
|
The first lane is for ops-warden `warden access --fetch` / `--exec`.
|
|
|
|
## Safety Rules
|
|
|
|
- Do not put secret values in Git, State Hub, chat, prompts, workplans, or logs.
|
|
- Store only non-secret pointers here: path, field name, policy name, auth role,
|
|
flex-auth reference, and verification status.
|
|
- ops-warden may proxy a read as the caller, but it must not hold the returned
|
|
value beyond the caller-requested fetch/exec process.
|
|
- Live writes require an approved OpenBao/operator path and attended handling
|
|
of the secret value.
|
|
|
|
## whynot-design npm Publish Token
|
|
|
|
Ops-warden original request:
|
|
`551031d1-335e-4db8-9535-820fea52d0a3`
|
|
|
|
Ops-warden batch follow-up:
|
|
`fe5b1696-8956-4bd5-9d6f-dbde1901a076`
|
|
|
|
| Item | Value |
|
|
| --- | --- |
|
|
| ops-warden catalog id | `whynot-design-npm-publish` |
|
|
| Tenant/org | `coulomb` |
|
|
| Workload/project | `whynot-design` |
|
|
| KV mount | `platform` |
|
|
| OpenBao CLI path | `platform/workloads/coulomb/whynot-design/npm-publish` |
|
|
| Secret field | `NPM_AUTH_TOKEN` |
|
|
| Front-door readiness | `active`, `resolvable=true` in ops-warden |
|
|
| Read policy | `workload-kv-read-whynot-design-npm-publish` |
|
|
| Policy file | `openbao/policies/workload-kv-read-whynot-design-npm-publish.hcl` |
|
|
| OIDC auth mount | `netkingdom` |
|
|
| OIDC role | `whynot-design-workload-kv-read` |
|
|
| OIDC callback URIs | `https://bao.coulomb.social/ui/vault/auth/netkingdom/oidc/callback`, `http://localhost:8250/oidc/callback`, `http://127.0.0.1:8250/oidc/callback` |
|
|
| Kubernetes auth role | `whynot-design-workload-kv-read` if an in-cluster service account consumes this lane |
|
|
| flex-auth ref | `secret.read:whynot-design` if tenant policy requires pre-approval |
|
|
|
|
Expected caller login shape:
|
|
|
|
```bash
|
|
bao login -method=oidc -path=netkingdom role=whynot-design-workload-kv-read
|
|
```
|
|
|
|
Expected OpenBao fetch shape:
|
|
|
|
```bash
|
|
bao kv get -field=NPM_AUTH_TOKEN platform/workloads/coulomb/whynot-design/npm-publish
|
|
```
|
|
|
|
Expected ops-warden exec shape after activation:
|
|
|
|
```bash
|
|
warden access whynot-design-npm-publish --exec -- npm publish
|
|
```
|
|
|
|
Ops-warden confirmed activation in State Hub message
|
|
`f76d3a9e-a98f-4081-885d-b79d94312699`: selector
|
|
`whynot-design-npm-publish` is active, resolvable, and wired to this
|
|
caller-scoped lane. The sibling lanes `issue-core-ingestion-api-key` and
|
|
`openrouter-llm-connect` remain draft and are tracked separately by
|
|
`RAILIANCE-WP-0009` and `RAILIANCE-WP-0010`.
|
|
|
|
> **Field name contested, 2026-09-09 — do not change this on either side yet.**
|
|
> secrets-engine states the KV field is `npm_token` and that `NPM_AUTH_TOKEN` is
|
|
> only the environment variable their publication-scope policy injects;
|
|
> ops-warden has already corrected their catalog and playbook on that statement.
|
|
> This repository holds two dated live receipts naming `NPM_AUTH_TOKEN` as the
|
|
> OpenBao **field**, in `CCR-2026-0001`: a field-presence check on
|
|
> 2026-06-28T10:37:42Z, and an attended fetch by the founder on
|
|
> 2026-06-28T15:22:29Z that exited successfully with output to `/dev/null` — a
|
|
> `-field=` fetch that exits zero means that field exists. Both records can be
|
|
> true if the path carries **both** fields. Q2 of the attended session
|
|
> (`docs/openbao-open-questions-session.md`) enumerates the actual field names
|
|
> and settles it. Until then this table stays as written, because it is the side
|
|
> backed by receipts.
|
|
|
|
The fetch command returns the secret value to the authenticated caller. Run it
|
|
only in an attended shell or through a process that consumes the value without
|
|
logging it.
|
|
|
|
## OpenBao Policy
|
|
|
|
The source policy grants only:
|
|
|
|
```text
|
|
read platform/data/workloads/coulomb/whynot-design/npm-publish
|
|
read platform/metadata/workloads/coulomb/whynot-design/npm-publish
|
|
```
|
|
|
|
It does not grant write, delete, patch, sudo, auth, sibling workload, or parent
|
|
list capabilities.
|
|
|
|
Dry-run the policy apply path:
|
|
|
|
```bash
|
|
make openbao-workload-kv-lanes-dry-run
|
|
```
|
|
|
|
Apply the policy with an approved platform-admin/operator token:
|
|
|
|
```bash
|
|
OPENBAO_TOKEN_FILE=~/.local/openbao/platform-admin.token \
|
|
make openbao-configure-workload-kv-lanes
|
|
```
|
|
|
|
If the OpenBao pod has an approved token-helper session, use:
|
|
|
|
```bash
|
|
make openbao-configure-workload-kv-lanes OPENBAO_WORKLOAD_KV_ARGS=--use-token-helper
|
|
```
|
|
|
|
Do not paste the token into shell history or logs. The helper reads a token
|
|
from `OPENBAO_TOKEN_FILE` or an interactive hidden prompt unless
|
|
`--use-token-helper` is set, and passes it to OpenBao through stdin.
|
|
|
|
## Auth Role
|
|
|
|
The intended OpenBao OIDC role is:
|
|
|
|
```text
|
|
auth/netkingdom/role/whynot-design-workload-kv-read
|
|
```
|
|
|
|
The role must attach only:
|
|
|
|
```text
|
|
workload-kv-read-whynot-design-npm-publish
|
|
```
|
|
|
|
The OIDC role must include the browser and local CLI callback URIs accepted by
|
|
OpenBao:
|
|
|
|
```text
|
|
https://bao.coulomb.social/ui/vault/auth/netkingdom/oidc/callback
|
|
http://localhost:8250/oidc/callback
|
|
http://127.0.0.1:8250/oidc/callback
|
|
```
|
|
|
|
The role must request these OIDC scopes so KeyCape emits the group claim OpenBao
|
|
checks:
|
|
|
|
```text
|
|
openid
|
|
profile
|
|
email
|
|
groups
|
|
```
|
|
|
|
The whynot-design pilot claim is confirmed as `groups=whynot-design`. Before
|
|
applying any changed role, re-confirm the KeyCape/NetKingdom claim that
|
|
identifies the whynot-design caller. The role must bind to that claim; do not
|
|
create an unbounded OIDC role that grants this policy to every OIDC user.
|
|
|
|
If the consumer is an in-cluster service account instead of an OIDC caller, use
|
|
Kubernetes auth with the same role name and bind only the approved namespace
|
|
and service account.
|
|
|
|
## Secret Provisioning
|
|
|
|
An approved operator must create or confirm the secret with:
|
|
|
|
```text
|
|
path: platform/workloads/coulomb/whynot-design/npm-publish
|
|
field: NPM_AUTH_TOKEN
|
|
```
|
|
|
|
In the OpenBao UI, open the `platform` KV engine and create or edit the secret
|
|
at:
|
|
|
|
```text
|
|
workloads/coulomb/whynot-design/npm-publish
|
|
```
|
|
|
|
For policies and API checks, the same KV-v2 secret is addressed as:
|
|
|
|
```text
|
|
platform/data/workloads/coulomb/whynot-design/npm-publish
|
|
platform/metadata/workloads/coulomb/whynot-design/npm-publish
|
|
```
|
|
|
|
The OpenBao UI path does not include the `data/` or `metadata/` segment. Those
|
|
segments are the KV-v2 API and ACL policy paths.
|
|
|
|
The value must be entered directly through OpenBao/operator custody. Record only
|
|
non-secret evidence: actor, timestamp, path, field name, policy name, and
|
|
verification result.
|
|
|
|
## Verification
|
|
|
|
Positive verification:
|
|
|
|
1. Authenticate as the whynot-design caller using the approved OIDC or
|
|
Kubernetes auth role.
|
|
2. Fetch the field in an attended session or through `warden access --exec`.
|
|
3. Record only that the fetch succeeded; do not record the value.
|
|
|
|
Safe attended command shape before the dedicated ops-warden catalog id is
|
|
activated:
|
|
|
|
```bash
|
|
set +x
|
|
bao login -method=oidc -path=netkingdom role=whynot-design-workload-kv-read
|
|
warden access "npm token" \
|
|
--path platform/workloads/coulomb/whynot-design/npm-publish \
|
|
--field NPM_AUTH_TOKEN \
|
|
--no-policy \
|
|
--exec -- sh -lc 'test -n "$NPM_AUTH_TOKEN"'
|
|
```
|
|
|
|
Use `--no-policy` only while the local ops-warden config reports
|
|
`policy.enabled=false`; remove it once the flex-auth gate is enforced. If login
|
|
fails with `groups claim not found`, the OpenBao role is missing the `groups`
|
|
OIDC scope and must be corrected before retrying.
|
|
|
|
Negative verification:
|
|
|
|
1. Authenticate as a non-whynot identity.
|
|
2. Confirm the same field read is denied.
|
|
3. Record the non-secret OpenBao audit request ids or timestamps for the
|
|
allowed and denied attempts.
|
|
|
|
## ops-warden Handoff
|
|
|
|
Send ops-warden only these pointers:
|
|
|
|
```text
|
|
catalog id: whynot-design-npm-publish
|
|
mount: platform
|
|
path: platform/workloads/coulomb/whynot-design/npm-publish
|
|
field: NPM_AUTH_TOKEN
|
|
oidc login: bao login -method=oidc -path=netkingdom role=whynot-design-workload-kv-read
|
|
policy: workload-kv-read-whynot-design-npm-publish
|
|
policy file: openbao/policies/workload-kv-read-whynot-design-npm-publish.hcl
|
|
flex-auth ref: secret.read:whynot-design, if tenant policy requires it
|
|
runbook: docs/workload-kv-access-lanes.md
|
|
```
|
|
|
|
Until positive and negative caller verification are complete, ops-warden should
|
|
keep the catalog entry in `applied-pending-verify`/non-active state with
|
|
`resolvable=false`.
|
|
|
|
## reuse-surface hub runtime secrets (`CCR-2026-0005`)
|
|
|
|
Production federation hub at `https://reuse.coulomb.social`. Runtime secrets
|
|
are OpenBao-custodied and delivered to Railiance01 via External Secrets.
|
|
|
|
| Item | Value |
|
|
| --- | --- |
|
|
| CCR | `CCR-2026-0005-reuse-surface-runtime-secrets-lane` |
|
|
| KV mount | `platform` |
|
|
| OpenBao CLI path | `platform/workloads/reuse/reuse-surface/runtime-secrets` |
|
|
| Fields | `REUSE_SURFACE_TOKEN`, `REUSE_SURFACE_FORGEJO_WEBHOOK_SECRET` |
|
|
| Read policy | `workload-kv-read-reuse-surface-runtime` |
|
|
| Policy file | `openbao/policies/workload-kv-read-reuse-surface-runtime.hcl` |
|
|
| K8s auth role | `reuse-surface-runtime-eso`, SA `reuse/reuse-surface-eso`, audience `openbao` |
|
|
| Primary consumer | ExternalSecret `reuse/reuse-surface-runtime` → Secret `reuse-surface-env` (Railiance01, 1h refresh) |
|
|
| ClusterSecretStore | `openbao-reuse` (Kubernetes auth to private railiance01 OpenBao, namespace `reuse`) |
|
|
| ops-warden catalog | `reuse-surface-hub-write-token` |
|
|
|
|
RPF-WP-0037 replaced static ESO authentication without rotating workload values.
|
|
ESO uses the separate `workload-kv-read-reuse-surface-runtime-eso` policy: exact
|
|
data read and self-token lifecycle only. The caller-facing policy/catalog above
|
|
remains separate. See `docs/eso-auth-recovery.md`.
|
|
|
|
Fetch hub write token (do not log the value):
|
|
|
|
```bash
|
|
export REUSE_SURFACE_TOKEN=$(
|
|
bao kv get -field=REUSE_SURFACE_TOKEN \
|
|
platform/workloads/reuse/reuse-surface/runtime-secrets
|
|
)
|
|
```
|
|
|
|
Webhook HMAC (dual consumer — Forgejo org webhook must match):
|
|
|
|
```bash
|
|
bao kv get -field=REUSE_SURFACE_FORGEJO_WEBHOOK_SECRET \
|
|
platform/workloads/reuse/reuse-surface/runtime-secrets
|
|
```
|
|
|
|
Or via ops-warden:
|
|
|
|
```bash
|
|
warden access reuse-surface-hub-write-token --fetch REUSE_SURFACE_TOKEN
|
|
```
|
|
|
|
**Consumer facts the generated plan does not cover:**
|
|
|
|
- `REUSE_SURFACE_FORGEJO_WEBHOOK_SECRET` is consumed by both the hub pod and
|
|
the Forgejo org webhook. After rotation, run `railiance-apps`
|
|
`make reuse-forgejo-webhook` once ESO has refreshed.
|
|
- Break-glass cluster read remains available via
|
|
`kubectl ... get secret reuse-surface-env` when OpenBao is down; steady-state
|
|
custody is OpenBao + ESO only.
|
|
- Rotation procedure: `docs/reuse-surface-runtime-secrets-rotation-runbook.md`;
|
|
post-rotate smoke: `make -C ~/railiance-apps reuse-webhook-smoke`.
|
|
|
|
## Railiance offsite backup lane (`CCR-2026-0004`)
|
|
|
|
Workstation and platform backup tools (`railiance-backup`, `forgejo-backup`) upload
|
|
age-encrypted artifacts to the Nextcloud file drop (Option A, 2026-07-09).
|
|
|
|
| Item | Value |
|
|
| --- | --- |
|
|
| CCR | `CCR-2026-0004-railiance-backup-offsite-lane` |
|
|
| KV mount | `platform` |
|
|
| OpenBao CLI path | `platform/workloads/railiance/backup/offsite-lane` |
|
|
| Fields | `NC_WEBDAV_TOKEN`, `NC_WEBDAV_URL`, `AGE_PRIVATE_KEY` |
|
|
| Read policy | `workload-kv-read-railiance-backup-offsite-lane` |
|
|
| Policy file | `openbao/policies/workload-kv-read-railiance-backup-offsite-lane.hcl` |
|
|
| OIDC auth mount | `netkingdom` |
|
|
| OIDC role | `railiance-backup-workload-kv-read` |
|
|
| Bound claim | `groups=net-kingdom-admins` (confirmed via live `platform-admin` role) |
|
|
| ops-warden catalog id | `railiance-backup-offsite-lane` (draft until front door verified) |
|
|
|
|
Caller login:
|
|
|
|
```bash
|
|
bao login -method=oidc -path=netkingdom role=railiance-backup-workload-kv-read
|
|
```
|
|
|
|
Fetch upload token for a backup run (do not log the value):
|
|
|
|
```bash
|
|
export RAILIANCE_BACKUP_NC_TOKEN=$(
|
|
bao kv get -field=NC_WEBDAV_TOKEN platform/workloads/railiance/backup/offsite-lane
|
|
)
|
|
export RAILIANCE_BACKUP_NC_WEBDAV_URL=$(
|
|
bao kv get -field=NC_WEBDAV_URL platform/workloads/railiance/backup/offsite-lane
|
|
)
|
|
```
|
|
|
|
Or let `lib/railiance-backup-common.sh` load from OpenBao after login when env is unset.
|
|
|
|
Recovery escrow (`AGE_PRIVATE_KEY`) is stored in the same path for disaster
|
|
recovery; prefer the password-manager copy on restore drills per
|
|
`railiance-cluster/docs/backup-restore.md`. Fetch only in attended sessions.
|
|
|
|
## Forgejo admin API token lane (`CCR-2026-0006`)
|
|
|
|
Workstation and activity-core automation (`forgejo-package-prune`, org webhooks,
|
|
operator bootstrap) need a Forgejo site-admin PAT. Phase 1 replaces the legacy
|
|
workstation file `/tmp/forgejo-tegwick-api-token` and `FORGEJO_ADMIN_TOKEN` env
|
|
drops with OpenBao custody. Sibling to `forgejo-mailer` (SMTP); no cluster ESO
|
|
in phase 1.
|
|
|
|
| Item | Value |
|
|
| --- | --- |
|
|
| CCR | `CCR-2026-0006-forgejo-admin-api-token-lane` |
|
|
| KV mount | `platform` |
|
|
| OpenBao CLI path | `platform/workloads/forgejo/forgejo-admin` |
|
|
| Fields | `API_TOKEN` (secret); optional metadata `API_USER`, `API_BASE_URL`, `TOKEN_SCOPES`, `GENERATED_AT` |
|
|
| Read policy | `workload-kv-read-forgejo-admin` |
|
|
| Policy file | `openbao/policies/workload-kv-read-forgejo-admin.hcl` |
|
|
| OIDC auth mount | `netkingdom` |
|
|
| OIDC role | `forgejo-admin-workload-kv-read` |
|
|
| Bound claim | `groups=net-kingdom-admins` |
|
|
| ops-warden catalog id | `forgejo-admin-api-token` (draft until front door verified) |
|
|
|
|
Caller login:
|
|
|
|
```bash
|
|
bao login -method=oidc -path=netkingdom role=forgejo-admin-workload-kv-read
|
|
```
|
|
|
|
Fetch PAT for a Forgejo API run (do not log the value):
|
|
|
|
```bash
|
|
export FORGEJO_ADMIN_TOKEN=$(
|
|
bao kv get -field=API_TOKEN platform/workloads/forgejo/forgejo-admin
|
|
)
|
|
```
|
|
|
|
PAT mint: attended session as Forgejo user `tegwick` (site admin). Minimum scopes:
|
|
`read:package`, `write:package`, `read:repository`, `write:repository`, plus admin
|
|
scopes required by `forgejo-operator-bootstrap`. Downstream repos update `load_token()`
|
|
to read OpenBao when env is unset after lane verification.
|
|
|
|
## Tenant commercial secrets (mount `tenants/`) — WARDEN-WP-0028
|
|
|
|
Client/tenant secrets are **not** under `platform/workloads/`. They use a
|
|
dedicated KV v2 mount:
|
|
|
|
```text
|
|
tenants/<tenant_slug>/<workload>/<bundle>
|
|
```
|
|
|
|
CCR applier allowlist accepts `mount: tenants` and paths under `tenants/`
|
|
(in addition to `platform/workloads/` for fleet lanes).
|
|
|
|
### Binky company email IMAP (`CCR-2026-0007`)
|
|
|
|
| Item | Value |
|
|
| --- | --- |
|
|
| ops-warden catalog id | `binky-company-email-imap` |
|
|
| Tenant | `binky` |
|
|
| Mount | `tenants` |
|
|
| OpenBao CLI path | `tenants/binky/company-email/imap` |
|
|
| Fields | `IMAP_USERNAME`, `IMAP_PASSWORD` |
|
|
| Read policy | `workload-kv-read-binky-company-email-imap` |
|
|
| Policy file | `openbao/policies/workload-kv-read-binky-company-email-imap.hcl` |
|
|
| OIDC role | `binky-company-email-imap-workload-kv-read` |
|
|
| Front-door readiness | active, resolvable=true (provisioned 2026-07-17) |
|
|
| Risk | high |
|
|
|
|
```bash
|
|
bao login -method=oidc -path=netkingdom role=binky-company-email-imap-workload-kv-read
|
|
# after provision:
|
|
bao kv get -field=IMAP_PASSWORD tenants/binky/company-email/imap # interactive human only
|
|
warden access binky-company-email-imap --all --out /tmp/p # preferred
|
|
```
|
|
|
|
Onboarding playbook: `ops-warden/wiki/playbooks/tenant-secret-onboarding.md`.
|
|
|
|
### Binky Qonto bank API (`CCR-2026-0008`)
|
|
|
|
| Item | Value |
|
|
| --- | --- |
|
|
| ops-warden catalog id | `binky-qonto-api` |
|
|
| Tenant | `binky` |
|
|
| Mount | `tenants` |
|
|
| OpenBao CLI path | `tenants/binky/qonto-api` |
|
|
| Fields | `API_KEY`, `API_USER` (map to `QONTO_API_KEY` / `QONTO_ORGANIZATION_ID`) |
|
|
| Read policy | `workload-kv-read-binky-qonto-api` |
|
|
| Policy file | `openbao/policies/workload-kv-read-binky-qonto-api.hcl` |
|
|
| OIDC role | `binky-qonto-api-workload-kv-read` |
|
|
| Front-door readiness | active, resolvable=true (provisioned + first pull 2026-07-21) |
|
|
| Risk | high |
|
|
| Consumer | thirdparty API / self-hosted `qonto/qonto-mcp-server`; harness read-only |
|
|
|
|
```bash
|
|
bao login -method=oidc -path=netkingdom role=binky-qonto-api-workload-kv-read
|
|
warden access binky-qonto-api --all --out /tmp/k # primary field API_KEY
|
|
```
|
|
|
|
Design: `binky-control/integrations/qonto-mcp.md`.
|
|
Onboarding playbook: `ops-warden/wiki/playbooks/tenant-secret-onboarding.md`.
|
|
|
|
## agent-harness Forgejo deploy key
|
|
|
|
| Item | Value |
|
|
| --- | --- |
|
|
| ops-warden catalog id | `agent-harness-forgejo-deploy` |
|
|
| OpenBao CLI path | `platform/workloads/agent-harness/forgejo-deploy-key` |
|
|
| Fields | `SSH_PRIVATE_KEY`, `SSH_PUBLIC_KEY` |
|
|
| Read policy | `workload-kv-read-agent-harness-forgejo` |
|
|
| Policy file | `openbao/policies/workload-kv-read-agent-harness-forgejo.hcl` |
|
|
| Worker host | railiance01 `~/.local/agent-harness/ssh/forgejo-deploy` |
|
|
| Deploy key repos | `coulomb/executor-sandbox` (write); `binky-control` at cutover |
|
|
| Front-door readiness | active (provisioned 2026-07-17) |
|
|
| Risk | high |
|
|
|
|
```bash
|
|
# public key only is safe to print; never print SSH_PRIVATE_KEY
|
|
bao kv get -field=SSH_PUBLIC_KEY platform/workloads/agent-harness/forgejo-deploy-key
|
|
```
|
|
|
|
## agent-harness Binky mail AppRole
|
|
|
|
| Item | Value |
|
|
| --- | --- |
|
|
| ops-warden catalog id | `agent-harness-binky-mail-approle` |
|
|
| AppRole name | `agent-harness-binky-mail` |
|
|
| Token policies | `workload-kv-read-binky-company-email-imap` |
|
|
| token_ttl / max | 15m / 30m |
|
|
| token_num_uses | 8 |
|
|
| Host delivery | railiance01 `~/.local/agent-harness/approle-binky-mail/{role_id,secret_id}` |
|
|
| Env | `EXECUTOR_APPROLE_DIR` via `~/.local/agent-harness/env` |
|
|
| Front-door readiness | active (provisioned 2026-07-17) |
|
|
| Risk | high |
|
|
|
|
Does **not** replace the human OIDC role
|
|
`binky-company-email-imap-workload-kv-read`. Same secret path; separate
|
|
unattended principal.
|
|
|
|
Playbook: `ops-warden/wiki/playbooks/agent-harness-secrets.md`.
|
|
|
|
|
|
## email-connect transactional SMTP + ingest token (`CCR-2026-0010`)
|
|
|
|
IONOS STARTTLS credentials and the shared user-engine ingest bearer for the
|
|
`email-connect` transactional invitation/verification receiver on railiance01.
|
|
|
|
| Item | Value |
|
|
| --- | --- |
|
|
| CCR | `CCR-2026-0010-email-connect-transactional` |
|
|
| KV mount | `platform` |
|
|
| OpenBao CLI path | `platform/workloads/email-connect/transactional` |
|
|
| Fields | `EMAIL_CONNECT_INGEST_TOKEN`, `EMAIL_CONNECT_SMTP_USERNAME`, `EMAIL_CONNECT_SMTP_PASSWORD` |
|
|
| Operator read policy | `workload-kv-read-email-connect-transactional` |
|
|
| Policy file | `openbao/policies/workload-kv-read-email-connect-transactional.hcl` |
|
|
| ESO policy | `external-secrets-email-connect` |
|
|
| ESO policy file | `openbao/policies/external-secrets-email-connect.hcl` |
|
|
| Current ESO auth | policy-limited orphan token in Secret `external-secrets/openbao-email-connect-eso-token` |
|
|
| K8s auth follow-up | role `external-secrets-email-connect` after the railiance01 auth mount is wired |
|
|
| ClusterSecretStore | `openbao-email-connect` (namespace `email-connect` only) |
|
|
| Primary consumer | ExternalSecret `email-connect/email-connect-runtime` → Secret `email-connect-runtime` |
|
|
| Package manifests | `email-connect/deploy/k8s/railiance/` |
|
|
| ops-warden catalog | `email-connect-transactional` (draft until front door verified) |
|
|
|
|
Non-secret SMTP host/port/sender and portal URL stay in ConfigMap
|
|
`email-connect-config` (not in OpenBao).
|
|
|
|
Operator provision (attended; values from mode-0600 files only):
|
|
|
|
```bash
|
|
bao kv put platform/workloads/email-connect/transactional \
|
|
EMAIL_CONNECT_INGEST_TOKEN=@file \
|
|
EMAIL_CONNECT_SMTP_USERNAME=@file \
|
|
EMAIL_CONNECT_SMTP_PASSWORD=@file
|
|
```
|
|
|
|
Fetch for operator smoke only (do not log values):
|
|
|
|
```bash
|
|
bao kv get -field=EMAIL_CONNECT_SMTP_USERNAME \
|
|
platform/workloads/email-connect/transactional
|
|
```
|
|
|
|
Or via ops-warden after catalog promotion:
|
|
|
|
```bash
|
|
warden access email-connect-transactional --exec -- \
|
|
sh -lc 'test -n "$EMAIL_CONNECT_SMTP_PASSWORD"'
|
|
```
|
|
|
|
**Consumer facts:**
|
|
|
|
- user-engine must hold the **same** ingest token under its own runtime secret;
|
|
it must never receive `EMAIL_CONNECT_SMTP_*`.
|
|
- NetworkPolicy in the package admits only `user-engine` to TCP 8080 and egress
|
|
only DNS + TCP 587.
|
|
- Rotation is overlap-first for both SMTP password and ingest token; roll both
|
|
email-connect and user-engine after ESO refresh when the bearer changes.
|