Skip to content

Vault: each Environment owns its vault (root decision 0198, DEV-6631 task 638a) - #391

Merged
immakermatty merged 9 commits into
mainfrom
agent/DEV-6631-environment-own-vault
Oct 14, 2026
Merged

immakermatty merged 9 commits into
mainfrom
agent/DEV-6631-environment-own-vault

Conversation

@immakermatty

@immakermatty immakermatty commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

Root decision 0198 (points 1, 2, 4, 6 and 7, with 0197 points 3 and 7–9) gives every Environment its own vault: its own organization in its network's Lazurio Vaultwarden, created and held by the Environment's technical account and remembered by ID. Until now (decision F43) an Environment was a member of a person's organization: an Admin invited a guessed address vaultwarden@<address> into a collection, confirmed the member by its fingerprint, and the Environment recognized its collection partly by name. This PR replaces that model in the Platform (DEV-6631 task 638 part A, contract C3).

Target state

  • The account and the vault come from the handover. The optional, closed handover member vault: {server_url, account, name} (contract C2), which Machines writes only for a Platform that reads it, names the network's vault, the technical account the network pre-allowed for this Environment (vaultwarden-<26 base32>@<Environment address>) and the vault's name. Without it the Environment has no vault yet and says so (unsupported, no-vault). Nothing is guessed: no vaultwarden@<address>, no vault derived from Headscale, no collection-name match (including the "·" name).
  • The Environment creates its vault. lazurio vault setup (and the installed Launchpad at its start, by Executor's pattern) installs the pinned bw, registers the account (the existing flow), logs in with its API key (client_credentials) and creates the organization with POST /api/organizations: the organization key RSA-OAEP-encrypted to the account's own public key (derived from its own private key), the organization key pair with its private key wrapped by the organization key, the billing e-mail (the account), the name vault.name and a first collection "Agenti", its name encrypted with the organization key. It records the organization and Agenti by ID and renames the organization when vault.name changes. A creation is never sent twice: its receipt (the new organization's public key, with the time, recorded before the request) is resolved first. While it is unresolved, every setup looks for the organization carrying that key among the account's memberships of any status and sends no new creation; found nowhere (an answer lost, a profile that lists it late, a request that arrives late), the setup reports creating and the next one looks again. Only a receipt older than 15 minutes (a request times out at 30 s) that still matches nothing is taken for a creation that never happened: discarded (journal receipt-expired) and the vault created once. A creation refused by the vault's answer discards its receipt at once. A recorded organization that is gone, or a refused API key, is revoked and never replaced.
  • One shared unlocked bw session for agents, unchanged.
  • The agents use it from the start (0198 point 1). The setup in which the vault becomes ready (its collection Agenti recorded) turns "Používají agenti" on for bitwarden in the Environment's Folder, at the Launchpad's start as with lazurio vault setup: the same change the switch makes, refused as the switch is where the tool is not offered or the Organization does not allow it. Once per vault: a person may turn it off and it stays off, because no later setup (a new session after a restart, a rename, a repair) turns it on again; a failure is journaled (agents-not-enabled) and never fails the setup. The page no longer turns the switch on itself.
  • No bw ever runs without its own data directory (bw rewrites its store on every start, so a run without one rewrites a default profile, a person's own included). bwCli, through which every bw of the vault runs (setup, status, refresh, env's unlock, secrets, the pilot subset, the installer's version check), now refuses before anything runs unless the binary and the data directory are absolute paths, and sets BITWARDENCLI_APPDATA_DIR last on every run so no step can replace it. The one other path that starts a bw, the version probe of Settings → Tools, already gives it a fresh mkdtemp directory (the catalog's isolatedData), removed afterwards; a test now pins both.
  • The Tools row shows only the state and "Otevřít trezor" (<server_url>/#/vault?organizationId=<id>), plus one action only where a setup moves the vault on ("Nastavit", "Zkusit znovu", as the wireframe's unreachable state does). No dialog, no details, no disconnect. Czech copy is formal and minimal.
  • Pilot safety. Environments connected the 0197 way keep working read only while their handover names no vault: status connected, the shared session unlocked, module secrets (F46) from the recorded collection. This frozen subset lives alone in src/vault/legacy-0197/, whose README names its deletion condition (every handover carries vault and task 649 has moved the items). When the handover gains vault, the new flow runs with the new account in its own directory and the pilot's directory stays untouched.
  • F46 reads the own vault: the one item named exactly like the secret anywhere in it (login.password). On a work Environment the owning Organization's apps read it; on a personal Environment the Personalspace's modules do (0198 point 4); everything else is refused with a clear reason (other-organization, personalspace, personal-environment).

What changes

  • src/machine/: the handover schema of Machines v0.12.159 (the merge of Apps → Trezor only where a vault is: the entry follows the vault core's answer (F36/F53 addendum, DEV-6612) #500, 8b66889b; adds only vault, with a work and a personal account shape), vendored byte for byte with its provenance; MachineVault type.
  • src/vault/: host.ts (enableVaultForAgents: the switch's own Folder change at the current revision, retried on a busy or meanwhile-changed Folder as the Organization's settings are), flow.ts (enableForAgents, called once by the setup in which the vault becomes ready, outside the account's lock), bw.ts (the data-directory guard), context.ts (facts from the member only), store.ts (custody keyed by the account; the own record {organizationId, collectionId, pendingKey}, unreadable → refused), register.ts (vaultRequest with PUT/DELETE, apiKeyLogin, unlockPrivateKey, publicKeyOf), new organization.ts (create, recognize by receipt, find Agenti by ID, rename), new session.ts (the one shared session and the secret read, shared with the pilot subset), new status.ts (the answers), flow.ts (status, setup, refresh, env, secrets; setUpAtStart), host.ts, cli.ts (env|status|refresh|setup), bw.ts (no fingerprint step; items by organization); new legacy-0197/ (frozen pilot read path + README).
  • Launchpad: vault-routes.ts (status, refresh, setup with a job; atStart), server.ts and cli.ts/update/cli.ts (vaultAtStart, the Executor rule; the Folder's switch for a given host), vault-view.ts and vault-panel.ts (state, link, one action), tools-panel.ts (after a followed setup ends connected the page reads the Folder again; it never toggles the switch itself), the dialog and its CSS removed from index.html, messages (formal Czech, minimal).
  • F46: runtime-secrets.ts hands the module's kind to the vault, which decides; the catalog's check follows the same rule; texts name the vault, not a collection.
  • Agents: the bitwarden catalog entry (minimal, correct; room left for task 652's a/b/c), template revision base-instructions-49 (Copy: address people formally (vykání) in Launchpad, shell, CLI and agents' speech #328's vykání took 48); the tool's purpose, which the Launchpad also shows, keeps Copy: address people formally (vykání) in Launchpad, shell, CLI and agents' speech #328's neutral wording ("Co v něm je, smějí agenti použít bez ptaní.").
  • Recovery evidence withholds vault.account, vault.name and the vault's host.
  • Docs: new decision F53 (supersedes F43's collection model, amends F46; F52 is the module generator's, Modules: one module generator in the Platform, with the personal form (M2 1/3, #359) #394), environment-tools.md, launchpad-development.md, machine-handover.md, recovery.md, public-development.md, module-adoption.md.

What deliberately does not change

  • Správci membership (638b), Nastavení → Trezor (648), secret requests (651), the full Folder guidance (652), Dashboard, releases.
  • The session model, the pinned bw 2026.7.0 and its installer, F43's custody form.
  • The agents' switch stays a switch a person can turn off (the wireframe keeps it); only the vault's first readiness turns it on.

Verification

  • bun run check on head 7eab1559823f520a841edad92db545f851f4e906 (rebased on main a9f80c7, with Copy: address people formally (vykání) in Launchpad, shell, CLI and agents' speech #328): Biome, tsc, the public guard, the proof build and smoke, then 3490 pass, 8 skip, 1 fail (10 min): the one failure is a flake of main itself, untouched here (Flaky: launchpad-prompts expects no GitHub call before admission, but the Launchpad's start peeks the Personalspace holder in the background #413: tests/launchpad-prompts.test.ts expects no GitHub call before admission while the Launchpad's start peeks the Personalspace holder in the background; 7 of 10 runs of that file fail on plain main a9f80c7 locally, 6 of 10 on this branch). CI on this head: green (static checks, both Linux test shards, check (ubuntu-24.04)) on the third attempt of tests (2/2); its first two timed out in tests/shell-artifact.test.ts, whose second build's bun build child hung (untouched here; Flaky on Linux CI: shell-artifact's second build hangs in its bun build child (contract.js) until the 60 s bound #414), and the third passed (1.1 s).
  • Earlier heads, before the rebase: 3425e71 (the review fix) 2623 pass, 0 fail, CI green; 88c382d (the agents' switch and the bw data-directory guard) 2621 pass, 0 fail; a4bb8f3 2619 pass, 0 fail.
  • On Linux, where a Folder offers the vault (on 88c382d): tests/launchpad-vault.test.ts, tests/vault-flow.test.ts and tests/vault-store.test.ts in a Linux container (oven/bun:1.4.2, the temporary directory on ext4 as the Folder's lock requires): 26 pass, 0 fail, including the Launchpad's Folder switch test, which macOS skips. CI's Linux shards run them too.
  • New and rewritten tests against the real consumers (startLaunchpad over HTTP, runVaultCommand, createModuleOperations) and the fake Vaultwarden extended with the API-key login, the profile and the organization endpoints: tests/vault-flow.test.ts (17, including the agents' switch turned on once per vault, the review's reproduction (a lost answer, then one profile without the organization: creating, one organization, found on the next run) and a receipt that matches nothing making exactly one organization after its bound), tests/vault-organization.test.ts (2, including the account opening its own organization key from its master password down to Agenti's name and the organization's private key), tests/vault-pilot.test.ts (6, the pilot with and without vault, its directory untouched), tests/vault-cli.test.ts, tests/launchpad-vault.test.ts (routes, the setup at start, and the Folder's switch on Linux), tests/vault-handover.test.ts (the member, a missing or invalid member, an earlier Platform refusing a handover with it, the binding, redaction), tests/vault-secrets.test.ts, tests/runtime-secrets.test.ts, tests/module-runtime-secrets.test.ts (a Personalspace module reading its secret on a personal Environment end to end), tests/vault-view.test.ts, tests/vault-context.test.ts, tests/vault-host.test.ts, tests/vault-store.test.ts (with bw refused without its own data directory and the Tools probe's temporary one, and the receipt's time required in its one form), tests/vault-register.test.ts. No value or token on argv (the fake bw logs $HOME/bw.calls), in the journal or in an answer.
  • In a browser (decision 0178), throwaway Launchpads of this branch with the fake vault, Settings → Nástroje. The row: "Hesla a další položky pro agenty.", "Připojeno", and its only control "Otevřít trezor" (https://vaultwarden.example.lazurio.io/#/vault?organizationId=<id>, new tab, noopener noreferrer). The switch, on Linux in a personal Remote Environment's Folder with bitwarden offered and off: the Launchpad's start set the vault up while the row followed the job ("Instaluje se Bitwarden…", switch off), it ended "Připojeno" with the link and the switch on (aria-checked="true", the Folder's selection ["bitwarden"]); turned off by a click, it stayed off through a later setup of the same vault (its session lost: connected, locked → setup → connected, enabled: false). A creation that never reached the vault (on 3425e71): the row read "Trezor se zakládá" with "Zkusit znovu" and the switch off, and "Zkusit znovu" ended in the same state without a second creation. (The not-allowed/no-vault lines are covered by tests/vault-view.test.ts and the HTTP tests, not opened in the browser.)
  • End to end against the real image (on a4bb8f3, before the review's three commits) ghcr.io/lazurio/vaultwarden:1.37.4-lazurio.1@sha256:68da93bb…f492 (amd64 under Rosetta, OrbStack, own container prefix and port, TLS with a throwaway CA) and the real pinned bw 2026.7.0 for macOS arm64, downloaded and verified by the core's own installer, driving this branch's core: /admin/invite pre-allowed the account; setup connected in 21 s (install → account → vault → sign-in); the account is the vault's only, confirmed Owner and a member of nothing else; the vault has exactly one collection, the recorded Agenti; the real bw sync and bw list collections showed "Agenti" (bw opened the organization key itself); an item created in Agenti was read back by the core as a runtime secret; a new name renamed the same vault; a setup again kept one vault; no secret in 28 bw argv lists or the 7 journal entries. 17 of 17 checks; the container, volume and the run's state were removed afterwards. The Linux bw binary was not exercised here.

Risks, open questions, follow-ups

Plan and work context

Status: ready for review

🤖 Generated with Claude Code

@agentrozjedemeai agentrozjedemeai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@immakermatty — changes requested on exact head 88c382d (#391).

Blocker — src/vault/organization.ts:142-174: A saved pendingKey does not prevent another POST when the profile temporarily omits the newly created organization. The code searches current confirmed memberships; on no match it generates a new key, overwrites the receipt and sends another create request. A delayed first request, a lagging profile, or a briefly unconfirmed membership can therefore create two organizations for one Environment, orphan the original, and violate the vault identity/idempotency contract. I reproduced this against the in-repo fake vault: let the first POST succeed but lose its answer, return a valid empty organization list from one subsequent profile request, then retry setup. The result was connected with 2 organizations; the recorded receipt was replaced. Please fail closed while an earlier receipt remains unresolved (or use a server-enforced idempotency/reconciliation mechanism), and add a test for this transient absence, not just a lost answer immediately visible in the profile.

Validation: 57 focused tests passed, 1 platform-specific test skipped locally; public guard passed. Green CI on this head. I found no client Organization or person named in the added source/docs; references to HumanAndMachine-ai/Machines and prototypes-lazurio are provider/source links. Schema re-pin to Machines #500 merge remains a declared pre-merge gate. No merge performed.

@immakermatty

Copy link
Copy Markdown
Contributor Author

Re the blocker in the review of 88c382d: a saved pendingKey did not stop another create when the profile briefly omitted the new organization. Confirmed and fixed in 3425e71.

  • An unresolved receipt fails closed. While a creation's receipt is unresolved, no setup sends another POST /api/organizations. Each run looks for the organization that carries the recorded public key among the account's memberships of any status (/api/accounts/profile, then GET /api/organizations/<id>/public-key). A membership whose key the vault refuses to show (4xx) is skipped. Any other failure ends the run with the receipt kept.
  • Matches and the new state. A match is recorded once its membership is confirmed. Until then, and while nothing matches, the setup reports the new state creating. The local status says the same, the Launchpad's start sets it up again, and the row reads "Trezor se zakládá" with "Zkusit znovu".
  • The bound. The receipt now carries its time (pendingSince, required with the key in toISOString form). Only a receipt older than 15 minutes (receiptBoundMs; a request times out at 30 s) that still matches nothing is taken for a creation that never happened. It is discarded, journaled as receipt-expired (no key, no id), and the vault is created once.
  • Refused creations. A creation the vault refuses with its answer (4xx but 429) created nothing and discards its receipt at once, so organization-refused still recovers on the next run. No answer, or a 5xx, keeps the receipt.
  • Tests (tests/vault-flow.test.ts):
    • Your reproduction: the POST succeeds with its answer lost, then one profile with an empty organization list, then a retry. Result: creating, one organization, one POST, receipt unchanged. The next setup finds it: connected, with that one organization and the receipt cleared.
    • A receipt that matches nothing (the POST never reached the vault) stays creating at 1 and 14 minutes, with no POST. At 15 minutes it makes exactly one organization, with receipt-expired journaled.
    • The record's form is in tests/vault-store.test.ts; the row's creating state is in tests/vault-view.test.ts.
    • Browser: a creation that never reached the vault reads "Trezor se zakládá" with "Zkusit znovu", and a retry stays there without a second creation.
  • F52 point 3 now states the rule (see also docs/environment-tools.md).

bun run check on 3425e71: 2623 pass, 0 fail. CI on it is green; its first attempt failed one test in tests/launchpad-hosted.test.ts, untouched here: the page's boot document, which waits at most 500 ms, was missing from one of two page loads. The re-run passed, and the flake is filed as #405. The branch is not rebased onto the newer main, because follow-up PRs build on it; a trial merge with main (ad19a61) merges cleanly and passes tsc and the Folder and vault tests.

Ready for another look at 3425e71.

@agentrozjedemeai agentrozjedemeai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@immakermatty — APPROVED on exact head 3425e71. The earlier orphaned-second-organization reproduction now remains creating through a temporarily empty profile, keeps the same receipt, sends only one POST, and subsequently connects to the original organization. A genuinely unmatched receipt waits through 1 and 14 minutes and creates once at the 15-minute bound; the bound’s residual delayed-visibility risk is stated in the PR. I inspected the receipt/membership/status/Launchpad paths and F52. Local isolated-checkout validation: 29 focused tests passed, plus 15 Launchpad/CLI/handover tests passed (1 macOS skip); static check (Biome, TypeScript, public guard, proof build and smoke) passed. Head CI is green, with zero open review threads. git diff --check reports one nonblocking trailing blank line in docs/decisions.md. Before merge, re-pin the vendored handover schema to the merged Machines #500 commit and repeat exact-head checks/review gates; no merge performed by me.

immakermatty added a commit that referenced this pull request Oct 13, 2026
… creation is not confirmed

#391 gained the state `creating` (the organization's creation was asked
for and is not confirmed yet; the next setup looks for it again, and the
Launchpad's start runs that setup). The page's row now says the vault is
being created, as for a running setup, with no way in until the vault is
the Environment's; it said "Not available here" before, through a default
branch. The row's words are now an exhaustive switch over the states, so
a state added later fails to compile instead of falling through.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
immakermatty added a commit that referenced this pull request Oct 14, 2026
…is unresolved

Since #391's `creating` state (an organization whose creation is not
resolved yet: a receipt with its time and no ids), the request core already
refuses it as `not-connected`, as every vault that is not ready: it needs
the recorded vault and Agenti by ID. A test now writes that record, in its
four-field form with `pendingSince`, and shows a new request and a save
refused while the status reads `creating`, and the waiting request saved
once the vault is ready again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
immakermatty and others added 9 commits October 14, 2026 14:57
Root decision 0198 (DEV-6631 task 638a, contract C3): the Environment's
technical account, which the handover's new `vault` member names (contract
C2), registers itself, creates the Environment's own organization with
POST /api/organizations (the organization key RSA-OAEP-encrypted to the
account's own public key, the organization key pair, the billing e-mail,
the handover's name and a first collection "Agenti"), remembers it by ID
and renames it when the handover's name changes. The account and the
vault come from the handover only; the guessed vaultwarden@<address>
account, the vault derived from Headscale and every collection-name match
are gone. State is keyed by the account, so a 0197 pilot's directory stays
readable beside it.

The Admin-approval and fingerprint-confirmation flow, its states, the
four-step dialog and the disconnect are removed. `lazurio vault setup`
replaces `connect`; the Launchpad runs the same setup at its start where
the vault needs it (the Executor pattern). The Tools row shows the state,
"Otevřít trezor" and one action only where a setup can move the vault on.

Environments connected the 0197 way keep working read only through the
frozen subset in src/vault/legacy-0197/ (status, the shared session and
F46 from the recorded collection) until their handover names a vault and
task 649 moves their items. F46 reads the own vault: the one item named
exactly like the secret anywhere in it; a work Environment serves its
Organization's apps, a personal one the Personalspace's.

Work in progress: the tests and the docs follow in the next commits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d handover member

Tests against the real consumers and the fake Vaultwarden, now with the
API-key login, the profile and the organization endpoints: the setup from
not allowed to connected, idempotent, renamed, a lost creation answer
recognized by its receipt, a gone organization and a refused API key
revoked and never replaced; the account opening its own organization key
from its master password down to Agenti's name; the frozen 0197 pilot with
and without `vault`, its directory untouched by the new account; the CLI;
the Launchpad over HTTP and its setup at start; the handover member, an
earlier Platform refusing it, and its redaction; F46 on the own vault and
the vault's rule for Personalspace modules; no value or token on argv, in
the journal or an answer.

Docs: decision F52 (superseding F43's collection model, amending F46),
environment-tools, launchpad-development, machine-handover, recovery,
public-development and module-adoption. The vendored handover schema's
`vault` member is aligned with the Machines shared contract and marked
pending in schema-provenance.json until the Machines pull request of task
637 publishes it. Template revision base-instructions-48 for the agents'
bitwarden text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e vault

The bitwarden tool's prompt a person copies for an agent spoke of the
Machine handover; towards people the place is the Environment (decision
0170, the wording guard), so it now says the network pre-allowed the
account for this Environment and gave it a vault or not. The module view's
F46 expectations follow the texts that now name the Environment's vault,
not its collection.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The handover's `vault` member is now the one Machines writes: the head of
the open Machines pull request #500 (DEV-6631 task 637, guest side), byte
for byte, which adds only the optional top-level member to #449's schema,
with a work account of the Environment's <vm>.<org> address and a personal
one of its <login> address. schema-provenance.json pins that head and says
in `pending` that it is re-pinned to the pull request's merge before this
one merges. The relay test keeps checking the relay member; the provenance
and the two account shapes are checked with the vault's member.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bw rewrites its store on every start, so a run without
BITWARDENCLI_APPDATA_DIR rewrites a default profile, a person's own bw
included. Every bw of the vault runs through bwCli (setup, status,
refresh, env's unlock, secrets, the 0197 pilot subset, the installer's
version check), which now refuses before anything runs unless the binary
and the data directory are absolute paths, and sets the directory last
on every run, so no step's variables can replace it.

The only other path that starts a bw, the version probe of Settings →
Tools, already gives it a fresh temporary directory (the catalog's
isolatedData) and removes it afterwards; tests/vault-store.test.ts now
pins both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…enti" on

Root decision 0198 point 1: the agents use the Environment's vault
themselves, so a vault they are not told about makes no sense. The
setup that records the vault's collection Agenti, which happens once
per vault, now turns the agents' switch on for bitwarden in the
Environment's Folder, at the Launchpad's start as with `lazurio vault
setup`: the change the switch itself makes, at the current revision,
refused as the switch is where the tool is not offered or the
Organization does not allow it (enableVaultForAgents in
src/vault/host.ts, called by the core outside the account's lock).

No later setup (a new session after a restart, a rename, a repair)
turns it on again, so a person who turns the switch off keeps it off;
a failure is journaled (agents-not-enabled) and never fails the setup.
The page no longer toggles the switch itself: after a setup it
followed ends connected, it reads the Folder again.

Tested in the core everywhere (tests/vault-flow.test.ts) and over HTTP
in the Launchpad's Folder on Linux, where the Folder offers the vault
(tests/launchpad-vault.test.ts).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The creation's receipt (the new organization's public key, recorded
before POST /api/organizations) was only looked for among the confirmed
memberships of one profile. A profile that briefly omitted the new
organization (an answer that was lost, a listing that came late, a
request that arrived late) made the next setup create a second
organization and overwrite the receipt, orphaning the first.

Now, while a receipt is unresolved, no setup sends another creation.
Each one looks for the organization that carries the recorded key among
the account's memberships of any status and records it once its
membership is confirmed; until then, and while nothing matches, the
setup and the local status report the new state `creating`, and the
Launchpad's start sets it up again. The receipt carries its time: only
a receipt older than 15 minutes (a request times out at 30 s) that still
matches nothing is taken for a creation that never happened, discarded
(journal receipt-expired, nothing else) and the vault created once. A
creation the vault refuses with its answer (4xx but 429) created
nothing and discards its receipt at once; no answer or a server error
keeps it.

The row says "Trezor se zakládá" with "Zkusit znovu"; F52 point 3 states
the rule. Tests: the review's reproduction (a lost answer, then one
profile without the organization: `creating`, one organization, found
by the next setup) and a receipt that matches nothing making exactly
one organization after its bound.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Machines #500, which adds only the optional top-level member `vault`
(DEV-6631 contract C2), is merged as 8b66889b and released as
v0.12.159, whose tag targets that merge. The vendored schema was taken
from #500's head and is byte-identical to the merge and to Machines
main (SHA-256 76a05804…), so only its provenance changes: the version
and tag v0.12.159, the merge commit, and the release as the pin's
update. The pending note is gone; docs/machine-handover.md and the
decision name the release.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main took F52 for the module generator (#394), so the vault decision
of this branch, written as F52 before that merged, is F53: its
heading, the notes on F43 and F46 that point to it, the section and
anchor in docs/machine-handover.md, and every comment, doc and test
that names it. The module generator's own references to F52 are
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@immakermatty
immakermatty force-pushed the agent/DEV-6631-environment-own-vault branch from 3425e71 to 7eab155 Compare October 14, 2026 13:15
immakermatty added a commit that referenced this pull request Oct 14, 2026
… creation is not confirmed

#391 gained the state `creating` (the organization's creation was asked
for and is not confirmed yet; the next setup looks for it again, and the
Launchpad's start runs that setup). The page's row now says the vault is
being created, as for a running setup, with no way in until the vault is
the Environment's; it said "Not available here" before, through a default
branch. The row's words are now an exhaustive switch over the states, so
a state added later fails to compile instead of falling through.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
immakermatty added a commit that referenced this pull request Oct 14, 2026
#391 renumbered the Environment's own vault from F52 to F53 when it was
rebased onto main, where F52 is the module generator (#394). This pull
request's references follow it: the addendum of 2026-10-14 is F53's in
decisions.md, hosted-entry.md, environment-access.md, environment-tools.md
and launchpad-development.md (with their anchors), and in the comments of
server.ts, members.ts and the vault page's HTTP tests. No reference to the
module generator's F52 changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@agentrozjedemeai agentrozjedemeai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@immakermatty — APPROVED on exact head 7eab155 (base a9f80c7). I rechecked the rebased changes against the previously approved 3425e71: the once-only creation receipt behavior is preserved; the Folder revision is 49 with its pinned digest, and the Bitwarden wording retains #328’s neutral form. F52 remains the module-generator decision and this vault decision and its links are F53. The vendored schema digest 76a058045be25b718caed8a04e533d67fa8666945bfa4fa0153d618bc4d78957 matches the released Machines v0.12.159 tag (8b66889bf4e00b111027f9b280423f4b9cdfcf4e) and Machines main; the pending provenance gate is cleared. Isolated checkout: 122 focused tests passed, 1 macOS-only skip; lint, TypeScript, public guard, proof build and smoke passed. Head CI is green; #413 and #414 track the reported unrelated flakes. Live pre-review gates: same head, mergeable, no open threads or competing review requests. The existing trailing blank line in docs/decisions.md remains nonblocking. No merge performed.

@immakermatty
immakermatty merged commit dace17d into main Oct 14, 2026
15 of 19 checks passed
immakermatty added a commit that referenced this pull request Oct 14, 2026
… creation is not confirmed

#391 gained the state `creating` (the organization's creation was asked
for and is not confirmed yet; the next setup looks for it again, and the
Launchpad's start runs that setup). The page's row now says the vault is
being created, as for a running setup, with no way in until the vault is
the Environment's; it said "Not available here" before, through a default
branch. The row's words are now an exhaustive switch over the states, so
a state added later fails to compile instead of falling through.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
immakermatty added a commit that referenced this pull request Oct 14, 2026
#391 renumbered the Environment's own vault from F52 to F53 when it was
rebased onto main, where F52 is the module generator (#394). This pull
request's references follow it: the addendum of 2026-10-14 is F53's in
decisions.md, hosted-entry.md, environment-access.md, environment-tools.md
and launchpad-development.md (with their anchors), and in the comments of
server.ts, members.ts and the vault page's HTTP tests. No reference to the
module generator's F52 changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
immakermatty added a commit that referenced this pull request Oct 14, 2026
… creation is not confirmed

#391 gained the state `creating` (the organization's creation was asked
for and is not confirmed yet; the next setup looks for it again, and the
Launchpad's start runs that setup). The page's row now says the vault is
being created, as for a running setup, with no way in until the vault is
the Environment's; it said "Not available here" before, through a default
branch. The row's words are now an exhaustive switch over the states, so
a state added later fails to compile instead of falling through.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
immakermatty added a commit that referenced this pull request Oct 14, 2026
#391 renumbered the Environment's own vault from F52 to F53 when it was
rebased onto main, where F52 is the module generator (#394). This pull
request's references follow it: the addendum of 2026-10-14 is F53's in
decisions.md, hosted-entry.md, environment-access.md, environment-tools.md
and launchpad-development.md (with their anchors), and in the comments of
server.ts, members.ts and the vault page's HTTP tests. No reference to the
module generator's F52 changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
immakermatty added a commit that referenced this pull request Oct 14, 2026
…is unresolved

Since #391's `creating` state (an organization whose creation is not
resolved yet: a receipt with its time and no ids), the request core already
refuses it as `not-connected`, as every vault that is not ready: it needs
the recorded vault and Agenti by ID. A test now writes that record, in its
four-field form with `pendingSince`, and shows a new request and a save
refused while the status reads `creating`, and the waiting request saved
once the vault is ready again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
immakermatty added a commit that referenced this pull request Oct 14, 2026
…is unresolved

Since #391's `creating` state (an organization whose creation is not
resolved yet: a receipt with its time and no ids), the request core already
refuses it as `not-connected`, as every vault that is not ready: it needs
the recorded vault and Agenti by ID. A test now writes that record, in its
four-field form with `pendingSince`, and shows a new request and a save
refused while the status reads `creating`, and the waiting request saved
once the vault is ready again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

2 participants