fluid-telegram/docs/requests/ops-warden-telegram-operator-lane.md
tegwick 854e807899 Request a credential lane for the Telegram operator
Addressed to ops-warden as the front door, and explicit that the lane
itself is railiance-platform's to create -- ops-warden routes this row
rather than executing it.

States the two things that are easy to get wrong. The lane needs write and
not only read: apply's critical write happens immediately after BotFather
issues the bot token, and a denial there leaves a registered bot whose only
credential is a chat message, with a re-run creating a second bot. And the
redaction salt must never be rotated, so write-once on that path would be
welcome if the lane tooling can express it.

Leaves the <domain> segment open rather than assuming infotech: the only
concrete lane we can read uses "coulomb", which looks like a tenant rather
than a sector, and the segment belongs to its owner.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0172sgCZEEDJcnQmr4SGDvKa

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1361245@bnt-lap001
Assistant-Session: b3b428ef-f3e6-4688-b091-01f71461d66a
2026-09-04 23:11:24 +02:00

6.2 KiB

to from date subject routes_to
ops-warden fluid-telegram 2026-09-04 Credential lane for the Telegram operator (workplan FT-WP-0002) railiance-platform (OpenBao)

Request — credential lane for the Telegram operator

fluid-telegram provisions HelixForge's Telegram presence from a declared specification (FT-WP-0002, docs/provisioning.md). The tooling is built, tested and ready; the only thing blocking the first run is that it has nowhere sanctioned to keep four secrets and no role that can reach them.

Per wiki/AccessRouting.md this is the "API key / DB credential" row, so ops-warden routes rather than executes it. We are asking ops-warden for the routing artifacts, and asking it to point us at railiance-platform for the lane itself.

What the workload is

A provisioning tool, run by an operator on demand. It is not on any request path, and it is not the adapter — the adapter that publishes to Telegram holds only a bot token and never sees the rest.

It runs plan and apply against a declared spec: registering the bot through BotFather over MTProto, creating channels, and granting the bot post_messages and nothing wider.

The four secrets

All under one bundle prefix, one KV entry each:

Bundle Contents Written by Read by
operator-app api_id, api_hash from my.telegram.org operator, by hand provisioner
operator-session MTProto session string provisioner (session bootstrap) provisioner
bot-token Telegram bot token provisioner (apply) provisioner, adapter
redaction-salt 32 random bytes provisioner, once, never rotated adapter

Two of these deserve a note.

operator-session is a full-account credential. It can do anything the operator's Telegram account can do. It is held only because the Bot API cannot create a bot or a channel — both are client capabilities reachable only through MTProto (Canon INT-03). The account is a dedicated operator account, never a person's own, and the session is used for provisioning only: all ordinary publishing goes through the bot token on the supported Bot API surface. We would grade this lane high risk.

redaction-salt must never be rotated. Rotating it silently invalidates every longitudinal comparison the interface has made, with no visible failure — the numbers keep arriving and quietly stop meaning what they used to. The tool has no code path that overwrites it (create-if-absent only). If your lane tooling can enforce write-once on that one path, we would welcome it.

What we need

1. From railiance-platform — a workload KV lane

Following railiance-platform/docs/workload-kv-access-lanes.md:

  • A role, by your naming convention presumably fluid-telegram-workload-kv
  • Policy over platform/workloads/<domain>/fluid-telegram/<campaign>/*
  • OIDC through auth/netkingdom, as the existing lanes use

This lane needs write, not only read. Every documented lane we found is -workload-kv-read, and read-only would fail badly here rather than merely being inconvenient: apply writes three of the four paths, and the write that matters happens immediately after BotFather issues the bot token. A denial at that moment leaves a registered bot whose only surviving credential is a chat message, and re-running creates a second bot. If a split is preferred, the minimum is write on operator-session, bot-token and redaction-salt, and read on all four.

2. From ops-warden — a catalog entry

So that warden access 'telegram operator credentials' resolves to something concrete rather than the generic openbao-api-key template. Proposed, in the shape of whynot-design-npm-publish:

id: fluid-telegram-operator
title: "fluid-telegram Telegram operator credentials (MTProto session, bot token, salt)"
risk: high
workload_ref:
  applicability: applicable
need_keywords: [telegram, mtproto, botfather, bot, token, session, fluid-telegram,
                helix-forge, hall-of-helix, provisioning]
owner_repo: railiance-platform
subsystem: OpenBao
warden_executes: false
auth_method: bao login -method=oidc -path=netkingdom role=fluid-telegram-workload-kv
path_template: platform/workloads/<domain>/fluid-telegram/<campaign>
policy_ref: flex-auth check secret.read:fluid-telegram
wiki_ref: fluid-telegram/docs/seeding-runbook.md

Corrections welcome — we have modelled this on your existing entries rather than inventing a shape.

One open question — the <domain> segment

We had assumed infotech, this repository's State Hub domain. But the only concrete lane we can read uses platform/workloads/**coulomb**/whynot-design/…, where the segment looks like a tenant rather than a sector.

We do not want to guess: the segment is yours to define, and a workload that picks its own path in someone else's store is how a policy ends up written around a mistake. Tell us which is correct and we will take it.

The provisioner reads BAO_MOUNT and FLUID_BAO_PREFIX, so whatever you confirm is configuration on our side, not a code change.

What is already done

  • Paths, mount and prefix are configurable; nothing is hardcoded.
  • The tool reads ~/.vault-token and BAO_TOKEN/VAULT_TOKEN; it never writes a credential to disk or logs one, and error messages name paths, never values.
  • provision preflight checks the whole chain without contacting Telegram, and currently reports everything green except OpenBao access.

Note on a diagnosis that cost us time

warden access renders bao login -method=oidc role=<domain> for this need. The working form is -path=netkingdom, which we found in railiance-platform's runbook. Because OpenBao answers 403 permission denied for paths that do not exist as well as for those you may not reach, the wrong mount is indistinguishable from an expired token from the outside — we spent a while renewing a token that was not the problem.

If auth_method in the generic openbao-api-key entry carried -path=netkingdom, the next person would not repeat this. Offered as an observation, not a defect report: the entry is explicitly a template with owner-confirmed placeholders.

Contact

Repository fluid-telegram, workplan FT-WP-0002, State Hub topic helix-forge, domain infotech.