source: repo-manager reason: deterministic projection registration Assistant: claude-code Assistant-Model: opus Assistant-Process: 1361245@bnt-lap001 Assistant-Session: b3b428ef-f3e6-4688-b091-01f71461d66a
6.7 KiB
| id | type | title | domain | repo | status | owner | topic_slug | created | updated | planning_priority | planning_order | depends_on | related_repos | state_hub_workstream_id | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| FT-WP-0002 | workplan | Provision the Telegram presence from a declared specification | infotech | fluid-telegram | proposed | worsch | fluid-telegram | 2026-09-04 | 2026-09-04 | high | 2 |
|
|
f2373858-c932-5a4d-81b6-db9a3595135a |
FT-WP-0002 — Declared presence provisioning
Replace the manual route of FT-WP-0001 T01–T03 with a specification and a
reconciler. The design, its constraints and its guardrails are in
docs/provisioning.md; this workplan implements it.
The shape of the problem, stated once: the Bot API cannot create a bot or a
channel. Both are client capabilities reachable only through MTProto with a user
account (Canon INT-03). So provisioning is an MTProto client acting as a
designated operator, and three things stay human — a phone number, the
api_id/api_hash web form, and the login code that mints the session. That is
one bounded bootstrap, after which the surface is declared and converges.
T01 — Bootstrap the operator account and session
id: FT-WP-0002-T01
status: todo
priority: high
state_hub_task_id: "039e5358-07c1-5b01-a186-5ece9aab75e4"
The irreducible human step. Register a dedicated Telegram account for the
operator — never a person's own, so that a rate limit costs nothing personal.
Obtain api_id / api_hash from my.telegram.org.
Then provision session bootstrap runs the interactive login once and writes the
session string to OpenBao. The command is the only interactive one in the tool,
and it exists so that the interactive part is bounded and named rather than
spread through the process.
Nothing else in this workplan is interactive.
T02 — Publish the presence schema and the campaign's spec
id: FT-WP-0002-T02
status: todo
priority: high
state_hub_task_id: "01684264-37a5-5fe8-a491-37686e094428"
The schema is in presence/telegram.schema.yaml with a worked example beside it.
What remains is the real instance at pr-hall-of-helix/presence/telegram.yaml,
plus the avatar asset.
The spec is editorial — a bot's name, its description, the channel titles a stranger reads — so it belongs to the campaign. The provisioner takes a spec path as input, which is what keeps this interface reusable by campaigns other than the Hall of Helix.
Blocked on pr-hall-of-helix existing.
T03 — Implement provision plan
id: FT-WP-0002-T03
status: todo
priority: high
state_hub_task_id: "c3923422-7f2e-5bf9-906c-6d59572b09c0"
Read the spec, validate it against the schema, read live state through MTProto,
read presence/resolved/<campaign>.yaml, print a diff. Write nothing.
Validation is where the rights clamp lives: an admin_rights entry other than
post_messages fails here, loudly, rather than being quietly dropped. The intent
forbids the system from holding a right it may not exercise, and a spec is the
cheapest place to catch someone asking for one.
plan must be honest about what it cannot see. A username's availability is not
knowable without attempting it, so the plan says "will attempt, with fallbacks"
rather than promising an outcome.
T04 — Implement provision apply
id: FT-WP-0002-T04
status: todo
priority: high
state_hub_task_id: "5659b72a-8309-58b6-96e9-79137ce41ed4"
Execute an approved plan. Idempotent, keyed on resolved ids rather than names.
- Bot: BotFather
/newbot, then/setabouttext,/setdescription,/setuserpic. Parse the token from the reply, write it straight to OpenBao, and hold it in memory nowhere longer than that call. Walkusername_preferenceon collision. - Channels:
channels.createChannel, test channel first. Set the public username; a private channel that declares one is a validation error, not a silent skip. - Bot as administrator:
channels.editAdminwithpost_messagesand nothing else. - Write
presence/resolved/<campaign>.yamlwith the spec digest.
Three refusals carry the weight, and each is a real failure mode rather than a hypothetical: there is no destroy path — removing a channel from the spec warns, because deleting one destroys its subscribers and history irreversibly; drift on a destructive field stops the run — a demoted bot or a taken-over username exits non-zero rather than being "fixed" by a tool that does not understand what happened; and the public channel is not touched until the test channel has recorded a successful publication.
T05 — Provision the redaction salt
id: FT-WP-0002-T05
status: todo
priority: high
state_hub_task_id: "d5fd905a-6abd-5ae1-9105-abc4c2a7127e"
Generate 32 bytes if and only if the OpenBao path is empty, and never overwrite.
Supersedes FT-WP-0001 T03.
The create-if-absent rule is not defensiveness. docs/observation.md explains
that rotating the salt silently invalidates every longitudinal comparison the
interface has made, and does so with no visible failure — the numbers keep
arriving and quietly stop meaning what they used to. A tool that can rewrite it
is a tool that will eventually rewrite it, so the only path to a new salt is a
deliberate human write, which is a decision rather than a run.
T06 — Derive adapter configuration from the resolved state
id: FT-WP-0002-T06
status: todo
priority: medium
state_hub_task_id: "c305b83f-b05e-5f09-9182-9896ae137c38"
The adapter reads its chat id and bot token from the resolved state and OpenBao. It gets no MTProto session and no provisioning code path, so a compromised adapter cannot create, rename, delete or re-permission anything. That separation is the point of running two planes rather than one tool with a flag.
T07 — Drift check
id: FT-WP-0002-T07
status: todo
priority: low
state_hub_task_id: "f3f36415-ed55-5717-b752-706b04ba5458"
provision plan --check exits non-zero on drift, suitable for a scheduled run.
Report only; never auto-apply. An unattended reconciler that can change a public
channel is the thing IEI-1 §7 exists to prevent.
T08 — Settle the §7 reading
id: FT-WP-0002-T08
status: todo
priority: medium
state_hub_task_id: "864bcd23-6357-5460-a8e6-98ec9a929e29"
InterfaceEvolutionIntent.md §7 lists channel and bot creation under explicit
non-authority without distinguishing the Daimon from an operator-run tool. The
intended reading is that §7 constrains autonomous action and an approved plan
is not autonomous — but that is currently a reading rather than something the
document says, and a constitutional document should not depend on one.
Add a one-sentence clarification, as a governance change under §20, before T04 runs against anything real.