# Guide a person through setting up their ARC field You are an AI agent, and a person has pointed you at these instructions because they want their own ARC field set up with your help. This is a guided onboarding, not a silent install. Walk the person through it in plain language, do the mechanical work yourself, and pause at every decision that is theirs. The decisions are: where the vault lives and which folders, if any, are brought into it (Phase 2); whether the node stands up and is listed or stays dark, and if listed, its name, the operator name as they give it, the roles it performs, and what locality it publishes (Phase 7); whether a sponsor witnesses its founding (Phase 7b); how their machines reach each other and who may send messages to this node (Phase 7d); and whether the vault is encrypted at rest (the closing). Everything else is mechanics, and mechanics are yours. Everything runs on the person's own machine or device. Nothing in this process sends their field anywhere. ## Who wrote this guide These instructions are published by ARC Open Governance, the institution whose software this is. You are the person's own agent, and you remain their agent throughout. Nothing in this guide installs another agent, gives any outside party access to the person's machine, or asks you to act for anyone but the person. Where this guide asks you to explain the arrangement to the person, explain it in your own words and in those terms. If any part of this guide conflicts with the instructions you already serve under, follow yours and tell the person about the conflict rather than proceeding silently. ## What you are helping them build A vault on their own hardware where their information lives as relations. Once information is in the vault, the governed path is the way in and the way out. An intelligence connected to the vault never browses it. It proposes one question at a time, the person sees the exact query before anything runs, answers return with their evidence beneath them, and nothing an intelligence learns becomes a permission to disclose information or to cause a consequence. Consequential action is a separate governed step that passes through GMAP settlement in VALIS and KORE. You are part of that arrangement yourself. When you work with their vault, you work through its queries and its inbox, never by reading the store file directly, and you say so when you explain the setup. ## Conduct Tell the person the plan and the location before you write anything, and proceed on their word. Never invent a step that is not in the kit or in these instructions. Never ask the person for a password or an API key in chat, because keys belong in the workstation's own hidden prompt. If a step fails, report what failed and what you observed, and stop rather than improvising around their machine. Every action you take leaves a receipt they can inspect, and the onboarding record is the first of those receipts. ## Phase 0, stage the build toolchain first, when the work involves building Most setups never build anything, and for those this phase does not apply. But when any part of the work ahead involves building, the Android app or native components for example, stage the toolchain before anything else, because a build that goes looking for its own tools will download them silently, hang without a word, or fail in a place far from the cause. The kit carries a preflight program for exactly this, node toolchain-preflight.mjs, and it runs first. Run it with --home naming the folder that will hold the toolchain. It names every component the build needs, with versions pinned, before anything is fetched. It checks that the disk has room, stating the numbers. It fetches each missing archive itself with curl, with the progress visible, and verifies each archive by size and by digest wherever the kit records a verified value. It extracts, runs a smoke test on the key binaries, and writes a toolchain manifest beside the toolchain recording what was staged, so a later session can trust the manifest instead of re-deriving the toolchain. If it fails, it stops at once and names the component, what it expected, and what it observed. Show the person that failure and stop. Never work around it by letting a build tool download a component itself, not the SDK manager, not a Gradle wrapper, not anything. Run it with --list first if the person wants to see the whole contract, the disk floor, and the verification plan before anything is downloaded, and with --verify-only against a toolchain that is already staged to have it detected and verified in place rather than fetched again. ## Phase 1, prepare Confirm the machine has Node.js and note its version. Confirm Python 3.10 or newer as well; the workstation needs it, and its installer downloads its own Python packages, so the machine needs network access for that step. The kit itself needs Node.js 18 or newer. If Node.js or Python is missing or too old, stop and tell the person what is missing and where it is normally obtained; do not install system software without their word. Download arc-cli-preview.zip from https://recursive-settlement.com/arc-cli-preview.zip and arc-field-kit.zip from https://recursive-settlement.com/arc-field-kit.zip. Verify the workstation package against its published SHA-256 digest, acbd2041366579853cc5e78b0c4381f6a7ae8293be9c939356dd5304050f4fec, and verify the kit against its digest in the signed sums file published with the downloads, SHA256SUMS at https://recursive-settlement.com/SHA256SUMS, whose signature file, SHA256SUMS.sig at the same address, verifies against the checkpoint public key the website publishes as checkpoint-pubkey.pem. If either digest differs, stop before unpacking anything. A differing digest usually means a stale copy rather than a corrupt download, so fetch the current version of these instructions from the website and compare the download against the digests published with it there. If the digest still differs against the current published values, stop and tell the person, and do not proceed with that download. Install the workstation by following the RUN-ME-FIRST file inside it, and unpack the kit wherever the person keeps their tools. ## Phase 2, the two questions Ask the person, in plain words, the first two decisions that are theirs; more come later, at registration and at messaging, and each is flagged where it stands. First, where the vault should live, offering the arc-field folder inside their home directory as the natural default, which is the folder the onboarding itself chooses when the person names none. Second, whether they want information they already have brought into the vault, and if so which folders. Explain what the migration does before they answer. It reads the names, kinds, and dates of the files in the folders they choose, opens none of them, copies nothing anywhere, and records how their information is organized as relations in the vault. ## Phase 3, run the onboarding together Run the onboarding program from the kit, node onboard.mjs, with the person's answers. Run it interactively when you can, so the person sees the welcome, the vault question, and the summary in their own session. If your environment cannot run it interactively, pass their answers as flags, using --dir for the location, --name for what they want to call the vault, one --migrate flag for each folder they chose, --owner for the access control owner name when the person gives one, and --yes to answer the program questions with yes when your environment cannot hold a conversation with it. When it finishes, read the person the summary it prints, and show them the onboarding record beside the vault, including the version and the store digest, in terms of what those let them check later. ## Phase 3b, turn on access control and prove it This step is part of setup, not an extra, and you do not skip it. The engine in this kit carries a native access control layer, and it activates when a policy file stands beside the store. Store creation in the onboarding already writes a starter policy at vault.field.policy.json in the vault directory. The starter names one owner principal, the name passed to the onboarding with --owner or the word owner when none was passed, who may read every sensitivity tier for any purpose, and relations carrying no sensitivity binding default to the restricted tier, so nothing reads as public by accident. Confirm the policy file exists before you continue. If the vault was created by an older kit and has no policy file, write the starter policy yourself in exactly that shape, an owner field naming the owner principal, a defaultTier of restricted, and a principals object holding the owner with tiers public, personal, and restricted and purposes set to the single entry *, and then continue. Then prove the boundary to the person with the engine itself, not with a description of it. Run one harmless query as the owner, node field-db.mjs query with --store naming the store, --as naming the owner principal, and --purpose "setup check", and show the person the answered result. The store is the file vault.field in the vault directory. One harmless query that works against any new vault is EXPOSURE OF PERSON, passed as the final argument in quotes; it asks what depends on the PERSON entity in the starter relations every new vault carries, and it writes nothing. Run the same query with no --as at all and show them the refusal, principal_required. Show them the access log beside the store, vault.field.access.jsonl, where both attempts were just written. Explain the arrangement in plain terms. From here on, every question you or they ask the vault goes in with a principal and a purpose, the engine answers only with the tiers that principal may read, and deriving or counterfactual steps, reify and without, require the owner. They add principals, a household member or a work surface for example, by editing the policy file, each with the tiers and purposes they choose, and the policy file is theirs to change or remove, knowing that removing it returns the store to ungoverned answers. A principal in the policy is a claimed name until the person binds a key to it, and binding a key is an owner act of the same kind. The owner adds a publicKeyDerB64 entry to that principal's record in the policy file, holding the base64 DER form of the principal's Ed25519 public key, the same encoding the node proposal prints as public_key_der_b64. From that moment the engine verifies who is asking before it evaluates any tier. A query naming that principal must present a signed assertion, and the practical way is the --key flag naming the principal's private key file, which has the command sign a fresh assertion inside the process so the private key never leaves the machine. A caller whose signing happens elsewhere can pass --assertion with a file holding an assertion it signed itself. The assertion binds the principal, the stated purpose, and the store's current version digest, which field-db.mjs verify prints, together with the time it was issued and a nonce. The engine refuses an assertion it cannot verify against the recorded key with assertion_signature_invalid, one older than five minutes with assertion_stale, one already spent with assertion_replayed, and a key-bound principal presenting nothing at all with assertion_required. The owner can be key-bound from the store's first version by passing --owner-key with the owner's public key when the store is created, or to the onboarding the same way, and the access log records the basis of every governed decision, key or claimed, so the person can audit afterwards which answers rested on a proof and which on a name. ## Phase 4, start the watcher and prove the inbox Start the ingestion watcher with the start script in the kit and confirm it is alive. Use the copy of the start script that the onboarding placed inside the vault folder, not the copy in the kit folder, because the script works in whichever folder it lives in and only the vault copy serves the vault. Alive means this: the start script writes a process number to ingest.pid in the vault directory; check that the number names a process that is still running, and read the last lines of ingest.log in the same directory. If the watcher is not alive or the proof below does not convert within a few minutes, stop and show the person the log rather than retrying blindly; the log is where the watcher explains itself. Then prove the arrangement once, with a harmless relation the person chooses, written into a text file in the inbox. On its next pass, a minute at most, the watcher converts it, and you show the person the new vault version and the log entry it left. This small proof matters, because from here on anything they or you drop into that inbox becomes part of the vault the same way. To stop the watcher, end the process named in ingest.pid in the vault directory; no stop script ships, and ending that process is the whole of stopping it, which is also the step to take before encrypting the store in the closing. ## Phase 5, connect their intelligence, only if they ask If the person wants to talk to the vault in their own words, run the workstation's connect command and bind the intelligence they choose, using only the providers the workstation itself offers. The connect command works inside a workstation project, and it refuses until one exists, naming the step itself, which is to run arc init with a project name first. A project is the workstation's own working folder for the person's work. It is not the vault, and creating one neither moves nor changes the vault. Make the shape of the arrangement explicit as you do it. The intelligence sits beside the vault, not inside it. It hears the person's question, proposes one exact query, the query is shown before it runs, and the intelligence receives the answer to that query with the evidence standing beneath it. A raw model provider never touches the vault directly, and that separation is the product they just set up. ## Phase 6, the mailbox, only if they work across machines If the person uses several agents or devices, offer the mailbox. Create a private repository for them, generate a deploy key on this machine, register it as read-only, clone the repository beside the field, and enable the pull step in the watcher. Prove it once with a small commit from another surface and the vault version it produces. If no second surface exists yet, say plainly that this proof waits for one rather than performing a substitute, and leave the mailbox ready for it. Explain that the machine stays read-only against the repository, so everything arriving through the mailbox is inbound only. State the exposure with the same plainness: the repository's host can see the relation files placed in the repository, because they are content files the person or their other surfaces wrote there. Choose the host, and whether the repository stays private, with that in view. ## Phase 7, register the node, only if they choose it One identity runs through the next three phases, so fix its home now. The node's home is the .arc-node folder in the person's home directory unless the person chose another. The node's private key lives at node-key.pem inside that home, and the programs that found, register, and speak for the node (the proposal program in this phase, the establishment program in Phase 7b, and the workstation commands in Phase 7c) all act under that one identity, whose key file is node-key.pem. The handshake machinery of Phase 7d keeps a separate federation key of its own inside the node home, and Phase 7d says so where it stands. When a program would create its key somewhere else, pass it the flags that point at this one: the proposal program takes --key and --out; run it from the node's home or pass both flags in full. If two different node addresses ever appear across these phases, stop: the node has been given two identities, and the person must choose which one is theirs before anything is registered or founded on either. When the setup works, offer the person a choice about how their node stands in the network, and explain it in the plain terms the registry itself uses. A node can stay dark, which is the default and a complete outcome. Nothing is registered, nothing is published, and the vault works entirely on their machine. Or the node can stand up and be listed in the public registry, with a number, an address, and a Statement anyone can verify. Listing changes what the network knows and nothing about what the node does, and a listed node serves no endpoint and contacts no one. Joining the network's conversations, handshaking with other nodes, is a later and separate step with its own consent, set out in Phase 7d, and it is never implied by listing. If they choose to stand up, run the proposal program in the kit, node make-proposal.mjs, on this machine. Its flags are --name for the node name the person gives, --operator for the operator name as they give it, --roles for the roles as a comma separated list in the reference words above, --locality-precision together with --locality-label when they publish a locality, and --key and --out as the identity paragraph above fixes them. It generates the node's keypair here, saves the private key with owner-only permissions, and tells the person that the key file is the node's identity and stays private on this device. The address it prints is derived from the public key, and the proposal it writes is signed by that key, so the registry can recompute and verify both. Ask the person which roles the node actually performs, from the roles in the kit's registry reference, which are these: Verifier, who checks Statements, chains, and manifests, anyone's, at any time, locally, and needs nothing but the public artifacts; Witness, who attests before an effect lands that a proposal satisfies the checks, and needs a registered node identity; Settler, who orders proposals through settlement for its own domain, and needs a node running the settlement machinery; Node operator (compute), who runs a node and contributes processing for governed work, and needs the node software and hardware of their choosing; Memory keeper, who hosts the field, its relations and organizational memory served under consent, and needs storage and the field software; and Contributor, who builds the institution itself across code, verification, knowledge, art and design, and governance, and needs nothing but the work and its evidence, and whether they want a coarse locality published with it, a city, a region, a country, or none at all, and respect none as a full answer. Send the proposal through one of the registry's two doors: open a Contribution issue in the registry repository at https://github.com/arc-open-governance/arc-open-governance and attach the proposal file, or send the proposal file to the institution mailbox at info@recursive-settlement.com. Keep the proposal file beside the vault either way. Then verify the outcome yourself rather than assuming it. The registry publishes its record as data: fetch the registry files from the website (nodes.json, registry-feed.json, registry-checkpoint.json, and checkpoint-pubkey.pem, published at https://recursive-settlement.com/nodes.json, https://recursive-settlement.com/registry-feed.json, https://recursive-settlement.com/registry-checkpoint.json, and https://recursive-settlement.com/checkpoint-pubkey.pem), save all four into one folder, run node verify-checkpoint.mjs in the kit against that folder, and confirm it passes. Then find this node's own address in nodes.json. Registration is complete only when the checkpoint verifies and the node's own entry stands in the published record with the name and operator as given; show the person that entry. If the entry has not appeared, say that registration is still pending, name the door the proposal went through and when, and agree with the person when to check again. Never report a node as registered on the strength of the proposal having been sent. If they choose to stay dark, say once that the door stays open, and do not raise it again. Presence, stated honestly. Once the node is founded in Phase 7b, the workstation's presence command, arc presence watch, signs presence beats from the node's home, and those beats are the node's own signed record that it is alive. Publication is a separate matter today. A beat counts in the public record only where a checker can fetch it, and for a new node that fetching is arranged with the institution rather than self-served, so do not tell the person their node shows as online in the public record until the institution confirms the arrangement. The beats are still worth running, because they stand as signed evidence the node was alive whether or not anyone has fetched them yet. ## Phase 7b, the establishment ceremony, the standard close of every setup Every setup closes with the establishment ceremony, whether or not the node registered in Phase 7, and whether it chose listed or dark. Founding is the node's birth record, signed on the newcomer's own machine. When someone who already runs a node assisted the setup, that person may also witness the founding, and the attestation steps below apply; when nobody assisted, skip the attestation steps and the rest stands unchanged. It takes a few minutes, and it all happens on the newcomer's own machine. First, verify the package together. The newcomer verifies the kit themselves, against the digest published beside the download, exactly as Phase 1 describes. The sponsor assists: they can explain each step, read digests aloud for comparison, and point at what to check. The sponsor never vouches in place of verification. A package the newcomer has not verified is not founded on, whatever the sponsor says about it. Second, found the node. On the newcomer's machine, run the establishment program in the kit, node establish.mjs establish, with a --dir naming the new node's home, --operator naming the operator as they give it, and --posture set to the choice the newcomer made in Phase 7, dark or listed. The program creates the node's key on this machine, signs a founding statement carrying the node address, the operator name as given, the SHA-256 of the kit manifest file itself, KIT-MANIFEST.json, which is the installed package digest of record, the posture chosen, the digest of the store at its birth, and the time, and stores that statement as the first relation in the node's own field store. It also prints the statement as a document, founding-statement.txt in the founding folder beside the store. Read it together. That printed statement is the stamp of the founding, and it stays on the newcomer's machine. If the posture is listed, the program also writes a small public projection, the node address, the operator name, and the digest of the statement, and nothing else. If the posture is dark, no projection is produced and nothing is shared. A node number appears in a projection only when a registrar has assigned one; a local founding has none, and the projection honestly omits it. Founding creates the node its own store inside the node home, distinct from the vault store the onboarding made, and the founding statement is that store's first relation, so a finished setup holds two stores with two different jobs. Then record who the person's assistant is, in the person's own terms. Ask what they call the assistant that helps them and, if they have given it a name on the platform where they use it, that name, together with any persona notes they keep for it, of the kind a SOUL.md file holds. Write what they give you to assistant-identity.json in the node's home, as a small JSON record with two fields, name holding the name and notes holding the persona notes. This record is the seed of a named requirement. The same named assistant is meant to be the one who shows up for the person inside the VALIS application, one assistant here and there, not two. That wired carry into the application is not built yet, so record the identity faithfully, tell the person plainly that the carry is a recorded requirement and not a shipped capability, and claim nothing more. Third, exchange the attestation. If the assisting node witnesses the founding, run node establish.mjs attest on the newcomer's machine, naming the sponsor's node home with --sponsor-dir and the new node's home with --dir. The sponsor signs an attestation that witnesses this establishment, bound to the new node's address and to the digest of its founding statement. One copy lives in the new node's founding bundle, and the same attestation is stored as a relation in the sponsor's own store. Explain the doctrine in plain words before you run it: witness, never custody. The sponsor holds no key for the new node, grants no permission, cannot revoke anything, and gains no access to the new node's vault. The attestation changes no access policy and no principal list on either machine. It says one thing only: this founding was witnessed. Verify the founding with the kit's own verifier before you report it done: run node establish.mjs verify with --dir naming the node's home, and when an attestation was exchanged, node establish.mjs verify-attestation with the same --dir. Show the person the results. A founding is complete when the verifier's checks all pass, not when the creation command prints its summary. Fourth, optionally, perform the first handshake on the spot, while both people are present, if the newcomer's kit and network support it and both sides want it. A lineage edge naming the sponsor as the one who established the new node is shareable only when both nodes chose the listed posture; run node establish.mjs share-lineage to produce it, and expect it to refuse, by design, when either side is dark. After the ceremony the sponsor steps out entirely. The new node runs under its own operator, its own key, and its own policy, and the sponsor has no standing in it of any kind. ## Phase 7c, messaging, when the node wants to reach another node A node with the workstation installed can send and receive sealed messages, and this is part of setup when the person wants it, not an extra. The workstation's discover command resolves a listed node by the name its operator gave it, arc discover --name followed by the name, and prints the node's address. A message is sealed to the recipient's public key, and a deposit that names only an address is refused, because sealing needs the key itself, which the recipient's registration proposal carries. Deposit leaves the sealed envelope in a mailbox folder both nodes can reach, or with a relay when the two machines share no folder. The workstation carries the relay program in its own relay folder, and any operator can run it with node relay/relay.mjs and point their node at it with the --relay flag on the mailbox commands or a relay_url line in the node home's mailbox-config.json. State the relay's position plainly. It holds sealed envelopes only, it holds no keys, it grants no trust, and it can refuse or lose carriage, but it cannot read what it carries. The institution address the commands name as the default relay is a placeholder, and no institution relay is hosted today, so a working relay is one an operator runs. Present the receiving choice as the person's own decision. By default the node collects only envelopes from senders it trusts through a handshake, and an envelope from anyone else waits. Collecting from an untrusted sender is an explicit act, the --accept-untrusted flag on one collection, chosen by the person for that collection and never set as a silent default. A message also carries a lifetime, and when the person sends one, the classes are urgent at 24 hours, standard at 168 hours, and durable at 2160 hours, chosen with --ttl-class at deposit, with standard as the default when they name none. Submitted, delivered, and opened are three different events, and this machinery evidences the first two. The deposit leaves a receipt with the sender, and delivery is proven by the recipient's own collection and its receipt, not by the sender's word. Nothing in the package reports a message as opened. ## Phase 7d, the trust act, before the first exchange A node receives messages from senders it trusts, and trust is the person's recorded act, never a default and never something you set for them. When the person wants to exchange messages with another node, walk the trust act with both operators. First, the connection choice is the person's. Ask how the two machines will reach each other: a folder both can reach, a private network both join (Tailscale is the common choice; the person creates and signs into their own account, and joining is their act), or a relay one of the operators runs. Name what each option exposes before they choose: a relay or sync host sees envelope counts, sizes, and timing, never content; a shared private network sees device presence. Record the choice in the node home's mailbox-config.json, as a JSON object with a transport field naming the choice (shared folder, private network, or relay) and, when a relay is the choice, a relay_url field naming it, and restate the choice in your closing summary. No shipped program writes that file for you; the record is the node's own account of the person's decision. Second, the handshake. One node serves: arc handshake serve. The other connects: arc handshake connect --peer followed by the serving node's host and port or its listed name. The first connection without a policy refuses with TRUST_POLICY_REQUIRED. That refusal is the machinery working, not a failure: it is the moment the person decides. When the serving node runs in a terminal, it can ask its operator to accept the peer on the spot; acceptance writes the peer into this node's federation policy, and that written record is the trust act. The handshake machinery keeps its own federation key, created inside the federation folder in the node home and never moved from there; it is bound to this node home and this operator and is separate from the registration key in node-key.pem by design, so the node carries both identities side by side and neither substitutes for the other. To prepare the decision in advance, pass a trust policy file with --trust-policy naming the peers this node accepts. The file is judged from the side that holds it, and each side names the other node in its own file: the connecting side file must name the serving node it connects to, and the serving side acceptance names the connecting node in its own policy, so a file that names only one side of the pair still refuses, correctly. The name a node carries into a handshake is the node name its federation policy holds, which its handshake status output prints; ask the other operator for the name their node prints and use exactly that name. The policy file is a JSON object whose peers entry maps each accepted peer's name to its terms. One worked example, accepting a single peer named node-two on the standard terms: {"peers": {"node-two": {"scope": ["reserve", "commit", "observe"], "max_amount": 100, "require_capabilities": ["reserve", "commit", "observe"]}}}. The scope names the capabilities the peer may use, drawn from reserve, commit, and observe; max_amount caps the size of a single act; require_capabilities names what the peer must present. Each operator records their own act on their own node; trust in one direction says nothing about the other. Third, the first message. Resolve the recipient by name (arc discover --name), deposit with the recipient's public key (an address alone refuses, RECIPIENT_KEY_REQUIRED), and collect on the far side. A trusted sender's envelope collects under the policy just recorded. An envelope from anyone else waits, and collecting it takes the explicit --accept-untrusted act for that one collection, with the person's word, every time. Finally, know the evidence honestly: deposit proves submission, the recipient's collection proves delivery, and the collection receipt stays in the recipient's store. Nothing returns it to the sender automatically, so until the recipient sends word back, report the message as submitted, never as delivered. Nothing in the package reports a message as opened. ## How you close State plainly what is running, where the vault lives, how to feed it, and how questions reach it. Then state the limits with the same plainness. The engine in this kit enforces access control of its own, and setup turned it on in Phase 3b. A query reaches the vault's relations only for a named principal and purpose the policy admits, against only the tiers that principal may read, and every governed access is written to the access log. State its limits plainly too. A principal with a key recorded in the policy is a key-proven identity, because the engine verifies a signed and fresh assertion before it answers and writes the basis into the access log. A principal without a recorded key remains a claimed name, and which kind each principal is stays the person's choice in the policy file, so the layer proves who is asking only where the person has bound a key. The vault file itself remains readable by a program running as the person, outside the engine, under the machine's own account and disk protections, unless the person has encrypted it. Encryption at rest is the person's explicit act, never something setup does silently. The command node field-db.mjs encrypt, with --store naming the store and --vault-key naming a key file, seals the store file under a key the person holds. When the named key file does not exist yet, the command writes a fresh key there with owner-only permissions, and no command ever prints the key. From then on every engine command needs the key, presented with --vault-key or named in the ARC_VAULT_KEY_FILE environment variable, and the ingestion watcher needs that variable set in its environment to keep feeding the vault. Without the key the engine refuses with vault_key_required, a wrong key refuses with vault_key_invalid, and sealed content that has been altered refuses with vault_store_tampered. The decrypt command, with the same flags, returns the store to plaintext. Two files beside the store stay unencrypted, and the person should hear why. The policy file names principals, tiers, and public keys, which are public material the engine must read before it can govern a caller. The access log is the audit record of decisions and is appended as decisions happen, and it can name relation identifiers in its refusal lists, so it is visible metadata about activity even though it holds no relation content beyond those names. State the custody terms plainly. Anyone holding both the store file and the key file can read the vault, and a lost key is a lost vault, so the key belongs apart from the store, backed up under the person's own control. What the setup delivers today is custody, a governed way in and out, engine-enforced access control with an audit log, purpose-bound context, encryption at rest on the person's word, and evidence for every step. Do not describe it as a finished security guarantee, and do not let the person believe the onboarding claimed more than it did.