Skip to content

feat(openbao): 1.2.0, server mode (openbao-local-storage) - #166

Merged
nabil-becker merged 11 commits into
mainfrom
feature/openbao-local-storage/1
Nov 4, 2026
Merged

nabil-becker merged 11 commits into
mainfrom
feature/openbao-local-storage/1

Conversation

@nabil-becker

@nabil-becker nabil-becker commented Nov 3, 2026 •

Copy link
Copy Markdown
Owner

What

Slice 2a of docs/proposals/secrets-master-split.md (section 12): openbao 1.2.0 server mode: raft on the Feature's volume, openbao:init (interactive, asks for a backup destination or an explicit no backup), unseal and seal, userpass, the generic AppRole tasks (ALL=1), openbao:server:status; tasks that handle shares or tokens refuse inside an agent's job.

The Operator's rulings (2026-11-04): the Operator's login only reissues secret ids for existing roles (plus starting or cancelling a root-token attempt, which OpenBao 2.6+ requires); creating or deleting a role takes a root token made from the unseal shares, used once and revoked (ADR 0050, 0051). seal also refuses inside an agent's job. Server mode needs OpenBao 2.4.0 or later.

Why

The approved proposal (#160), ADR 0048. Stacked on #162 (slice 1); retargeted to main when #162 merges. Draft until complete and green.

Checklist

  • Every commit is signed off (DCO)
  • version bumped and its CHANGELOG entry added
  • Downloads remain checksum-verified
  • Tests updated and the scenarios pass in CI
  • task lint passes (known devhost failures excepted)
  • NOTES.md updated and task docs run

https://claude.ai/code/session_01DPsHU61VPD8TZwHanFM7zj

devhost agent and others added 6 commits November 3, 2026 20:26
…build)

Co-Authored-By: Claude Opus 5.5 <claude-opus-5-5@noreply.invalid>
Claude-Session: https://claude.ai/code/session_01DPsHU61VPD8TZwHanFM7zj
Signed-off-by: devhost agent <devhost-agent@noreply.invalid>
…(openbao-state-build)

Slice 1 of secrets-master-split. The Feature now owns its login state like gh
and az: a named volume on /var/lib/devcontainer-features/openbao
(OPENBAO_STATE_DIR) and a post-create hook, openbao-setup (task
openbao:setup), that links ~/.vault-token into it, so a rebuild keeps the
login. dcf-secret (get, put, status) is the one command callers use to ask
for a secret: exit codes 10 to 14 with a one-line fix each, worked out from
bao status, its JSON and bao token capabilities, never falling back to a key
on disk. The mode option has only client, with OPENBAO_SETUP_MODE.

NOTES carry NFR-9's paragraph (checked 2026-11-03). Docker-free tests for
dcf-secret (stub bao) and openbao-setup run in task lint; container tests
add no_taskfile, mode_client and dev_server (a real bao server -dev).

Co-Authored-By: Claude Sonnet 5.5 <claude-sonnet-5-5@noreply.invalid>
Claude-Session: https://claude.ai/code/session_01DPsHU61VPD8TZwHanFM7zj
Signed-off-by: devhost agent <devhost-agent@noreply.invalid>
…openbao-state-build)

The Operator's ruling on #162: put writes only the given field and keeps the
secret's others (bao kv patch); a secret that does not exist is created with
kv put -cas=0, and if it appeared in between one more patch merges into it.
--replace makes the secret exactly the one field. A token without the patch
capability is refused with 13 and nothing is written. The volume name stays
openbao-config-${devcontainerId}; NOTES say it supersedes the proposal's
openbao-${devcontainerId}. Version stays 1.1.0 (unreleased).

Co-Authored-By: Claude Sonnet 5.5 <claude-sonnet-5-5@noreply.invalid>
Claude-Session: https://claude.ai/code/session_01DPsHU61VPD8TZwHanFM7zj
Signed-off-by: devhost agent <devhost-agent@noreply.invalid>
…openbao-state-build)

CI on #162 showed a real bao login replaces ~/.vault-token (the internal
helper writes a temp file and renames it), so a link into the volume does not
hold. The Feature now uses the CLI's own mechanism: BAO_CONFIG_PATH in
containerEnv names a config with token_helper =
/usr/local/bin/openbao-token-helper, which keeps the token at
$OPENBAO_STATE_DIR/token (mode 600, written atomically; erase on revoke).
openbao-setup drops the link and moves a token left in ~/.vault-token into the
state dir once. Unit tests for the helper and the hook, and the dev_server
scenario (login, use, bao token revoke -self), are updated. Version stays 1.1.0.

Co-Authored-By: Claude Sonnet 5.5 <claude-sonnet-5-5@noreply.invalid>
Claude-Session: https://claude.ai/code/session_01DPsHU61VPD8TZwHanFM7zj
Signed-off-by: devhost agent <devhost-agent@noreply.invalid>
…not an erased one (openbao-state-build)

CI on #162 showed bao token revoke -self does not call the token helper's
erase (OpenBao's token_revoke command only calls the API). The test now
expects the dead token to stay stored and dcf-secret to answer 12, and the
new task openbao:logout revokes the token (ignored if already dead) and
erases the saved one. dcf-secret's exit-12 line names login and logout.
Unit tests for the task, the dev_server scenario (with go-task) and NOTES,
CHANGELOG and README follow. Version stays 1.1.0.

Co-Authored-By: Claude Sonnet 5.5 <claude-sonnet-5-5@noreply.invalid>
Claude-Session: https://claude.ai/code/session_01DPsHU61VPD8TZwHanFM7zj
Signed-off-by: devhost agent <devhost-agent@noreply.invalid>
Co-Authored-By: Claude Opus 5.5 <claude-opus-5-5@noreply.invalid>
Claude-Session: https://claude.ai/code/session_01DPsHU61VPD8TZwHanFM7zj
Signed-off-by: devhost agent <devhost-agent@noreply.invalid>
Base automatically changed from feature/openbao-state-build/1 to main November 3, 2026 21:20
devhost agent and others added 2 commits November 3, 2026 21:51
…nseal, userpass and AppRole (openbao-local-storage)

openbao 1.2.0, slice 2a of the secrets-master-split proposal. The mode option
gains `server`: the post-start hook (openbao-setup start) writes a config into
the volume (raft storage, one loopback listener without TLS, the file audit
device declared in the config) and starts bao server, sealed until the
Operator unseals it.

Tasks: openbao:init (asks for a backup destination or an explicit "no backup"
and records it, the Operator's password, 3 shares with threshold 2 printed to
the terminal only, a proof unseal, configuration, root token revoked),
:unseal, :seal, :server:status, :approle:issue (ROLE/POLICY_PATH, ALL=1) and
:approle:revoke; userpass login of 4 hours, at most 8. init, unseal and seal
refuse inside an agent's job (DEVHOST_JOB_CHILD, CLAUDECODE,
OPENBAO_AGENT_JOB_VARS), init and unseal also without a terminal. AppRole
roles are bound to loopback with one valid secret id each, written 0600.

dcf-secret's fix lines name task openbao:unseal, :init and :server:status.
In server mode BAO_ADDR defaults to the local server through env.sh and
openbao-run. disable_mlock is not written: OpenBao has no mlock since 2.0.0.
Server mode needs OpenBao 2.4.0 or newer (the declarative audit stanza).

Tests: server_test.sh (a stub bao; a refusal test per task, init under a
pseudo-terminal, status, AppRole), start hook tests in setup_test.sh, new
dcf-secret cases, and the container scenario server_mode (real bao; also run
by hand against bao 2.7.2). NOTES, CHANGELOG and READMEs updated.

Co-Authored-By: Claude Sonnet 5.5 <claude-sonnet-5-5@noreply.invalid>
Claude-Session: https://claude.ai/code/session_01DPsHU61VPD8TZwHanFM7zj
Signed-off-by: devhost agent <devhost-agent@noreply.invalid>
…-storage/1

Signed-off-by: devhost agent <devhost-agent@noreply.invalid>

# Conflicts:
#	README.md
#	Taskfile.yml
#	src/openbao/CHANGELOG.md
#	src/openbao/NOTES.md
#	src/openbao/README.md
#	src/openbao/dcf-secret.sh
#	src/openbao/devcontainer-feature.json
#	src/openbao/install.sh
#	src/openbao/openbao-setup.sh
#	src/openbao/taskfile.yml
#	test/openbao/mode_client.sh
#	test/openbao/scenarios.json
#	test/openbao/test.sh
#	test/openbao/unit/dcf_secret_test.sh
#	test/openbao/unit/logout_test.sh
#	test/openbao/unit/setup_test.sh
devhost agent and others added 2 commits November 4, 2026 11:40
…and deleting a role take a root token from the shares (openbao-local-storage)

The Operator's token could write any approle-* policy and any role, so it could
write one with snapshot-force and log in through a role holding it, sidestepping
ruling 3. Its policy now covers only the reissue of secret ids for roles that
exist (list roles, read a role-id, list and destroy secret-id accessors, make a
secret id) and starting or cancelling a root-token generation. approle:issue with
POLICY_PATH and approle:revoke make a root token with bao operator generate-root
(OTP, two shares at a hidden prompt), use it for that step only and revoke it
after, also on failure; both refuse inside an agent's job and without a terminal.

Co-Authored-By: Claude Sonnet 5.5 <claude-sonnet-5-5@noreply.invalid>
Claude-Session: https://claude.ai/code/session_01DPsHU61VPD8TZwHanFM7zj
Signed-off-by: devhost agent <devhost-agent@noreply.invalid>
…s nonce (openbao-local-storage)

A share piped on stdin needs -nonce; only bao's own prompt looks it up.

Co-Authored-By: Claude Opus 5.5 <claude-opus-5-5@noreply.invalid>
Claude-Session: https://claude.ai/code/session_01DPsHU61VPD8TZwHanFM7zj
Signed-off-by: devhost agent <devhost-agent@noreply.invalid>
@nabil-becker
nabil-becker marked this pull request as ready for review November 4, 2026 12:01
@nabil-becker
nabil-becker marked this pull request as draft November 4, 2026 12:53
@nabil-becker

Copy link
Copy Markdown
Owner Author

Back to draft: this conflicts with #165 on openbao's version, CHANGELOG and README (#165 bumps openbao to 1.1.1, this to 1.2.0). After #165 merges, main is merged in here keeping 1.2.0 with the 1.1.1 entry below it, and this is marked ready again when CI is green.

https://claude.ai/code/session_01DPsHU61VPD8TZwHanFM7zj

openbao stays 1.2.0 with the 1.1.1 entry below it; How it fits gains server mode's data.

Co-Authored-By: Claude Opus 5.5 <claude-opus-5-5@noreply.invalid>
Claude-Session: https://claude.ai/code/session_01DPsHU61VPD8TZwHanFM7zj
Signed-off-by: devhost agent <devhost-agent@noreply.invalid>
@nabil-becker
nabil-becker marked this pull request as ready for review November 4, 2026 13:17
@nabil-becker

Copy link
Copy Markdown
Owner Author

Ready again: main (with #164 and #165) is merged in, openbao stays 1.2.0 with the 1.1.1 entry below it, How it fits now lists server mode's data, CI 81/81 on 4ed4b1c, and it contains the current main. No other PR is marked ready, so nothing else to collide with.

https://claude.ai/code/session_01DPsHU61VPD8TZwHanFM7zj

@nabil-becker
nabil-becker merged commit b18c0a0 into main Nov 4, 2026
81 checks passed
@nabil-becker
nabil-becker deleted the feature/openbao-local-storage/1 branch November 4, 2026 13:18
nabil-becker pushed a commit that referenced this pull request Nov 4, 2026
…1-slices)

ssh-agent 1.4.0, gh 1.1.0 and devcontainer-cli 1.19.0 keep their versions with #165's patch entries below them;
the READMEs regenerated; the secrets-with-openbao server-mode fragment is now checked (1.3.0 has its options).

Co-Authored-By: Claude Opus 5.5 <claude-opus-5-5@noreply.invalid>
Claude-Session: https://claude.ai/code/session_01DPsHU61VPD8TZwHanFM7zj
Signed-off-by: devhost agent <devhost-agent@noreply.invalid>
nabil-becker pushed a commit that referenced this pull request Nov 4, 2026
…bao-phase1-slices)

Signed-off-by: devhost agent <devhost-agent@noreply.invalid>
nabil-becker added a commit that referenced this pull request Nov 4, 2026
…nd the backs' logins (openbao-phase1-slices) (#167)

## What

OpenBao phase 1, slices 2b, 2c, 3 and 4, built in parallel as four
streams and shipped as one release:
- **2b, backup and restore**: the `backup` role, `openbao:backup`,
`backupKeep`, `backupInterval`, `openbao:restore`.
- **2c, onboarding**: `openbao:onboard:export` / `:claim`
(`rotate-keys`), `openbao:wrap` / `:unwrap`.
- **3, SSH keys in OpenBao**: `openbao:ssh:*` records and the import,
ssh-agent 1.4.0 `key:load` / `key:lock` / `key:rotate` from OpenBao,
`gh:ssh-key:add`, the devcontainer-cli deprecation, `allowed_signers`.
- **4, the backs and the register**: the backs' AppRoles, the fetch in
the job runner, the register's key creation into `dcf-secret put`, the
sealed line in the briefing.

Versions, each bumped once: openbao 1.3.0, ssh-agent 1.4.0, gh,
devcontainer-cli, agentic-register and devhost a minor each.

Stacked on #166 (openbao 1.2.0, server mode); retargeted to `main` when
#166 merges. Draft until all four streams are in and CI is green.

## Why

`docs/proposals/secrets-master-split.md` (approved in #160), section 12,
and ADR 0048. The Operator ruled on 2026-11-04 to build the rest of
phase 1 in parallel as one pull request.

## Checklist

- [ ] Every commit is signed off (DCO)
- [ ] `version` bumped and `CHANGELOG.md` entries added, once per
Feature
- [ ] Downloads remain checksum-verified
- [ ] `install.sh` idempotent, no `remoteUser` assumption
- [ ] Tests updated and passing
- [ ] `task lint` passes
- [ ] `NOTES.md` updated and `task docs` run

https://claude.ai/code/session_01DPsHU61VPD8TZwHanFM7zj

---------

Signed-off-by: devhost agent <devhost-agent@noreply.invalid>
Co-authored-by: devhost agent <devhost-agent@noreply.invalid>
Co-authored-by: Claude Opus 5.5 <claude-opus-5-5@noreply.invalid>
Co-authored-by: Claude Sonnet 5.5 <claude-sonnet-5-5@noreply.invalid>
nabil-becker added a commit that referenced this pull request Nov 4, 2026
…164; the devhost runs openbao in server mode (#168)

## What

Records since #164: ADRs 0050 to 0053 (the Operator's narrowed OpenBao
policy, the root-token attempt paths, onboarding's claim token with `jq`
and no PGP, the ready/draft rule), the lexicon's claim token, the
ready/draft rule in PROCESS.md, backlog amendments applied, the ledger
since #164.

## Why

The decisions taken on 2026-11-04 while building openbao 1.2.0 and the
phase 1 slices (#166, #167).

## Checklist

- [x] Every commit is signed off (DCO)
- [x] `task devhost:verify` passes

https://claude.ai/code/session_01DPsHU61VPD8TZwHanFM7zj

---------

Signed-off-by: devhost agent <devhost-agent@noreply.invalid>
Co-authored-by: devhost agent <devhost-agent@noreply.invalid>
Co-authored-by: Claude Opus 5.5 <claude-opus-5-5@noreply.invalid>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant