ops-mason/plans/fluid-telegram-operator-credential-lane.md
tegwick 4e3fc02f86 Close the inbound-library IMAP AppRole lane: built, verified, routed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1170398@bnt-lap001
Assistant-Session: 622cd705-cb31-4322-ba08-dd42e44fa583
2026-10-05 16:14:02 +02:00

9.6 KiB

id demand_source consumer_repo credential_type status approved_by approved_at created updated
fluid-telegram-operator-credential-lane fluid-telegram/workplans/FT-WP-0002 and State Hub message 287cf897-7f47-4bcc-87d6-085f43d5f03e fluid-telegram openbao-oidc-kv-read-write draft null null 2026-09-04 2026-09-04

Construction plan: fluid-telegram operator credential lane

1. Demand

fluid-telegram has an attended provisioner that creates a Telegram bot and channels from a declared campaign specification. The provisioner needs an operator OIDC token that reads four campaign-specific KV entries, writes the MTProto session and bot token, and creates the redaction salt once. The MTProto session is a full-account credential, so this is a high-risk operator lane, never an autonomous agent or adapter lane. ops-mason constructs only the OpenBao structure and never handles Telegram values.

The first consumer is campaign hall-of-helix. A future adapter has a different, narrower need and is intentionally excluded from this plan.

2. Existing-structure survey

Disk survey completed 2026-09-04

  • railiance-platform/docs/workload-kv-access-lanes.md documents attended OIDC through auth/netkingdom, exact group-bound roles, three callback URIs, and 15-minute tokens.
  • The nearest concrete tenant-shaped path is platform/workloads/coulomb/whynot-design/npm-publish. Its CCR history says the owner corrected the first segment to the organisation/tenant, not the State Hub domain.
  • Existing policy files contain no fluid-telegram lane.
  • ops-warden/registry/routing/catalog.yaml contains only the generic openbao-api-key template for this need, and its login string omits -path=netkingdom. No concrete Telegram lane exists.
  • ops-mason/src/ops_mason/executor.py supports AppRole and Kubernetes KV lanes. It has no OIDC role writer and its generic policy helper emits the same capabilities for one data and metadata path, which cannot express this four-path matrix.
  • railiance-platform/schemas/credential-change-request.schema.yaml permits only request_type: workload-kv-read; its validator also requires the workload-kv-read- policy prefix and -workload-kv-read OIDC role suffix.

Live survey pending

No valid scoped OpenBao session was available during intake, so the required live outputs from bao secrets list, bao auth list, bao policy list, and the relevant auth/netkingdom/role/* reads are not yet attached. Phase 2 must repeat the survey with ./scripts/bao-session.sh grant MASON-WP-0005-T01.

Existing-lane answer: none is known from source state. This remains a draft finding until the live survey confirms it.

3. Proposed changes

The recommended CLI prefix is platform/workloads/coulomb/fluid-telegram/hall-of-helix. coulomb is a recommendation from the existing owner precedent, not an authorization; T01 must replace this paragraph with railiance-platform's explicit decision before review.

The recommended objects are:

# Action Object Rationale
1 create Policy workload-kv-fluid-telegram-hall-of-helix-operator A new exact-path matrix is required; no read-only lane can satisfy the writes.
2 create OIDC role fluid-telegram-hall-of-helix-workload-kv at auth/netkingdom The caller is an attended operator; AppRole and Kubernetes auth are the wrong identity shapes.
3 modify ops-mason executor with an approved OIDC KV matrix spec The current executor cannot safely express OIDC or per-path capabilities.
4 modify railiance-platform CCR schema/validator with an approved read/write request type and naming rules The platform owner explicitly rejects this shape today; bypassing that gate is forbidden.
5 modify railiance-platform agent high-risk boundary with exact data and metadata denies for all four paths Agent-bound identities must not inherit this lane through another policy.
6 propose ops-warden entry fluid-telegram-operator, pointer-only, status: draft, resolvable: false A concrete selector is useful before activation; no placeholder prefix becomes routable.

Exact policy matrix

All entries are individual KV-v2 API paths. There is no * grant, parent list, metadata mutation, delete, destroy, undelete, or sudo capability.

CLI entry KV-v2 data-path capabilities Risk and reason
.../operator-app read High confidentiality: Telegram application id/hash; entered only through sanctioned attended value entry.
.../operator-session create,read,update High: full-account MTProto credential. Provisioning only; never adapter-visible.
.../bot-token create,read,update High: controls Bot API publication. Provisioner writes immediately after BotFather issues it.
.../redaction-salt create,read High integrity and sensitive pseudonymisation material. Overwrite, patch, and deletion are denied.

OpenBao KV v2 documents that it honors the ACL distinction between create and update; it also documents CAS 0 as create-if-absent. The fluid-telegram client currently performs a read followed by a normal POST. The ACL therefore supplies the decisive server-side write-once boundary: the first POST is a create and a later POST is an update, which this policy denies. The client should still add CAS 0 to make its intent race-safe and explicit, but this plan does not depend on client-only behavior.

This is operational write-once for the provisioner, not immutable storage. A platform administrator can recover from a corrupt first write through a separately approved attended action. That action must preserve the old version until recovery is verified and must never be exposed through this OIDC role.

OIDC role shape

  • auth mount: netkingdom
  • role: fluid-telegram-hall-of-helix-workload-kv
  • token policies: exactly workload-kv-fluid-telegram-hall-of-helix-operator; set token_no_default_policy=true
  • role type: oidc
  • token TTL: 15m, maximum TTL 30m
  • user claim: sub; groups claim: groups
  • scopes: openid,profile,email,groups
  • proposed bound claim: groups=fluid-telegram-operators — unconfirmed
  • callbacks: Bao UI plus localhost and loopback CLI callbacks already accepted by the platform contract

The role is campaign-specific because its policy is campaign-specific. A second campaign receives a second policy and role after its own review; it is not added below this prefix.

Value flow

  • An attended operator enters operator-app with the existing sanctioned paste-once/value-entry mechanism.
  • The provisioner creates or updates operator-session and bot-token.
  • The provisioner creates redaction-salt once.
  • ops-mason records paths, policy/auth metadata, capabilities, versions, timestamps, and audit references only. It never requests or reads a value.

4. Review notes (phase 2)

This section is incomplete while T01 and T02 are open; the plan must remain draft.

  • Reuse: reuse the existing netkingdom auth mount, callback set, group claim pattern, 15-minute TTL, and KV-v2 mount. Create only the policy and role that do not exist.
  • Least privilege: exact entry paths are safer than one campaign-prefix wildcard and are necessary for the salt's create-only rule. The role has no access to KV metadata because the provisioner uses data GETs to detect absence; metadata evidence comes from the separately scoped builder/operator verification path.
  • Identity binding: an unconfirmed group is a hard blocker, not a warning. The role must not be readable by every OIDC user.
  • Write-once semantics: KV-v2 create/update distinction is documented, but activation also requires an owner-run non-secret probe proving the installed engine behaves as expected. The resulting evidence contains no probe value.
  • Agent boundary: explicit denies must cover all four data paths and their metadata paths. The operator-session path is the decisive negative check.
  • Adapter separation: MASON-IN-0003 tracks a later runtime lane that reads only bot-token and redaction-salt; no role or policy in this plan is reused by the adapter.
  • Reversal: disable/delete the OIDC role first, then retire the policy. KV entries remain in operator custody for an explicit retention/recovery decision; teardown does not silently delete values.
  • Implementation gates: both ops-mason and railiance-platform must extend their current read-lane tooling before construction. Direct bao policy write/bao write auth/netkingdom/role/... commands outside those approved surfaces are not an alternative.

Verification required before routing activation

  1. Positive capabilities on each exact path match the matrix above.
  2. Parent, sibling workload, and sibling campaign paths report deny.
  3. A non-member OIDC identity cannot obtain the role's policy.
  4. Agent-bound identities report deny on all four data and metadata paths.
  5. An owner-run disposable KV-v2 probe proves create succeeds and a second write with the same policy is denied; only timestamps, versions, path, and pass/fail are returned.
  6. The value-entry/provisioner flow confirms all required entries exist using metadata/version evidence only.
  7. ops-warden keeps fluid-telegram-operator non-resolvable until all checks pass and the exact built pointers are returned.

5. Executive summary (phase 3)

Not yet renderable. The owner-approved tenant segment, OIDC bound claim, live structure survey, CCR/executor extension, and installed-engine create/update probe are open inputs. When those close, this section must ask for one explicit approval covering the exact objects and capability matrix above.