Durable, beneficiary-bound subaddress index reservation
This commit is contained in:
@@ -18,9 +18,11 @@ The independent private chain uses a fixed pilot genesis time and its own determ
|
||||
|
||||
This stack does **not** connect to the operator's Monero daemon, create real Monero deposit addresses, scan a wallet, approve real credits, construct or relay withdrawals, or settle NFT sales against active consensus. Having a full node supplies only the blockchain daemon; it is not a Wallet-RPC service, watch-only deposit wallet, or spending wallet. Deposit enrollment and withdrawal request flags remain rejected outside the mainnet profile, and mainnet remains separately gated. Do not expose the service publicly or solicit funds.
|
||||
|
||||
### Pilot custody identity groundwork (schema v10)
|
||||
### Pilot custody identity and durable deposit reservations (schema v11)
|
||||
|
||||
Schema v10 adds an immutable, identity-only binding with separate fields for the Wikideck market network/chain (`wikideck-randomx-pilot-1` and the pilot chain ID), Monero network (`mainnet`), custodian UUID, policy version and initialization time. It intentionally does not widen the existing allocation or withdrawal table constraints, initialize the mock sandbox's `custody_meta` identity, create addresses, grant runtime privileges, or enable any HTTP funding routes.
|
||||
Schema v10 added the immutable identity binding with separate fields for Wikideck market network/chain (`wikideck-randomx-pilot-1` and pilot chain ID) and Monero network (`mainnet`). Schema v11 adds a separate pilot reservation table. A signed beneficiary/wallet request can now reserve a never-reused subaddress index transactionally, with request replay, same-beneficiary recovery, concurrent index allocation, and conflict protection. Mainnet allocation/withdrawal constraints and v1-v10 migration definitions remain unchanged.
|
||||
|
||||
The reservation table has a composite foreign key to the immutable identity row, so direct SQL inserts cannot bind a reservation to a different custodian, Wikideck chain, or Monero network. The focused disposable PostgreSQL lifecycle test verifies index sequencing, replay, concurrent reservations, beneficiary conflict, and denied financial/address access for the restricted role. This implementation still does not create any address.
|
||||
|
||||
Use a **separate fresh custody database** for this identity exercise. The existing pilot Compose database contains mock sandbox custody and is not eligible; importing or reinterpreting its mock journals as Monero liabilities is prohibited. An operator migration is explicitly gated; identity initialization also refuses populated financial, mock, observer, allocation, credit, release or withdrawal tables.
|
||||
|
||||
@@ -28,10 +30,13 @@ After an operator creates/provisions a distinct empty database and its schema-ow
|
||||
|
||||
1. With the `pilot` profile selected, run `custody:db migrate-pilot-schema` with `WIKIDECK_PILOT_SCHEMA_MIGRATION=explicit-pilot-schema-migration-only`.
|
||||
2. Run `custody:db initialize-pilot-custody-identity <CUSTODIAN_UUID>` with `WIKIDECK_PILOT_MODE=private-mock-only`, `WIKIDECK_PILOT_CUSTODY_IDENTITY=initialize-pilot-custody-v1`, and `WIKIDECK_PILOT_CUSTODY_OPERATIONS=identity-only-no-funds`.
|
||||
3. If using the reservation library against that database, create a separate least-privilege role out of band and run `custody:db grant-pilot-deposit-reservation-runtime <ROLE>` with `WIKIDECK_PILOT_CUSTODY_OPERATIONS=reservation-only-no-addresses`.
|
||||
|
||||
The schema migration does not grant runtime roles. The identity command is one-time and replay-idempotent only for the same pilot chain and custodian. The CLI refuses other custody actions on the pilot profile; mainnet keeps its existing separate controls. This is groundwork only: no customer deposits, financial posting, withdrawal intent or send is enabled by these commands.
|
||||
The schema migration does not grant runtime roles. The reservation role can read schema-version digests and the immutable pilot identity, execute a fixed isolation predicate, and read/insert immutable reservation rows. It cannot read custody metadata, balances, journals, mock custody, observer data, withdrawal intents, or alter reservation history. The isolation predicate uses a fixed-search-path schema-owner function; the role does not receive broad SELECT access just to check that the dedicated database remains unpopulated.
|
||||
|
||||
The signed pilot deposit-request contract is also implemented as a validation-only library boundary. It explicitly signs both the pilot market identity and Monero Mainnet identity, then verifies the initialized identity and wallet-generation/fingerprint/account context. It returns an allocation intent digest only; it does not reserve an index, call Wallet-RPC, return an address, persist an allocation, or expose an HTTP route. Existing mainnet enrollment remains unchanged. Do not treat a valid signature or this validator as approval to accept funds.
|
||||
The CLI refuses other custody actions on the pilot profile; mainnet keeps its existing separate controls.
|
||||
|
||||
The library path verifies the signed pilot request, checks both network identities and configured wallet-generation/fingerprint/account, then reserves an index. It intentionally stops there: no Wallet-RPC call, address creation/registration, address response, observer, credit, withdrawal, or HTTP enrollment route exists. A durable reserved index is never reclaimed; wallet-side index advancement or lost RPC responses must be reconciled before address-generation support is added. Existing mainnet enrollment remains unchanged. Do not treat a reserved index or valid signature as approval to accept funds.
|
||||
|
||||
### Reusing the operator-hosted daemon
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ Updated: 2026-10-22. Implementation plan for a private, operator-supervised func
|
||||
- **Step 1 started; mock-only foundation implemented.** Added a distinct `pilot` profile with its own network/genesis identity, explicit private-mock-only startup opt-in, separate local ledger/market/custody paths and browser wallet database, and a loopback-bound PostgreSQL sandbox stack. Setup and limits are in [the pilot deployment guide](real-xmr-pilot-deployment.md). Testnet v6 and mainnet candidate identities/gates were left intact.
|
||||
- **Operator infrastructure update:** a Monero full node is hosted on the operator's network and is intended to be reused; the pilot does not need to deploy or synchronize another daemon. Its network mode, RPC reachability from the pilot host/container, authentication/transport boundary and sync health still need verification. This does not provide Wallet-RPC, deposit observation, address allocation or a spending wallet.
|
||||
- **Next integration slice implemented:** added an operator-triggered, read-only `monerod get_info` probe, opt-in Compose check service, and mocked regression coverage. The Linux test image builds and focused probe/deployment tests pass (6/6). The probe validates expected Mainnet/Stagenet identity and synchronization, but has not been run against the operator's node because its private endpoint/configuration has not been provided. It does not enable wallet access, addresses, deposits, or credits. See [the probe setup and security boundary](real-xmr-pilot-deployment.md).
|
||||
- **Pilot identity/schema slice implemented:** schema v10 additively records a separate identity binding `wikideck-randomx-pilot-1` + current pilot chain ID to Monero `mainnet`, with an immutable `identity-only` activation status. Explicit pilot-only schema-migration and identity-initialization CLI actions require exact no-funds acknowledgements, reject non-pilot profiles, and refuse any target DB with pre-existing mock/financial/deposit data. No runtime roles/grants or deposit/withdrawal routes were added. Existing v1-v9 migration definitions/digests remain unchanged.
|
||||
- **Pilot deposit-contract slice implemented:** added a separate signed pilot request schema that explicitly binds the Wikideck pilot network/chain, Monero Mainnet, custodian, beneficiary and watch-only wallet generation. Its validator checks signature, expiry, identity-only status and wallet context, and returns only a validated intent digest—no address/index or RPC/DB side effect. It is not connected to HTTP or an allocator.
|
||||
- **Validation:** the latest serial offline suite passed 189/189; the new pilot contract tests passed 3/3. PostgreSQL integration suite passed 42/42 after schema v10, including v1/v2 upgrades, identity replay/mismatch checks, dirty-database rejection, and no role access to the identity table. The isolated pilot identity operation itself requires a separate fresh database and has not been run outside disposable tests.
|
||||
- **Pilot identity/schema slice implemented:** schema v10 additively records a separate identity binding `wikideck-randomx-pilot-1` + current pilot chain ID to Monero `mainnet`, with an immutable `identity-only` activation status. Schema v11 adds separate immutable pilot reservation rows. Explicit pilot-only migration, identity, and reservation-role CLI actions require exact acknowledgements, reject non-pilot profiles, and refuse reused financial databases.
|
||||
- **Durable pilot allocation implemented:** a signed pilot request now reserves the next never-reused index transactionally, serializes concurrent allocators, replays idempotently, and rejects request/beneficiary conflicts. PostgreSQL enforces the reservation's custodian, market-chain, and Monero-network binding with a composite foreign key to the immutable pilot identity. A dedicated role can read schema digests and pilot identity, execute the isolation check, and read/insert reservations only; it cannot read balances, register addresses, or access observation, credit, or withdrawal tables. This code does not call Wallet-RPC, return a Monero address, or connect to HTTP.
|
||||
- **Validation:** focused PostgreSQL allocator lifecycle passed, covering first reservation, request replay, same-beneficiary recovery, concurrent index allocation, conflict rejection, and least-privilege denials. The schema v1-to-v11 migration test passed and the Linux test image builds. The serial offline suite passed 189/189 after the allocator implementation; no operator database or real node was accessed.
|
||||
- **Step 1 is not complete.** The current pilot stack does not connect to that external daemon and still has no Wallet-RPC gateway, observer, real-fund deposit or withdrawal path. It is useful for isolated UI/mock-flow work only and must not receive funds.
|
||||
- **Validation history:** earlier pilot-only checks passed 10/10. An earlier full-suite attempt had a transient RandomX peer-gossip failure; the most recent serial offline suite subsequently exited 0.
|
||||
- **Steps 2–5:** not started. Existing deposit/withdrawal APIs still require the separately gated mainnet profile; the new pilot record is identity metadata only. Sale-lock transactions remain candidate-only and are not accepted by active consensus.
|
||||
@@ -25,7 +25,7 @@ Use the existing pooled-custody architecture, PostgreSQL accounting, native Mone
|
||||
## Reuse what exists
|
||||
|
||||
- Exact atomic-XMR prices and fee calculations.
|
||||
- PostgreSQL schema v10 and accounting/reorg records.
|
||||
- PostgreSQL schema v11 and accounting/reorg records.
|
||||
- Signed deposit enrollment, observation worker and reviewed credit/release commands.
|
||||
- Signed balance reads and withdrawal reservation/cancellation APIs.
|
||||
- Marketplace/custody UI and executable sale-lock/accounting models.
|
||||
@@ -46,7 +46,7 @@ One Linux host, one authoritative market writer, one treasury tool/worker, fixed
|
||||
- Add one pilot deployment definition using existing Docker patterns: app, PostgreSQL, observer and private Wallet-RPC gateway. Reuse the operator-hosted full node over a verified private network connection; do not add a duplicate daemon service. Connect the observer/watch-only wallet and separate spending wallet explicitly. Keep daemon and Wallet-RPC endpoints private, authenticated and unavailable from the public Internet; supply credentials through protected files/secrets, not checked-in Compose values.
|
||||
- Include schema initialization, role grants and required configuration in a short setup procedure. Keep spending keys outside the web app and Wallet RPC off the public Internet.
|
||||
|
||||
**Progress:** A separate mock-only pilot network/profile, launch opt-in, profile-isolated local storage, PostgreSQL deployment, and opt-in read-only daemon probe now exist. The probe awaits the operator's protected endpoint config. Additive schema v10 and a pilot-only CLI bind the separate Wikideck pilot chain to Monero Mainnet in a fresh identity-only database; this grants no runtime access and cannot be used to enroll or credit deposits. Observer/Wallet-RPC roles and all real-fund integrations remain outstanding. See [pilot deployment status and startup](real-xmr-pilot-deployment.md).
|
||||
**Progress:** A separate mock-only pilot network/profile, launch opt-in, profile-isolated local storage, PostgreSQL deployment, and opt-in read-only daemon probe now exist. The probe awaits the operator's protected endpoint config. Additive schema v11 binds the pilot chain to Monero Mainnet and durably reserves signed beneficiary-bound address indexes in a dedicated database/role. The allocator stops before Wallet-RPC: it does not create/register or return addresses, start observation, credit funds, or enable HTTP enrollment. Observer, Wallet-RPC and real-fund integrations remain outstanding. See [pilot deployment status and startup](real-xmr-pilot-deployment.md).
|
||||
|
||||
**Result:** start the stack, open the UI, create two wallets and obtain a test card; verify the hosted daemon's intended network, synchronization and private RPC reachability from the pilot runtime. Do not start a duplicate daemon. Prepare the watch-only/observer and separately controlled spending-wallet services while application development proceeds. A Stagenet rehearsal still requires a Stagenet daemon endpoint; an operator's Mainnet daemon cannot substitute for it.
|
||||
|
||||
@@ -121,4 +121,4 @@ Keep the functional essentials: signed authorization, correct network binding, p
|
||||
|
||||
## Next coding task
|
||||
|
||||
**Next: add the separate durable pilot allocation and observer identity path, then test it only with disposable fixtures—still without enabling an HTTP enrollment route or creating addresses.** The signed pilot request contract now defines the dual-network authorization boundary. Next migration/role work must preserve `identity-only`, separate pilot records from mock custody, and reject credit until reviewed funding, withdrawal execution and recovery are ready. Run the read-only daemon check when the protected endpoint config is available; no duplicate daemon is planned. Continue treasury execution and active sale-lock settlement as parallel tracks once their shared identity boundary is defined. Completion means a buyer purchasing a card and the seller receiving withdrawable XMR—not another scaffold or release checklist.
|
||||
**Next: implement Wallet-RPC create/recover for durable pilot reservations through the existing private mTLS wallet gateway, with lost-response recovery and out-of-band index-consumption tests.** Do not expose enrollment over HTTP or enable credits. Keep addresses private and operator-triggered until actual withdrawals, recovery, and financial review are ready. Run the daemon health check when protected endpoint config is available; no duplicate daemon is planned. Keep the deployment mock-only until network binding, reviewed credit, actual withdrawal execution, recovery, and sale settlement are connected. Continue treasury execution and active sale-lock settlement as parallel tracks once their shared identity boundary is defined. Completion means a buyer purchasing a card and the seller receiving withdrawable XMR—not another scaffold or release checklist.
|
||||
|
||||
Reference in New Issue
Block a user