Plan ILIB-WP-0003: unattended OpenBao AppRole lane for the library mailbox.
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
This commit is contained in:
parent
d05d6ed35b
commit
15df3d7e52
2 changed files with 151 additions and 1 deletions
|
|
@ -158,7 +158,8 @@ Done 2026-10-05: `run-due` runs under a lock. The systemd units are in `ops/syst
|
|||
|
||||
```task
|
||||
id: ILIB-WP-0002-T07
|
||||
status: todo
|
||||
status: wait
|
||||
blocking_reason: "Needs the unattended OpenBao AppRole lane (ILIB-WP-0003)."
|
||||
priority: high
|
||||
state_hub_task_id: "1e2ab60c-86ef-5e1c-9b94-1f9f1b3182ba"
|
||||
```
|
||||
|
|
@ -195,3 +196,7 @@ version 2.
|
|||
2026-10-05: the founder reports that the entry was created and `IMAP_PASSWORD`
|
||||
was added. This is not yet verified natively. A live read-only scan is still
|
||||
needed for acceptance.
|
||||
|
||||
2026-10-05: the founder rejected an env file as a credential cache. The live
|
||||
credential now comes from an ops-mason AppRole lane, fetched on every run
|
||||
(ILIB-WP-0003). This task completes with ILIB-WP-0003-T06.
|
||||
|
|
|
|||
145
workplans/ILIB-WP-0003-openbao-approle-imap.md
Normal file
145
workplans/ILIB-WP-0003-openbao-approle-imap.md
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
---
|
||||
id: ILIB-WP-0003
|
||||
type: workplan
|
||||
title: "Read the library IMAP credential unattended from OpenBao"
|
||||
domain: infotech
|
||||
repo: inbound-library
|
||||
status: active
|
||||
flavor: implementation
|
||||
owner: claude
|
||||
topic_slug: custodian
|
||||
created: "2026-10-05"
|
||||
updated: "2026-10-05"
|
||||
---
|
||||
|
||||
# Read the library IMAP credential unattended from OpenBao
|
||||
|
||||
The timer must read `library@coulomb.social` without an operator and without a
|
||||
copy of the password cached on disk. The ecosystem already has the pieces; this
|
||||
workplan uses them and does not build new infrastructure.
|
||||
|
||||
- **ops-mason** builds OpenBao AppRoles, policies and KV path structure from a
|
||||
construction plan (`plans/<id>.md`). The plan goes from draft to reviewed, then
|
||||
to approved (by the founder, from its executive summary), then built, then
|
||||
catalogued. The build refuses to run unless the approved spec digest matches
|
||||
the execution inputs. AppRole credentials go to private, exclusive files, and
|
||||
the build is written to ops-mason's own audit trail. `AppRoleKVSpec` already
|
||||
generates this shape.
|
||||
- **ops-warden** routes to the lane through a pointer-only catalog entry
|
||||
(`registry/routing/catalog.yaml`). It never holds the value.
|
||||
- Precedents: `rein-openweights-openrouter-approle` and
|
||||
`agent-harness-binky-mail` (an unattended AppRole on the workstation), and
|
||||
`rein-aharness/mailscan.py` (an AppRole login followed by an IMAP scan).
|
||||
|
||||
Audit trail: the approved construction plan holds the decision and its reasoning,
|
||||
and the approved digest binds that decision to what was built. ops-mason's build
|
||||
evidence and audit log record the execution. The warden catalog commit records
|
||||
the routing. The KV entry `platform/workloads/inbound-library/imap` itself was
|
||||
created by `railiance-platform/scripts/inbound_library_imap_entry.py`
|
||||
(docs/inbound-library-imap-custody.md).
|
||||
|
||||
## Draft the ops-mason construction plan
|
||||
|
||||
```task
|
||||
id: ILIB-WP-0003-T01
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
Write `ops-mason/plans/inbound-library-imap-approle.md`, with demand source
|
||||
ILIB-WP-0002-T07 and `credential_type: openbao-approle-kv`. Proposed shape:
|
||||
- policy `workload-kv-read-inbound-library-imap`, read only, on
|
||||
`platform/data/workloads/inbound-library/imap`;
|
||||
- AppRole `inbound-library`, following the precedent: `token_ttl` 15m,
|
||||
`token_max_ttl` 30m, and an explicitly bounded `token_num_uses`;
|
||||
- delivery to `~/.local/inbound-library/approle/` (`role_id`, `secret_id`);
|
||||
- `secret_id_ttl` to be decided in review.
|
||||
|
||||
Include the section 2 existing-structure survey (live `bao` policy, auth and
|
||||
secrets lists, and the warden catalog), the phase 2 self-review, and the build
|
||||
spec with its digest.
|
||||
|
||||
Acceptance: the plan reaches status `reviewed` and its executive summary is
|
||||
rendered.
|
||||
|
||||
## Founder approval
|
||||
|
||||
```task
|
||||
id: ILIB-WP-0003-T02
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
The founder decides from the executive summary. The plan then records
|
||||
`approved_by`, `approved_at` and `approved_spec_sha256`.
|
||||
|
||||
Acceptance: the plan is `approved`. The digest matches the build spec.
|
||||
|
||||
## Build the lane
|
||||
|
||||
```task
|
||||
id: ILIB-WP-0003-T03
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
Run the ops-mason AppRole builder from the approved plan, in an attended
|
||||
platform-admin session. It creates the policy and the AppRole and delivers
|
||||
`role_id` and `secret_id` to private files. Then record capabilities-safe
|
||||
evidence: the lane token can read the path, a default-policy token is denied,
|
||||
and no value is printed. Append section 6 with the build result.
|
||||
|
||||
Acceptance: the plan is `built`, and the evidence is in ops-mason
|
||||
`docs/evidence/`.
|
||||
|
||||
## Fetch the credential on every run
|
||||
|
||||
```task
|
||||
id: ILIB-WP-0003-T04
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
In `inbound_library`, add a standard-library OpenBao client:
|
||||
- an AppRole login using the delivered files;
|
||||
- one KV v2 read of `IMAP_USERNAME`, `IMAP_PASSWORD`, `IMAP_HOST`, `IMAP_PORT`
|
||||
and `IMAP_FOLDER`;
|
||||
- values held in memory for one run only, never logged, never written to disk.
|
||||
|
||||
The bao address, the AppRole directory and the KV path go in
|
||||
`config/library.json`. The environment variables remain only as an explicit
|
||||
override for tests. When OpenBao is unreachable, `run-due` reports
|
||||
`credential_unavailable`, and matching and notices still run. Remove the
|
||||
`EnvironmentFile` from the service unit.
|
||||
|
||||
Acceptance: the tests use a fake OpenBao (login, read, denied, unreachable).
|
||||
No secret appears in any output.
|
||||
|
||||
## Route the lane in ops-warden
|
||||
|
||||
```task
|
||||
id: ILIB-WP-0003-T05
|
||||
status: todo
|
||||
priority: medium
|
||||
```
|
||||
|
||||
ops-mason proposes a pointer-only catalog entry `inbound-library-imap-approle`
|
||||
(`warden_executes: false`) and a playbook, modelled on
|
||||
`rein-openweights-openrouter-approle`.
|
||||
|
||||
Acceptance: `warden access` resolves the need to this lane.
|
||||
|
||||
## Live verification
|
||||
|
||||
```task
|
||||
id: ILIB-WP-0003-T06
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
Install the timer and trigger one run through systemd. The journal must show an
|
||||
AppRole login and a read-only scan of `library@coulomb.social`, with no secret
|
||||
in the output. This also completes ILIB-WP-0002-T07.
|
||||
|
||||
Acceptance: one real mail is retained with provenance. No mailbox state changes,
|
||||
and no credential file exists other than the AppRole delivery.
|
||||
Loading…
Add table
Add a link
Reference in a new issue