diff --git a/AGENTS.md b/AGENTS.md
index 981f1cc..42a0e4e 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -3,48 +3,51 @@
Guidance for agents and developers working in this repo. This file is the source
of truth for how to build, run and not break things. `CLAUDE.md` points here.
-It deliberately does **not** restate versions, decisions or known upstream
-issues — those live in [`docs/roadmap-m1.md`](./docs/roadmap-m1.md), and a
-second copy would go stale. What the product _is_ — and is not — is specified in
-[`docs/m1-brief.md`](./docs/m1-brief.md). Work items live in
+It deliberately does **not** restate the design or the dependency versions. The
+design is in [`docs/architecture.md`](./docs/architecture.md); versions are
+pinned in `Cargo.toml` and `rust-toolchain.toml`. A second copy of either would
+go stale. Work items live in
[milestone M1](https://github.com/BootNodeDev/strata-vault-kit/milestone/1).
## What this is
-A white-label tokenized vault on Stellar/Soroban, built on the OpenZeppelin
-Soroban vault. An approved investor deposits USDC and receives `bvUSDC` shares;
-they redeem and get USDC back.
+A white-label RWA vault kit on Stellar/Soroban. Shares are a claim on an
+off-chain asset whose value is attested on chain, so no price exists at the
+moment an investor acts. Entry and exit are therefore requests: what goes in is
+escrowed, the next accepted attestation prices it, and the investor claims the
+result. Three states per side, none skipped: **pending, priced, claimed**.
-Two invariants the contract enforces:
+What the contracts enforce:
-1. **Entry is gated** by a post-KYC allowlist — the `deposit`/`mint` receiver,
- and both sides of `transfer`/`transfer_from`.
-2. **Exit is never gated and never pausable.** A de-listed holder can always
- leave. `withdraw`/`redeem` carry no allowlist check by design.
+1. **Entry is gated** by a post-KYC allowlist, checked on the receiver of a
+ subscription and on every share transfer.
+2. **A covered claim always pays.** Once priced and covered, a cash claim cannot
+ be blocked by a pause, a stale valuation, or the investor losing their
+ allowlist place. Priced claims are never re-priced and never identity-gated;
+ a delisted, non-frozen investor leaves through the exit-only cash path.
+3. **Cancellation is atomic and single-step**, open only until the attestation
+ that prices the request is accepted. There is no instant exit.
-Milestone 1 has no yield: shares stay 1:1. Testnet only. Not audited.
-
-## State of the repo
-
-Bootstrap only: documentation, issue templates and the toolchain pin. The Rust
-workspace arrives with the first contract crate, and the interface after that.
-The sections below describe how the project is built as each piece lands.
+Five authorities, each a native Stellar multisig: governance, compliance,
+attestation, treasury, guardian. Testnet only. Not audited.
## Reference base
[`stellar-vault-demo-dapp`](https://github.com/BootNodeDev/stellar-vault-demo-dapp)
-is our own working testnet demo. Its 188-line contract proves the design. Read
-it while building; do not port it wholesale. Its frontend is not carried over —
-M1 builds a new one designed around the role model.
+is our own working testnet demo, but it is **synchronous**: deposit and withdraw
+are priced at call time. It does not model the request lifecycle and its flow
+does not carry over. Read it for Soroban and OZ mechanics only.
## Build & run
- **Contracts:** `stellar contract build` — **not** `cargo build`. The OZ crates
enable an experimental `soroban-sdk` feature (`spec_shaking_v2`) that only
- works through the CLI wrapper (Stellar CLI ≥ 25.2).
-- **Tests:** `cargo test -p vault` (unit tests run against the in-memory `Env`).
-- **Toolchain:** pinned in `rust-toolchain.toml`. rustup installs it on first
- build.
+ works through the CLI wrapper. The devshell pins the Stellar CLI it expects.
+- **Tests:** `cargo test` from the repo root runs every workspace member against
+ the in-memory `Env`. There is no unit-test runner for `app/` or `app-lib/`;
+ `e2e/` runs Playwright separately. CI does not run the Rust tests yet.
+- **Toolchain:** `nix develop` provides it, or rustup honours
+ `rust-toolchain.toml`.
## Gotchas
@@ -52,30 +55,22 @@ Carried over from the reference base, where each one cost real debugging. They
apply as the corresponding code lands here.
- Build with `stellar contract build`, not `cargo build` (see above).
-- OZ vault wiring: `#[contractimpl(contracttrait)]` on **both** `FungibleToken`
- and `FungibleVault`; `type ContractType = Vault` goes **only** on
- `FungibleToken`; import `soroban_sdk::MuxedAddress` (the contracttrait macro
- references it).
-- Do **not** call `operator.require_auth()` inside overridden vault methods —
- `Vault::*` already authorizes, and a second call fails with
- `Error(Auth, ExistingValue)`.
-- `ed25519-dalek` v3 breaks the test build; pin to `2.2.0` if it resolves
- higher.
-- `motion` must be v12+ (`motion/react`); a bare `npm i motion` pulls v10
- (Motion One), which has no React entry.
-- USDC is a **classic asset** → an account needs a trustline to hold it.
- `bvUSDC` is a **Soroban contract token** → no trustline. Deposit is a single
- transaction with nested authorization; there is no separate `approve`. Get
- test USDC from Circle's faucet (pick Stellar) after establishing the
- trustline.
+- A SEP-56 vault is **not** the base here: its interface assumes the price
+ exists at call time, which a request lifecycle cannot express.
+- `ed25519-dalek` is transitive and unpinned by any manifest. A newer major
+ breaks the test build; hold it back in the lockfile if compilation fails
+ there.
+- The deposit asset is a **classic asset** → an account needs a trustline to
+ hold it. The share token is a **Soroban contract token** → no trustline.
+ Deposit is a single transaction with nested authorization; there is no
+ separate `approve`. When the deposit asset is USDC, Circle's faucet (pick
+ Stellar) issues test units once the trustline exists.
- Two network configs must agree: `environments.toml` is the network the
CLI/scaffold **deploys** to, `app/.env` (`PUBLIC_STELLAR_*`) is the network
the **frontend** reads at runtime. The scaffold default is local, so both need
setting or the UI talks to the wrong chain.
- Generated contract clients ship their `src/` but not their `dist/`. A fresh
clone builds the client before the app, or `tsc` cannot resolve the module.
-- No `Cargo.lock` is committed until the first contract crate lands (#20); see
- the comment in `Cargo.toml`.
- `app-lib/clients/index.ts` is auto-generated and rewritten on every build or
redeploy. Do not hand-edit it; customize by importing the client under `app/`.
@@ -83,7 +78,7 @@ apply as the corresponding code lands here.
Not recorded here on purpose. The reference base kept them in this file and they
drifted: its `AGENTS.md` and its generated client pointed at two different vault
-contracts. The addresses emitted by the deploy script (#15) are authoritative.
+contracts. The addresses emitted by the deploy script are authoritative.
## Conventions
diff --git a/CLAUDE.md b/CLAUDE.md
index 32f1ca2..38e9aa2 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -2,5 +2,11 @@ See [AGENTS.md](./AGENTS.md) for what this repo is, how to build and run it,
network configuration, and the Stellar-specific gotchas. It is the single source
of truth for this project's conventions.
-Versions, decisions and known upstream issues live in
-[`docs/roadmap-m1.md`](./docs/roadmap-m1.md) — not duplicated anywhere else.
+The design lives in [`docs/architecture.md`](./docs/architecture.md) — the
+source of truth for what the protocol does and why. It wins on the **what**:
+properties, invariants and guarantees. On the **how**, a disagreement with the
+code is resolved explicitly rather than by default — a mechanism that proves
+better in the code is a reason to amend the document, not a defect.
+
+Dependency versions are pinned in `Cargo.toml` and `rust-toolchain.toml` — read
+them there rather than from prose.
diff --git a/docs/architecture.md b/docs/architecture.md
new file mode 100644
index 0000000..aa7a351
--- /dev/null
+++ b/docs/architecture.md
@@ -0,0 +1,395 @@
+# Technical Architecture: Strata
+
+**Product:** Strata, an RWA lifecycle protocol for attested-value assets:
+request-based subscriptions and redemptions priced against on-chain guarded
+attestations, built on OpenZeppelin's Stellar contracts. Distributed as a kit:
+each operator deploys, configures and brands an independent white-label
+instance. **Chain:** Stellar. Soroban smart contracts; classic assets consumed
+through their Stellar Asset Contract (SAC) interface. **Deposit asset:** any
+classic Stellar asset chosen at genesis (typically a USD stablecoin such as
+USDC). **Maintainer:** BootNode (bootnode.dev).
+
+Shares in this vault are a claim on an off-chain asset whose value is attested
+on chain. No price exists at the moment you act, so entry and exit are requests:
+what you put in goes into escrow, the next accepted attestation prices it, and
+you claim the result.
+
+---
+
+## 1. Design principles
+
+1. **Configured, not built.** Each operator deploys an independent instance: no
+ factory, no shared state. A deployment is defined by its configuration and
+ five authorities (native Stellar multisig accounts). Everything an operator
+ brands or configures lives outside the trust boundary; everything inside it
+ is the same code for every adopter.
+
+2. **Built on OpenZeppelin, differentiated above it.** The share token is OZ's
+ SEP-41 token with the SEP-57 RWA extensions (freeze, forced transfer,
+ recovery); access control, pausable and upgradeable come from OZ crates.
+ Dependencies are pinned to exact versions and audit inheritance is evaluated
+ component by component; what Strata adds stays within its own audit scope.
+ What OZ does not cover is the layer Strata adds: the attested valuation
+ oracle, request-based flows priced against attestations, split reserve
+ accounting, and the operational surface.
+
+3. **Request-based entry and exit.** The exact price of a share does not exist
+ when an investor acts; it is attested afterwards. Entry and exit are
+ requests: funds or shares go into escrow, the next accepted attestation
+ prices them, and the investor claims the result. This is the ERC-7540 pattern
+ with two differences: cancellation is a single step that closes when the
+ pricing attestation arrives, and the price is set by each attestation for
+ every pending request, not by a manager.
+
+4. **Attested NAV.** The reporter attests the share price itself, computed
+ off-chain from the deployed value and the vault's public figures under a
+ documented methodology. The contract validates, stores and exposes it. Every
+ on-chain operation preserves that price by construction: pricing a deposit
+ releases escrow into the reserve and mints shares in proportion, pricing a
+ redemption burns shares and fixes the matching liability, and a custodian
+ transfer moves value between pockets without changing the total.
+
+5. **Payable claims always pay.** Neither the guardian pause, a delisting, nor a
+ stale valuation can block the payment of an already-priced, funded cash
+ claim. A pause can delay unpriced requests. Priced claims are never re-priced
+ and never identity-gated. A delisted, non-frozen investor exits through the
+ exit-only cash path. Outside this guarantee, disclosed as trust assumptions:
+ a frozen investor, deposit-asset issuer controls, and reserve liquidity.
+
+6. **Split accounting, with priced and payable as separate states.** The vault
+ exposes committed (priced redemption liabilities), cancellable escrow
+ (pending subscriptions the investor can still recall) and free reserve.
+ Escrowed subscriptions never leave the vault. Committed can exceed the liquid
+ reserve; that gap is an explicit on-chain shortfall, outbound transfers are
+ blocked while it exists, and priced claims stay payable in FIFO order as
+ treasury tops up. A liquidity shortfall is not insolvency: solvency compares
+ total attested assets against liabilities and is handled by attested losses
+ and governance.
+
+## 2. Component overview
+
+Orange marks what only Strata provides; white is the existing ecosystem the kit
+consumes or integrates.
+
+```mermaid
+flowchart TB
+ subgraph FE["FRONTEND · WHITE-LABEL"]
+ LP["Investor dApp
request · claim ·
cancel · position"]:::strata
+ ADM["Admin panel
allowlist · valuation ·
pause · treasury"]:::strata
+ end
+
+ subgraph ON["ONCHAIN · SOROBAN"]
+ subgraph OZ["OpenZeppelin base"]
+ ST["SEP-41 + SEP-57
share token"]
+ AC["Access control · pausable
· upgradeable"]
+ end
+ SAC["Deposit asset ·
Stellar Asset Contract"]
+ subgraph SM["Strata modules"]
+ V["Vault · request lifecycle"]:::strata
+ OR["Valuation oracle ·
guardrails · NAV"]:::strata
+ SA["Split accounting ·
shortfall exposure"]:::strata
+ RQ["FIFO redemption coverage
· exit-only path"]:::strata
+ MGR["Manager ·
token authority"]:::strata
+ IVC["Compliance module
SEP-57 identity + rules"]
+ end
+ AUTH["Role framework
5 multisig authorities"]
+ end
+
+ subgraph OFF["OFF-CHAIN · OPERATOR"]
+ TR["Treasury ops"]
+ VS["Valuation source
attestation data"]
+ KYC["KYC process"]
+ end
+
+ subgraph RW["REAL-WORLD STRUCTURE"]
+ CU["Legal wrapper · custody ·
the asset"]
+ end
+
+ LP -->|"requests · claims"| V
+ ADM -->|"admin operations"| AUTH
+ OR ---|"attested value + proof ref ↑"| VS
+ IVC ---|"verified addresses ↑"| KYC
+ SAC ---|"reserve in / out"| TR
+ TR -->|"transfer_to_custodian"| CU
+ VS ---|"valuation data ↑"| CU
+
+ classDef strata fill:#FFE0B2,stroke:#E65100,stroke-width:2px
+```
+
+Authority and contract wiring:
+
+```mermaid
+flowchart LR
+ subgraph Investor
+ W[Wallet
Freighter / Wallets Kit]
+ LP[Investor dApp
backend-free]
+ end
+
+ subgraph Operator["Operator (off-chain)"]
+ KYC[KYC process
operator's own stack]
+ VAL[Valuation source
fund accounting]
+ CUST[Custodian
real-world structure]
+ end
+
+ subgraph Authorities["Authorities (native Stellar multisigs)"]
+ GOV[governance]
+ CMP[compliance]
+ ATT[attestation]
+ TRE[treasury]
+ GRD[guardian]
+ end
+
+ subgraph Soroban["Soroban contracts (the kit)"]
+ V[Vault
requests, pricing,
reserve accounting]
+ ST[Share token
OZ SEP-41 + SEP-57 ext]
+ MGR[Manager
token authority passthrough]
+ CM[Compliance module
SEP-57 identity + rules,
allowlist]
+ end
+
+ OPS[Admin panel
propose / review / sign / execute]
+
+ W --> LP --> V
+ KYC --> CMP
+ VAL --> ATT
+ GOV & CMP & ATT & TRE & GRD --> OPS --> V
+ OPS --> MGR --> ST
+ CMP -->|writes via Manager| CM
+ ST -.->|identity + transfer rules| CM
+ TRE -.->|free reserve only,
zero shortfall| CUST
+ V ---|SAC interface| USDC[Deposit asset]
+```
+
+Both interfaces are backend-free: they read contract state and build
+transactions that the authority multisigs sign. The chain never sees KYC data or
+valuation methodology, only their outputs: an allowlisted address, an attested
+number with a proof reference.
+
+## 3. Components and authorities
+
+| Component | Role | Controls |
+| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Vault** | Request lifecycle, pricing, split reserve accounting, custodian transfers, upgrade control | One authority per privileged entrypoint; upgrades behind a governance timelock with an exit window |
+| **Share token** | OZ SEP-41 + SEP-57 RWA extensions: freeze, forced transfer, recovery, identity and compliance checks on every transfer, independent transfer pause | Token manager authority held exclusively by the Manager contract, never a human key |
+| **Manager** | Token manager passthrough: every privileged token operation goes through it and is checked against roles | Role-gated |
+| **Compliance module** | Implements the SEP-57 identity and rules interfaces the share token consults, with the allowlist as its only rule | Written only by the compliance authority via the Manager; replaceable by OZ's identity verifier and compliance contracts (with RWA Wizard modules) without touching the token |
+| **Five authorities** | governance (parameters, roles, timelocked upgrades), compliance (allowlist, token interventions), attestation (valuation only), treasury (reserve movements only), guardian (pause; never payable claims) | Native Stellar multisig accounts; treasury and guardian distinct, compliance distinct from governance and treasury |
+| **Custodian** | Off-chain party holding the real-world structure; a genesis-configured slot rotatable only by governance | Not an on-chain authority |
+
+Each authority's threshold is sized to the quorum that authority requires.
+Signing of privileged operations through a coordinator is verified end to end,
+not assumed.
+
+## 4. Request lifecycle
+
+Every position change is a request with three states: **pending, priced,
+claimed**. Each accepted attestation prices every pending request; requests are
+then settled individually, by any account, so no attestation processes an
+unbounded batch and no investor can choose their price.
+
+### 4.1 Subscription
+
+- Request: verifies the receiver is allowlisted, moves the deposit asset into
+ escrow. At most one active request per controller.
+- Pricing: the escrow leaves the cancellable bucket, the share quantity is set
+ at the attested price, and the shares are minted and held for the investor.
+- Cancellation: atomic, available until the request's pricing attestation is
+ accepted; returns the escrowed asset in full.
+- Share claim: re-verifies the receiver and delivers the shares. If verification
+ fails, the position remains shares and exits through the redemption lifecycle
+ at the then-current price. No nominal refund exists after pricing.
+
+### 4.2 Redemption
+
+- Request: moves shares into escrow, no admission limit.
+- Pricing: the escrowed shares are burned and a fixed cash liability enters
+ committed at the attested price. Priced claims are never re-priced.
+- Coverage: a priced claim is payable when the liquid reserve covers it, in FIFO
+ order. An earlier unpaid claim never blocks a later one that is already
+ covered. The gap between committed and liquid reserve is the on-chain
+ shortfall treasury must top up.
+- Cash claim: pays the fixed amount; it does not depend on identity. A delisted,
+ non-frozen investor uses the exit-only cash path and cannot cancel back to
+ shares.
+
+```mermaid
+sequenceDiagram
+ participant I as Investor (allowlisted)
+ participant V as Vault
+ participant O as Attestation authority
+ I->>V: request_deposit(amount), asset to escrow
+ Note over V: pending, cancellable
+ O->>V: attestation
+ Note over V: priced: shares minted and held,
cancellation closed
+ I->>V: claim, re-checks allowlist
+ V-->>I: shares delivered
+```
+
+```mermaid
+sequenceDiagram
+ participant I as Investor
+ participant V as Vault
+ participant O as Attestation authority
+ participant T as Treasury authority
+ I->>V: request_redeem(shares), shares to escrow
+ O->>V: attestation
+ Note over V: priced: shares burned,
cash liability fixed
+ alt liquid reserve covers the claim
+ I->>V: claim
+ V-->>I: deposit asset paid
+ else reserve short
+ Note over V: shortfall visible on-chain
+ T->>V: return_from_custodian(funds)
+ I->>V: claim
+ V-->>I: deposit asset paid
+ end
+```
+
+## 5. Valuation and accounting
+
+The NAV is a permissioned attestation of the share price, published with a proof
+reference. The reporter computes it off-chain:
+
+```text
+share_price = (deployed_value + onchain_reserve - committed) / share_supply
+```
+
+where deployed_value is the attested off-chain value and the other three figures
+are read from the vault's public surface. Cancellable escrow is not part of it:
+pending subscriptions hold no shares yet. The contract does not recompute the
+price; it validates the report, stores it, and exposes it together with the
+liquidity figures it does own:
+
+```text
+liquid_reserve = reserve - cancellable_deposit_escrow
+free_reserve = max(liquid_reserve - committed, 0)
+shortfall = max(committed - liquid_reserve, 0)
+```
+
+**Attestation guardrails:** the reporter is a multisig, never a single key. Each
+attestation carries the share price and a proof reference; attestations are
+ordered by their acceptance time on the ledger. The price must stay within
+configured bounds, a minimum cooldown bounds frequency, and the deviation cap is
+asymmetric: upside is bounded per update, downward updates are uncapped so
+losses are recognized immediately.
+
+**Freshness and pause:** each attestation opens a validity window; when it
+lapses the feed is stale and new requests stop being priced. Guardian or
+governance can pause the vault: new requests, pricing and custodian transfers
+stop; payable claims, pending cancellations and refunds continue; attestations
+that pass the guardrails are still accepted, so recovery never deadlocks. Only
+governance lifts the pause, and only while the latest attestation is fresh.
+Paused and stale are independent: freshness lapses on its own, the pause is a
+decision.
+
+## 6. Compliance
+
+- The share token follows the SEP-57 topology: it consults identity for every
+ receiver and rules for every transfer. The kit ships one compliance module for
+ both, with the allowlist as its only rule; an operator needing richer rules
+ replaces it with OZ's contracts without touching the token.
+- KYC happens wherever the operator runs it; the chain sees only its output. The
+ compliance authority writes allowlist entries via the Manager.
+- Token interventions (freeze, unfreeze, forced transfer, recovery) are
+ compliance operations via the Manager, available even while the vault is
+ paused.
+
+## 7. Treasury and custodian
+
+- The custodian is a genesis-configured slot; only governance can rotate it.
+ Transfers to the custodian move free reserve only, only to that address, and
+ only while the shortfall is zero.
+- Transfers from the custodian are always open and credit only assets actually
+ received.
+- The exposed figures (share price, liquid reserve, committed, shortfall) make
+ reserve coverage legible to investors and integrators.
+- Closing a vault needs no dedicated mechanism: governance pauses the vault, the
+ attester publishes the final value, treasury returns the funds, and every
+ position exits through the normal redemption path.
+
+## 8. Reference interfaces
+
+Both interfaces are part of the kit: they are how investors and operators use
+the protocol without writing code. Both are backend-free and read only the
+public contract surface; each deployment brands and hosts its own.
+
+### Investor dApp
+
+The investor's five actions and nothing else: deposit request, share claim,
+redeem request, cash claim, cancellation of a pending request. Nothing is valued
+at request creation; the only reference shown is the latest attested NAV,
+labelled and timestamped. Three states per side, none skipped: pending, priced,
+claimed. Waiting is stated, never counted down. A priced cash claim shows
+whether the reserve covers it and the current shortfall; a delisted investor
+sees the exit-only path.
+
+### Admin panel
+
+Operates an existing vault; deploys nothing. Every privileged entrypoint belongs
+to exactly one authority, so the panel splits into five surfaces:
+
+| Surface | Authority | Cadence | Operations |
+| ------------- | ------------------------------------- | ------------------- | --------------------------------------------------------------------------- |
+| Cycle | attestation, treasury; anyone settles | Continuous | Attestations, funding, transfers to and from the custodian, settlement |
+| Compliance | compliance | Continuous | Allowlist, freeze/unfreeze, forced transfer, recovery via Manager |
+| Emergency | guardian | Rare and urgent | Vault pause, share-token pause |
+| Configuration | governance | Rare and deliberate | Custodian slot, compliance module, parameters (bounds, freshness, timelock) |
+| Governance | governance | Very rare | Roles, admin handover, upgrade |
+
+Every operation is shown in domain terms, with its conditions and resulting
+state, before a signature is requested; read-only by default. Signing runs
+through an existing self-hostable coordinator. Configuration is derived from the
+public surface given the vault address.
+
+## 9. Trust boundaries & failure modes
+
+| Boundary | Risk | Mitigation |
+| ---------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| Attestation authority | Wrong or compromised reports misprice requests | Multisig reporter; the asymmetric deviation cap bounds any single report and the cooldown bounds frequency; a sustained sequence of biased reports within the cap remains possible, is bounded in speed, and is the monitoring plan's primary alert, with the guardian pause as the reactive control. Residual risk: value transfer between entry and exit cohorts |
+| Governance keys | Malicious upgrade | Timelock with an investor exit window; the guardian pause freezes the timelock clock so the window cannot be waited out while entries are closed |
+| Treasury keys | Reserve drained | Only free reserve is movable, only to the genesis-configured custodian, verified on-chain; outbound transfers are blocked while any shortfall exists, and escrowed subscriptions never leave the vault |
+| Guardian keys | Griefing via pause | Guardian can only pause new requests, pricing and custodian transfers; it can never block payable claims or move funds; governance reverts and rotates the role |
+| Compliance keys | Wrongful delisting or freeze | Delisted investors keep the exit-only cash path; freezes require the Manager path and are auditable per operation |
+| Compliance module | Faulty module blocks transfers | Fail-closed semantics; replaceable by governance without touching the token |
+| Deposit asset issuer | Freeze or clawback of the vault's reserve | Not mitigated by the kit; declared risk of the chosen asset, verified and reported at genesis (auth flags) |
+| Custodian / real world | Underlying loss or delay | Reflected through attested NAV (downward updates uncapped); the kit constrains what reaches the chain, it does not verify the world |
+
+Disclosed trust assumptions: the accuracy of the operator's KYC process, the
+quality of the data behind each attestation, and the operator's key ceremony.
+
+## 10. Deployment
+
+Deployment is scripted and ends with no human key holding governance. It is
+complete only when the final state is verified on-chain: every authority is the
+intended multisig, no bootstrap key retains any role, the configuration matches
+the request, and the deposit asset's auth flags are checked and reported.
+
+## 11. Relationship to existing Stellar tooling
+
+Where a cell says "Not provided", it means: not provided by SEP-41, SEP-56,
+SEP-57, OpenZeppelin Stellar Contracts, or the Soroban vault implementations
+evaluated (Templar, Untangled OctoVault, DeFindex).
+
+| Component | Already exists | Strata |
+| ------------------------------------------------------------------------ | -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| SEP-41 token + SEP-57 RWA extensions (freeze, forced transfer, recovery) | OpenZeppelin stellar-tokens; the RWA Wizard scaffolds the regulated token | Consumed and extended; the kit's compliance module implements the SEP-57 interfaces the token expects |
+| Synchronous tokenized vault | SEP-56 / OZ Token Vault | Not a base for Strata: SEP-56 assumes the price exists at call time, so its interface cannot express a request lifecycle. Only OZ conversion and rounding math reused, as library code |
+| Access control, pausable, upgradeable, timelock | OZ crates | Consumed; pinned by exact version, audit coverage and gaps documented per component |
+| Multisig and signing coordination | Native Stellar + existing coordinators, OZ Role Manager | Integrated |
+| Request lifecycle priced against attestations | Not provided (ERC-7540 on EVM, where OpenZeppelin ships an implementation) | Core of the kit |
+| Guarded valuation oracle with freshness and pause | Not provided | Core of the kit |
+| Split reserve accounting with explicit shortfall exposure | Not provided | Core of the kit |
+| FIFO redemption coverage, exit-only path | Not provided | Core of the kit |
+| Reusable RWA configuration, verified genesis, white-label frontends | Not provided | Core of the kit |
+
+## 12. Delivery phases
+
+| Phase | Deliverables | Evidence of completion |
+| ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **1: Attested valuation and request pricing** | Valuation oracle with guardrails, freshness and pause; request lifecycle with escrow, cancellation and pricing-time mint and burn; public kit spec | Accounting property tests green in CI (price preserved by deposits, redemptions and custodian transfers; cancellation; rounding); multisig signing of privileged operations verified end to end through the coordinator |
+| **2: Split accounting and redemption** | Shortfall exposure; FIFO redemption coverage; exit-only cash path; SEP-57 integration (compliance module, delisted-investor path); threat model and monitoring plan | Settlement cost measured at 1, 10, 100 and 1,000 pending requests; SEP-57 path demonstrated end to end on testnet |
+| **3: Reference interfaces, audit remediation, mainnet** | Investor dApp and Admin panel (five surfaces, one per authority), backend-free; reproducible deployment; audit remediation (all critical and high findings fixed and verified, public changelog); mainnet reference deployment | Audit inheritance matrix published (component, version, audit report, Strata delta, resulting scope); external developer deploys a configured instance from docs alone; reference instance live on mainnet |
+
+The funded core is the valuation, pricing and accounting layer. The Investor
+dApp and the Admin panel are how that core is used by investors and operators;
+without the Admin panel the five authorities are not operable by a
+non-developer, and the kit stops being a kit.
diff --git a/docs/m1-brief.md b/docs/m1-brief.md
deleted file mode 100644
index 8ba783d..0000000
--- a/docs/m1-brief.md
+++ /dev/null
@@ -1,177 +0,0 @@
-# Strata Vault Kit — Technical Architecture
-
-_White-label, compliance-gated vault infrastructure on Stellar/Soroban._
-
-This document specifies what ships in the current milestone. The product's
-direction — vaults whose capital deploys off-chain with value reported back
-on-chain — is stated in §11 and specified when it is designed, not before.
-
-## 1. Overview
-
-An allowlisted investor deposits USDC on Stellar into a vault contract and
-receives shares; returning the shares recovers the USDC. Two rules define the
-product: **only verified addresses may enter**, and **exits are always open** —
-a de-listed holder can always leave. There is no yield in this milestone:
-`total_assets` is the contract's USDC balance, so the share price is effectively
-1:1.
-
-Every team building a compliance-gated vault on Stellar assembles the same
-pieces. OpenZeppelin's Soroban library provides the audited fraction — token,
-vault math, access control, pausable, upgradeable — and each team wires gating,
-roles, deployment and operations around it. Strata Vault Kit is that assembly,
-packaged as a template: **a team sets parameters and authorities and deploys.
-Configured, not built.**
-
-## 2. Design principles
-
-1. **Nothing money-critical is hand-rolled.** Share accounting, conversion math,
- rounding: 100% OpenZeppelin, pinned to audited releases. The custom layer is
- gating and wiring — it composes around the primitives, never rewrites them.
-2. **Exits are always open.** `withdraw`/`redeem` are never gated nor pausable.
- The vault never traps funds; the exit asset (USDC) carries its own
- compliance.
-3. **Separation of duties by construction.** Compliance gates addresses but
- touches nothing else; the guardian can pause entries but cannot change code;
- governance assigns authority but acts through a timelocked, multisig path.
-4. **Upstream-first.** Gaps found in OpenZeppelin primitives are reported and
- contributed upstream; local workarounds carry an explicit deletion trigger.
- Nothing in the product waits on upstream.
-
-## 3. System architecture
-
-```mermaid
-flowchart TB
- subgraph FE [FRONTEND]
- A[Investor dApp
deposit · withdraw · position]
- B[Admin panel
allowlist · pause
tx builder, multisig signs]
- end
- subgraph ON [ONCHAIN · SOROBAN]
- V[Vault + share token
SEP-56, OpenZeppelin]
- AL[Allowlist module]
- RB[Role framework
5 roles, native multisig accounts]
- end
- KYC[Off-chain KYC
operator's process] -->|verified addresses| B
- A --> V
- B --> ON
-```
-
-The frontend is backend-free: the dApp and admin panel read contract state over
-RPC and build transactions that the authority multisigs sign. KYC itself happens
-wherever the operator runs it; the chain only sees its output — an address added
-by the compliance authority.
-
-## 4. Vault and share token
-
-One contract: the vault **is** the share token (SEP-56 tokenized-vault standard,
-OpenZeppelin implementation). Mint/burn is bound to deposits and withdrawals —
-no discretionary issuance path. Appreciating-share model by construction
-(balances constant, value-per-share moves), although in this milestone
-value-per-share stays 1:1.
-
-```
-shares_minted = deposit * total_shares / total_assets
-assets_returned = shares_burned * total_assets / total_shares
-```
-
-Composition detail that matters for auditability: compliance gating does not
-fork or modify OpenZeppelin's vault. The OZ `AllowList` storage module is
-reused, with checks placed in the entrypoint overrides, keeping the storage
-layout upstream-compatible. A known upstream limitation (mutual exclusivity of
-OZ contract types) makes this the correct composition today; when the upstream
-fix ships in an audited release, the manual checks are deleted.
-
-## 5. Compliance module
-
-A set of KYC-verified addresses maintained by the compliance authority.
-`deposit`/`mint` check the receiver; two transfer modes are configurable at
-deploy: **disabled** (shares non-transferable) or **both-sides-allowlisted**
-(secondary movement only between verified parties). `withdraw`/`redeem` are
-never checked — principle 2.
-
-## 6. Roles and separation of duties
-
-Five roles, assignable at deploy time (one account may hold several). Each
-authority is a native Stellar multisig account; the contract requires the
-account's authorization — no multisig code on-chain.
-
-| Role | In this milestone |
-| ----------- | --------------------------------------- |
-| Governance | Assigns roles, authorizes upgrades |
-| Compliance | Maintains the allowlist |
-| Guardian | Pauses deposits/transfers — never exits |
-| Attestation | Declared and assigned; no functions yet |
-| Treasury | Declared and assigned; no functions yet |
-
-The last two exist now so their storage and authority wiring don't force a
-redeploy when their modules ship. Governance tooling is not rebuilt: role
-management runs on OpenZeppelin's open-source Role Manager, with role-change
-history served by OZ's public indexers.
-
-## 7. Investor flow
-
-1. **Onboard** — KYC with the operator, address allowlisted.
-2. **Deposit** — USDC in, shares minted.
-3. **Withdraw** — shares burned, USDC out. Works even after de-listing; pause
- never blocks it.
-
-## 8. Deployment and configurability
-
-Template repository, deploy-time configuration, independent instances — no
-factory, no shared state between deployments. The configuration struct is
-**versioned from day one** (`ConfigV1` with a migration path), because an
-upgradeable contract plus an unversioned config struct is a storage-migration
-trap.
-
-| Parameter | Meaning |
-| --------------- | ------------------------------------------------------------ |
-| Token metadata | Name, symbol of the share token |
-| Authorities | The five role addresses (multisigs) |
-| Transfer mode | `disabled` / `both-sides-allowlisted` |
-| Decimals offset | Share-price scaling mitigating the ERC-4626 inflation attack |
-
-Deployment is reproducible from a fresh clone: scripts create the multisig
-accounts, deploy, and assign roles end-to-end.
-
-## 9. Security and trust model
-
-**On-chain controls:** audited OZ releases only, exact version pins; guardian
-pause that can never trap exits; governance-gated upgrades; storage TTL
-discipline (Soroban state expires and must be extended — no vault entry may
-silently archive); role authorization via direct checks, never role enumeration
-in contract logic (avoiding a known upstream concurrency issue).
-
-**Known upstream limitations, handled:** the OZ contract-type system prevents
-composing the vault and allowlist types directly (worked around as described in
-§4, with a deletion trigger), and the vault's conversion math does not yet honor
-custom `total_assets` overrides — reported upstream with a contribution offered;
-relevant to future modules, not to this milestone.
-
-**Trust assumptions, disclosed:** the accuracy of the operator's KYC process,
-and the operator's key ceremony for the multisig authorities. The template
-constrains what reaches the chain; it does not verify the world.
-
-## 10. Ecosystem
-
-OpenZeppelin Role Manager (governance UI and role history, zero custom code) and
-Scaffold Stellar (typed TS clients, deploy configuration) are used today.
-Further composability — oracles, yield distribution, cross-chain inflows — is
-deliberately deferred until the modules that justify it exist.
-
-## 11. Direction
-
-The archetype this template is built toward: capital that leaves the chain into
-a real-world structure, with value reported back under on-chain constraints and
-redemptions that respect real-world timelines. Those modules — valuation and
-notice-period redemptions — are the next milestone, and this document will
-specify them when they are designed.
-
-## 12. What it is not
-
-- No yield in this milestone: share price is 1:1 until the valuation module
- ships. The README says so explicitly.
-- Not a vault for tokenized RWA tokens held and allocated on-chain — this
- template targets capital that leaves the chain.
-- Not a custody or legal solution — KYC, key ceremonies, and the real-world
- structure are the operator's.
-- Testnet only. Mainnet requires an external audit and an audited OpenZeppelin
- release covering every module used.
diff --git a/docs/roadmap-m1.md b/docs/roadmap-m1.md
deleted file mode 100644
index dca58c9..0000000
--- a/docs/roadmap-m1.md
+++ /dev/null
@@ -1,278 +0,0 @@
-# Technical Roadmap — Milestone 1
-
-## What M1 delivers
-
-A white-label tokenized vault on Stellar testnet, and the interface an investor
-uses to enter and leave it. No yield: shares stay 1:1. Valuation is M2 and
-builds on this base.
-
-**Operator surfaces are M2.** Governance in M1 runs through OZ Role Manager
-(Decision 3), which is enough to demonstrate the role model. A custom admin
-console is valuable but does not belong in the milestone that proves the vault.
-
-## Where we start
-
-The monorepo is scaffolded in #6 with the examples removed. The contract is
-built here, capability by capability.
-
-[`stellar-vault-demo-dapp`](https://github.com/BootNodeDev/stellar-vault-demo-dapp)
-is our own working testnet demo and serves as a **reference**: an OZ Vault
-composed with AllowList as a storage module, gating on
-`transfer`/`transfer_from` (both sides) and `deposit`/`mint` (receiver), open
-exits, LP counter, instance TTL discipline (Soroban storage expires and must be
-extended —
-["state archival"](https://developers.stellar.org/docs/learn/fundamentals/contract-development/storage/state-archival)),
-native 2-of-3 multisig, backend-free signing harness, Playwright e2e. Its
-contract is 188 lines. Read it while building; do not port it wholesale.
-
-Its frontend is **not** carried over. M1 builds a new interface designed around
-the role model, pause states and white-label configuration.
-
-**Versions:** OZ [`=0.7.2`](https://crates.io/crates/stellar-tokens) (latest;
-the 0.7.x line has a published audit of v0.7.0) ·
-[soroban-sdk](https://crates.io/crates/soroban-sdk) `=26.1.0` (do **not**
-upgrade to 27.x — K4) · Rust 1.93 / wasm32v1-none.
-
-## Decisions
-
-1. **Composition:** `ContractType = Vault` intact + OZ `AllowList` as a storage
- module (never occupying the type slot), with checks in the
- `transfer`/`transfer_from`/ `deposit`/`mint` overrides. Share math stays 100%
- OZ. Alternatives (RWA share token + custom vault logic, or a two-contract
- split) are rejected for M1: both rewrite money-critical conversion math.
-2. **Exits-open:** `withdraw`/`redeem` are never gated nor pausable — a
- de-listed holder can always leave. The withdraw `receiver` isn't gated either
- (USDC carries its own compliance).
-3. **Roles:** AccessControl (`stellar-access`), five roles as `Symbol`s.
- `symbol_short!` caps at 9 chars — `governance`, `compliance`, `attestation`
- don't fit; final naming (shorten vs. runtime `Symbol::new`) is closed in #8.
- Only compliance and guardian get entrypoints in M1; the other two are
- declared now to avoid a redeploy in M2. Role **assignment** runs on OZ Role
- Manager, which we don't build; role **actions** — allowlist, pause — are our
- own screens and they are M2. There is no `Ownable` phase: AccessControl
- arrives with the first thing worth gating.
-4. **Authorities:** native Stellar multisig G-accounts as tx source.
-5. **Versions policy:** exact pins; upgrades are never done mid-milestone — each
- migration is its own issue in the following milestone.
-6. **Upstream policy:** gaps in OZ primitives get a comment/PR upstream with
- this repo as evidence, plus a local workaround marked
- `// WORKAROUND(OZ#nnn): — delete when ` (greppable; a
- workaround without this comment is a process bug). **Upstream never sits on
- the critical path.**
-7. **Context files:** `AGENTS.md` is the source of truth for build, run and
- gotchas; `CLAUDE.md` is a pointer to it. Versions, decisions and known issues
- live in this document and are not restated anywhere else.
-
-8. **Interface split by audience, sequenced not deferred:** the LP interface is
- designed and built first; the operator action screens come last in the
- milestone, once everything they operate is green. Role assignment is never
- ours — that is Role Manager.
-9. **Governance is delayed, incident response is not:** privileged governance
- calls pass through a timelock; the guardian pause does not.
-
-## Known issues — OZ primitives (=0.7.2)
-
-| # | Issue | Impact | Handling | Action trigger |
-| --- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
-| K1 | [#560](https://github.com/OpenZeppelin/stellar-contracts/issues/560): `ContractType` mutual exclusivity — `Vault` and `AllowList` can't compose as types. Two fix approaches exist upstream (PR #821 `Compose`, PR #561 negative trait bounds) and their open/closed states have flipped during our own tracking — do not cite either as "the active one" | Solved in our code via Decision 1 | Keep the manual checks; storage layout is OZ's. Watch the **issue** only | #560 fix in an **audited release** → migrate, delete manual overrides, next milestone |
-| K2 | [#674](https://github.com/OpenZeppelin/stellar-contracts/issues/674): internal conversion math ignores `total_assets` overrides | Zero in M1 (default = contract balance is what we want). **Blocks attested-NAV accounting in M2** | Upstream comment + PR offer (#9). Rewriting conversion math ourselves is prohibited without a formal decision | Upstream fix → adopt. If M2 starts without it → decide fork-minimal vs. wait on day 1 of M2 |
-| K3 | [#752](https://github.com/OpenZeppelin/stellar-contracts/issues/752): role enumeration uses counter-derived storage keys → **footprint invalidation under concurrency** | Concurrent role-admin transactions can fail (not just cosmetic listings) | Never use enumeration in contract logic (`has_role` only); run role-admin ops sequentially | Upstream fix; no action ours |
-| K4 | soroban-sdk 27.0.5 (2026-08-03) is incompatible with OZ 0.7.2 (coupled to sdk 26) | Upgrading breaks the build | Stay on 26.x; dependabot ignore rule for sdk majors (#14) | Compatible OZ release → migration as its own issue, next milestone |
-| K5 | SEP-56 / SEP-57 are Draft status | Interface may move before mainnet | Accepted on testnet; frozen against the pinned version | Re-verify pre-mainnet; mainnet only on an audited OZ release covering the Vault module |
-| K6 | The hosted OZ Role Manager has mainnet disabled | None in M1 (testnet only) | Self-hosting Role Manager is a mainnet-track task | Mainnet planning |
-
-## Sequence
-
-```mermaid
-flowchart LR
- D0["E0 · Bootstrap, decisions, upstream
~2.5d"]
- D1["E1 · Vault contract
~6.25d"]
- D2["E2 · CI, deploy, multisigs
~2d"]
- D3["E3 · LP interface
~2.25d"]
- D5["E5 · Operator screens
~2d"]
- D4["E4 · Docs & release
~1d"]
-
- D0 --> D1
- D0 --> D2
- D1 --> D3
- D2 --> D3
- D3 --> D5
- D5 --> D4
-```
-
-## E0 — Bootstrap, decisions and upstream (≈2.5 d) · epic [#1](https://github.com/BootNodeDev/strata-vault-kit/issues/1)
-
-| Issue | Title | Est. |
-| ---------------------------------------------------------------- | --------------------------------------------------- | ---- |
-| [#6](https://github.com/BootNodeDev/strata-vault-kit/issues/6) | Initialize the monorepo and land the project docs | 1 |
-| [#7](https://github.com/BootNodeDev/strata-vault-kit/issues/7) | Does Role Manager detect a stellar-access contract? | 0.5 |
-| [#8](https://github.com/BootNodeDev/strata-vault-kit/issues/8) | Close the open design questions and record ADRs | 0.25 |
-| [#9](https://github.com/BootNodeDev/strata-vault-kit/issues/9) | Report two OpenZeppelin primitive gaps upstream | 0.5 |
-| [#28](https://github.com/BootNodeDev/strata-vault-kit/issues/28) | Start a living architecture doc and decision log | 0.25 |
-
-**Notes**
-
-- **#6** — `stellar scaffold init` with every example stripped, plus the context
- files and this document. `contracts/` ships empty, so `cargo check` starts
- working at #20. Blocks everything except #7.
-- **#7** — the milestone's only stop-gate, on a toy contract, **unblocked and
- run on day one in parallel with #6**. A no here revisits Decision 3 for
- pennies instead of mid-#21.
-- **#28** — `architecture.md` and `docs/adr/` are created here and updated by
- the PR that changes the design, not reconstructed at the end.
-- **#8** — four questions: (a) does `deposit` gate the receiver only, or both
- sides; (b) is the LP counter a product feature or a reference-base leftover
- (if it survives, it becomes an issue); (c) role naming under the 9-char limit;
- (d) licence — the reference base ships BUSL-1.1 and SCF may require
- Apache-2.0.
-
-## E1 — Vault contract (≈6.25 d) · epic [#2](https://github.com/BootNodeDev/strata-vault-kit/issues/2)
-
-Built capability by capability, each its own PR with tests.
-
-| Issue | Title | Est. |
-| ---------------------------------------------------------------- | -------------------------------------------------- | ---- |
-| [#20](https://github.com/BootNodeDev/strata-vault-kit/issues/20) | Build the vault on the OpenZeppelin Soroban vault | 1 |
-| [#21](https://github.com/BootNodeDev/strata-vault-kit/issues/21) | Gate entry with an allowlist and keep exits open | 1.25 |
-| [#22](https://github.com/BootNodeDev/strata-vault-kit/issues/22) | Gate share transfers on both sides | 0.5 |
-| [#23](https://github.com/BootNodeDev/strata-vault-kit/issues/23) | Pause entries without ever blocking exits | 0.5 |
-| [#24](https://github.com/BootNodeDev/strata-vault-kit/issues/24) | Make the contract upgradeable under governance | 0.75 |
-| [#25](https://github.com/BootNodeDev/strata-vault-kit/issues/25) | Configure the vault at deploy time | 0.75 |
-| [#32](https://github.com/BootNodeDev/strata-vault-kit/issues/32) | Put governance behind a timelock | 1 |
-| [#33](https://github.com/BootNodeDev/strata-vault-kit/issues/33) | Keep contract storage alive against state archival | 0.5 |
-
-**Notes**
-
-- **#20** establishes the baseline with no access control, so **#21** lands
- Decision 1 as a reviewable diff rather than burying it.
-- **#21** introduces `#[only_role(caller, "...")]`, which adds a
- `caller: Address` parameter to every gated entrypoint. Public signatures
- change, and the generated TS clients are an input to #16.
-- **#24 and #25 are coupled.** The Upgradeable docs warn that reading old
- storage with a changed type traps and the old type must stay defined in the
- new code — so #25's config is `ConfigV1` with an `into_latest` path from day
- one.
-- **#32** uses `stellar-governance` 0.7.2, the same audited line as the other
- pins — the timelock is not hand-rolled. Guardian pause stays outside it: an
- incident response cannot wait on a delay.
-- **#33** is a security control, not housekeeping. An archived allowlist entry
- or share balance locks a holder out of their own funds.
-- No role enumeration in contract logic (K3).
-
-## E2 — CI, deploy and multisigs (≈2 d) · epic [#3](https://github.com/BootNodeDev/strata-vault-kit/issues/3) — parallel to E1
-
-| Issue | Title | Est. |
-| ---------------------------------------------------------------- | ----------------------------------------------- | ---- |
-| [#14](https://github.com/BootNodeDev/strata-vault-kit/issues/14) | Set up continuous integration for the contracts | 1 |
-| [#15](https://github.com/BootNodeDev/strata-vault-kit/issues/15) | Deploy reproducibly with the four multisigs | 1 |
-
-**Notes**
-
-- **#14** — contracts pipeline only; the frontend pipeline arrives with the
- frontend. The reference base has no workflows and its dependabot config covers
- only npm, so the `cargo` ecosystem has to be added before a `soroban-sdk`
- ignore rule applies to anything.
-- **#15** — the reference `environments.toml` passes only `--asset` while the
- constructor also takes an admin, so a clean redeploy fails there today.
-
-## E3 — LP interface (≈2.25 d) · epic [#4](https://github.com/BootNodeDev/strata-vault-kit/issues/4)
-
-| Issue | Title | Est. |
-| ---------------------------------------------------------------- | -------------------------------------------- | ---- |
-| [#27](https://github.com/BootNodeDev/strata-vault-kit/issues/27) | Wireframe the LP interface | 1 |
-| [#30](https://github.com/BootNodeDev/strata-vault-kit/issues/30) | Build the investor deposit and withdraw view | 1.25 |
-
-**Notes**
-
-- **#27 runs first.** The wireframes settle the LP round trip and every blocking
- state before any component exists.
-- The scaffold already supplies wallet connect, signing, network detection,
- balances and notifications. None of that needs designing or building.
-- Nothing here is a port. The reference frontend informs the design and supplies
- no code. The reference UI was built for a single owner and informs the design
- without supplying the code.
-- **#16** consumes the entrypoint signatures frozen in #21 and the deployment
- from #15. Roles are read with `has_role`, never enumerated.
-
-## E5 — Operator action screens (≈2 d) · epic [#31](https://github.com/BootNodeDev/strata-vault-kit/issues/31)
-
-Last in the milestone: it starts once the contract, the deploy and the LP
-interface are green.
-
-| Issue | Title | Est. |
-| ---------------------------------------------------------------- | ------------------------------------------------- | ---- |
-| [#29](https://github.com/BootNodeDev/strata-vault-kit/issues/29) | Build the multisig signing flow without a backend | 1.25 |
-| [#16](https://github.com/BootNodeDev/strata-vault-kit/issues/16) | Build one action screen per role | 0.75 |
-
-**Notes**
-
-- OZ Role Manager assigns and revokes roles and knows nothing about this vault.
- Allowlist and pause are actions, and they need surfaces of their own.
-- Attestation and treasury have no entrypoints in M1, so they get no screen.
-- **#29 is new work, not a port.** The scaffold signs with a single wallet;
- every privileged action needs a 2-of-3 threshold. The reference base solved
- this without a backend — read it before designing.
-
-## E4 — Documentation and release (≈1 d) · epic [#5](https://github.com/BootNodeDev/strata-vault-kit/issues/5)
-
-| Issue | Title | Est. |
-| ---------------------------------------------------------------- | --------------------------------------------------- | ---- |
-| [#18](https://github.com/BootNodeDev/strata-vault-kit/issues/18) | Write the README, architecture and operator runbook | 0.5 |
-| [#19](https://github.com/BootNodeDev/strata-vault-kit/issues/19) | Run the Definition of Done and tag the release | 0.5 |
-
-**Notes**
-
-- `architecture.md` is maintained from #28 onward, so this epic reviews it
- against the contract as shipped rather than authoring it.
-- The Definition of Done is executed by whoever did **not** write each part,
- following only the docs. If they get stuck, the defect is in the
- documentation.
-
-## Definition of Done
-
-- From a fresh clone: full testnet deploy following the README, with the 4
- multisig authorities operational.
-- E2E demo: allowlist add → deposit → withdraw → allowlist remove → deposit
- reverts, **withdraw still works**.
-- LP interface: an approved investor completes the round trip, and a de-listed
- one is told entry is closed while exit stays available.
-- Transfer behaves per configured mode (both modes tested); `transfer_from`
- gated and tested.
-- Pause blocks deposit/mint/transfer, never withdraw/redeem; unpause restores.
-- CI green; Role Manager runbook verified by cross-execution.
-- Comments published on OZ #560 and #674; ADRs and addresses in the repo.
-- Tag `v0.1.0-m1`.
-
-## Totals
-
-| | Estimate |
-| -------------------- | -------------------------------------------------------- |
-| Happy-path effort | ~16 person-days |
-| Contingency (35%) | ~5.6 person-days |
-| **Total effort** | **~21.6 person-days** |
-| **Per-dev calendar** | **~10.1 days** with two people, counting #6 as delivered |
-
-Estimates are maintained in the `Estimate` field of the
-[project board](https://github.com/orgs/BootNodeDev/projects/29), which is what
-sums. The table above is a snapshot.
-
-## Out of scope — and where it goes
-
-| Deferred | Milestone |
-| ------------------------------------------------------ | -------------------------------------------------------------------- |
-| Role assignment and revocation | never — OZ Role Manager already does it |
-| Valuation and attested NAV | M2 |
-| Request-withdraw, notice period, oracle, indexer, fees | M2+ |
-| Porting the reference frontend | never |
-| Any upstream fix landing mid-M1 (#674, #560) | record the trigger in K1/K2, migrate next milestone — never hot-swap |
-
-## Amendment rule
-
-[`m1-brief.md`](./m1-brief.md) specifies what the product is; this document
-specifies the order it gets built in and what it costs; `architecture.md` (from
-#28) describes what was actually built. Where the first two disagree, the brief
-wins and this file is brought into line.
-
-This document is the plan, not a log. It changes when a decision changes — and a
-decision changes in an ADR (#28) or in an issue, which is then reflected here in
-one pass. It does not accumulate patches.