Caution-backed organization-user quorum bundle creation #384

Open
opened 2026-07-16 04:23:33 +00:00 by caution-bot · 3 comments
caution-bot commented 2026-07-16 04:23:33 +00:00 (Migrated from codeberg.org)

Current status — 2026-09-24

The API/CLI/dashboard feature is implemented. Service access, final acceptance and review remain open. Guided dashboard creation is no longer a missing feature.

Published PR heads checked on 2026-09-24: Platform 1f7e296, Locksmith 9f702bb, Bootproof 821b5c6. Platform's dependency/model/mock/default-runtime pins are aligned at Locksmith d2876e9; subsequent Locksmith changes concern examples, configuration, documentation and terminology. These are published implementation states, not merged/deployed-state claims.

Done: organization-member/key discovery; signed API/CLI generation; external-PGP, passkey and mixed holders; independent certificate/Keymaker proof checks; storage/download/manage operations; guided dashboard creation with manual public-PGP additions, explicit approval-method selection, threshold and review; passkey eligibility and 64-credential bounds; native cancellation and browser-relay cleanup; updated setup/recovery documentation. Current product contract.

Separate explicit ImportedV0 import/recovery and policy-free ImportedV0 packaging are implemented. They do not add V0 generation, automatic fallback from failed V1 verification, or earlier-V1 migration. Legacy scope.

Remaining:

  • #349: actual network restrictions and hosted Keymaker access control; issuance bearer auth alone does not meet the API-network-only requirement.
  • #383 / Locksmith #12: security/lifecycle acceptance, effective revocation and root/token recovery. Credential/member removal currently does not revoke historical bundle release authority.
  • Decide whether generation needs owner/admin authorization beyond the current authenticated-member/signed-request policy; this is an open product policy, not an implemented gate.
  • Record exact-candidate real-Nitro/hardware/browser/negative/restart acceptance and finish review/merge. Existing successful operator recovery reports should be attached to their revisions/PCRs.

Accepted scope: operator-configured URLs and trust files; no endpoint database; Keymaker owns one-shot serialization and Platform does not add a queue. Restart supervision/replacement is implemented; it does not supply caller authorization. The September 23 review was on 44a475d / c33e35e; this status refresh did not rerun the full stack.

Implemented CLI behavior

caution secret init (new remains an alias) supports explicit per-holder custody:

caution secret init --holder alice=external-pgp --holder bob=webauthn --threshold 2

Username/UUID selectors and registered PGP registration-ID/full-fingerprint selection resolve to exact organization members/keys. One selected PGP certificate or one derived certificate with a credential snapshot represents each organization holder; multiple passkeys do not increase quorum weight. Interactive confirmation shows custody and threshold. Missing/ambiguous/ineligible selections fail before generation; there is no silent Caution-backed fallback.

Existing --from-org-users/--caution-backed selectors remain documented, and manual/direct PGP-only generation uses current V1. CLI output/download retains the complete proof envelope. caution secret inspect verifies persisted bundle evidence and exposes holder/context details; recovery supports native and browser approval. See the creation contract and Platform recovery and validation.

Implemented dashboard behavior

The Secrets tab now provides a configure/review/create flow. It supports organization holders and manually added public PGP certificates, explicit passkey/external-PGP selection, threshold/count validation, a holder summary, signed creation, and an uncertain-outcome state without automatic retry. Multiple passkeys still authorize one share. Private-key uploads are rejected.

Implementation and local UI/browser validation are documented in the current dashboard section. Real-authenticator and deployed service acceptance remain separate.

Implemented API behavior

API route paths (relative to the configured API base):

  • GET /quorum-bundles/participants: active organization members, registered public PGP keys and credential counts, without private keys or raw credential bindings.
  • POST /quorum-bundles/from-org-users: signed, authenticated hosted generation/storage.
  • POST /quorum-bundles: proof-verified upload; existing list/get/update/delete routes remain.

Generation accepts optional name, required threshold, explicit participants (user_id, key_source, optional pgp_key_id), optional local pgp_certificates, allow_caution_backed_keys and labels. Key sources are existing_pgp and caution_backed_pgp. Hosted callers cannot set service URLs. Platform computes max from the assembled holders and validates threshold/count and independent key identities.

The current handler resolves the authenticated user's organization and enforces selected-member/key eligibility; gateway-signed authorization is required for creation and bundle mutations. It does not introduce a separate owner/admin-only generation gate. Whether product policy should impose that additional role restriction remains an explicit decision below.

Certificates, holder/credential associations and proof-bound quorum parameters are preserved through storage and full-bundle download. See the API implementation.

Keymaker and public key service configuration

Hosted organization-user generation calls both services from Platform only. CLI/UI generation requests cannot supply or override service addresses.

Use operator-managed KEYMAKER_URL and PUBLIC_CERTIFICATE_SERVICE_URL, together with independently provisioned PCR policies and the Caution CA. A database-backed static-IP registry is not required for this milestone. Missing/invalid required configuration fails affected operations closed. Direct PGP-only CLI generation remains a separate explicit mode; it does not override hosted configuration.

Certificate issuance authentication is implemented by Platform 5ebbe00 and Locksmith 30938f6. Platform requires backend-only PUBLIC_CERTIFICATE_SERVICE_TOKEN (32 random bytes encoded as 64 hex characters), matching the custody service's encrypted vault input, and sends it only to /v1/public-certificates over HTTPS with redirects disabled. PGP-only creation does not need this token. The TLS terminator is trusted with the bearer credential; certificate/proof verification remains independent.

The token is not forwarded to Keymaker and does not authorize shard release: public recryption routes retain WebAuthn approval. Hosted Keymaker access control and the original API-network-only reachability requirement are still outstanding; the bearer token does not make either service network-private. Certificate issuance and recryption still share one service/listener, with authentication applied only to issuance.

Local/synthetic validation is recorded with those commits. Live issuance/recovery/restart acceptance for the current candidate is not yet recorded; token provisioning, deployment revisions and independent PCR-policy updates must be included in that record; see the migration and acceptance runbook.

Keymaker concurrency

Keymaker owns its single-use serialization and reset lifecycle, tracked in Locksmith #2. Do not add a Platform semaphore or queue in this milestone.

Platform sends one bounded generation attempt, propagates busy/error/timeout results, and does not retry generation automatically. A timeout can mean generation completed remotely. Each new quorum consumes a fresh Keymaker instance; configured host supervision now replaces terminated instances automatically. Recovery, approval retries and application enclave restarts do not consume Keymaker. Replacement downtime and lost-response outcomes remain explicit failures, without automatic generation replay.

Current Keymaker contract

The shared model defines:

  • Request: GenerateQuorumRequest::V1, with bundle_id: [u8; 16], label, threshold, max and structured keyring.
  • Response: GenerateQuorumResponse = Proofed<GenerateQuorumBundle>. The outer object is {data, necroproof}; data is tagged version: "V1" and includes bundle_id, label, keyring, required threshold/max, shardfile and public_key.
  • Holders remain Key::OpenPGP { cert } or Key::WebAuthn { credential, cert }. Multiple credentials for one holder authorize one share.
  • UUIDs use canonical 16-byte representations. No legacy keyring_hash or inline payload proof is required. V0, unproofed and earlier V1 bundles missing required quorum parameters are unsupported.
  • For Caution-backed creation, the certificate service receives organization/count, generates the bundle UUID and returns proofed public certificates; Platform verifies that evidence and retains its UUID and credential associations when calling Keymaker.

Implemented backend generation flow

  1. Authenticate the requester, resolve their organization and validate the explicit request, active members, key-source eligibility, duplicate selections, labels and threshold.
  2. Load selected registered/local public PGP certificates and snapshot current registered passkeys for Caution-backed holders. Resolve operator-configured URLs and independent trust inputs.
  3. For WebAuthn/mixed creation, authenticate the certificate request with the backend bearer token; verify returned proof, CA certification, organization/bundle/index, certificate count and capabilities. Preserve the service-generated bundle UUID. PGP-only creation generates its own UUID and does not need certificate-service configuration.
  4. Assemble ordered structured holders; retain credential associations and reject shared signing/encryption identities between holders. Equivalent encryption subkeys within one holder remain valid; ECDH identity ignores KDF hash/cipher differences.
  5. Compute max, send one bounded current-V1 Keymaker generation request, verify the complete proofed response and compare requested bundle/labels/holders/quorum parameters. Keymaker owns single-use serialization/reset; busy/error/timeout never causes an automatic generation retry.
  6. Store the complete proofed V1 envelope and return bundle metadata/public key. Later recovery/restarts do not consume Keymaker.

Data/model status

Registered user-owned public PGP keys and credential discovery are implemented. Hosted selection resolves exact active registrations and checks organization ownership; no new PGP-key table is pending for this flow. Service endpoints remain operator configuration, without a database endpoint registry.

Guided dashboard creation is implemented. Remaining work is service access/security, acceptance evidence and the optional owner/admin policy decision. Existing bundles sharing encryption material are not repaired by stricter new-generation checks and need separate assessment/migration if present.

Security requirements

  • Caution-backed keys must be explicitly selected by CLI/UI/API; do not generate them silently.
  • The API, not the CLI, must enforce organization membership and key-source eligibility.
  • Only organization members may be selected.
  • Requester authorization must be enforced server-side.
  • Generated Caution-backed material/certificates must be bound to the organization, user, bundle, purpose, and policy.
  • Public key service responses must be verified before returned certificates are included in the Keymaker keyring.
  • Duplicate certificates must not create duplicate quorum participants unless explicitly intended and documented.
  • Final keyring assembly must be deterministic.
  • Keymaker and public certificate service URLs are global operator-controlled server configuration.
  • CLI/UI generation requests must not include or override internal service IPs, ports, or URLs.
  • The API uses configured service base URLs and fixed endpoint paths; hosted requests cannot override them.
  • Hosted Keymaker and certificate issuance must be reachable only from the platform API network boundary. This network restriction remains outstanding; the implemented issuance bearer check is application authentication, and public recryption must remain available.
  • Keymaker enforces single-use serialization/reset; Platform does not add its own semaphore or queue.
  • Platform generation attempts are bounded and never automatically retried after success, error, timeout or malformed responses.
  • Missing or invalid required service/trust configuration must fail closed with a clear operator-facing error.
  • Do not log or expose secrets, private key material, raw bearer tokens, shard contents, raw request bodies, or decrypted values.

Documentation updates

After the feature lands, update CLI and user-facing docs to explain:

  • caution secret new --from-org-users;
  • when and why to use --caution-backed;
  • how Caution-backed OpenPGP keys differ from user-provided OpenPGP keys;
  • what happens for users who already have PGP keys vs users who do not;
  • how threshold/max are calculated when mixing existing PGP keys and Caution-backed keys;
  • where generated quorum bundles appear in the dashboard;
  • the security model and migration guidance for existing manual caution secret new <keyring> users.

Do not consider the feature complete without docs. If docs are deferred to a later PR, the implementation PR should use Refs #... rather than closing this issue.

Acceptance criteria

  • API exposes authenticated discovery for eligible organization users and available key sources.
  • API exposes authenticated generation/storage for quorum bundles from selected organization users.
  • API distinguishes existing user-provided PGP certificates from Caution-backed PGP certificates.
  • API validates membership, authorization, duplicate selections, selected key-source availability, and threshold/max.
  • API requires explicit Caution-backed selection before deriving/generated Caution-backed PGP material.
  • API assembles a deterministic Keymaker v1::keyring: Vec<Key> from selected existing OpenPGP and Caution/public-key-service-derived WebAuthn certificates.
  • Platform loads global operator-configured Keymaker/public certificate service URLs and independent trust files.
  • Organization-user quorum generation resolves both service URLs server-side.
  • CLI/UI cannot override Keymaker or public key service addresses.
  • API uses operator-configured base URLs with fixed endpoint paths.
  • Keymaker owns single-use serialization; the API propagates bounded failures without automatic generation retries.
  • API calls Keymaker /generate_quorum with the current V1 request and preserves/verifies the complete proof-wrapped V1 response. Legacy V0 callers are unsupported.
  • API validates the V1 response fields that exist in current Keymaker models: bundle_id, label, keyring, threshold, max, shardfile, and public_key.
  • API stores the resulting V1 response in existing organization quorum bundle storage and returns the stored bundle id and Keymaker public key.
  • API returns clear errors when required service URLs or trust configuration are missing/invalid.
  • CLI supports caution secret init (alias new), explicit per-holder custody and the documented --from-org-users/--caution-backed selectors.
  • CLI fails closed when selected users lack PGP keys and Caution-backed generation was not selected.
  • Dashboard Secrets page includes a guided create flow and clearly labels existing PGP vs Caution-backed PGP participants before creation.
  • Existing manual keyring-file CLI usage remains available using current V1; legacy V0 wire/bundle compatibility is not implied.
  • Docs are updated for the CLI command, dashboard workflow, Caution-backed key behavior, and security model.

Suggested tests

  • discovery endpoint only returns users in the requester's organization;
  • generation rejects users outside the organization, duplicate participants, unavailable key source, Caution-backed users when disabled, and threshold > max;
  • generation rejects malformed/mismatched Caution-backed certificate response;
  • generation assembles deterministic GenerateQuorumRequest::V1 from mixed existing OpenPGP and Caution/public-key-service-derived WebAuthn certificates;
  • successful generation stores the typed Keymaker V1 response in quorum_bundles;
  • existing raw quorum bundle upload/list/get/update/delete behavior remains compatible;
  • generation fails clearly when a required service URL or trust file is missing/invalid;
  • generation ignores/rejects any request field attempting to set internal service address;
  • integration tests exercise Keymaker-owned single-use admission with concurrent generation requests;
  • busy/error/timeout responses do not cause automatic generation retries;
  • public certificate service URL comes from operator configuration, never hosted request input;
  • platform integration test or contract test proves the Keymaker route accepts the expected top-level V1 envelope before enabling organization-user generation.

Remaining product and access decisions

  • Completed: the Secrets creation flow, holder/approval-method selection, threshold/review and signed creation/failure behavior. Retain real-device/deployment acceptance as a separate gate.
  • Complete hosted Keymaker access control and API-network-only reachability for generation/issuance while keeping WebAuthn-authorized recryption public. Bearer authentication does not enforce network isolation; current ingress provisioning does not preserve per-rule source CIDRs.
  • Decide whether to add an owner/admin-only generation policy beyond the current authenticated-organization-member/signed-request behavior. Do not describe such a gate as already implemented.
  • Complete retained service/lifecycle requirements under #383 and record exact-revision live acceptance before closure. The current CA-certified profile and fixed hash encodings are accepted/implemented; a general structure-hash registry remains deferred. Track production revocation/root-recovery work explicitly.

Resolved implementation choices: canonical 16-byte UUIDs; proof-wrapped current V1 with required threshold/max; V1 Keymaker route; fixed participant/generation API routes; one selected registered PGP certificate or one derived certificate per organization holder; multiple passkeys as one share; server-computed max. These no longer need to be posed as open wire-format questions.

In-repository prerequisite

Keep #383 separate from this issue: #383 defines and implements the certificate derivation/proof service, while this issue tracks the platform API/CLI/dashboard organization-user quorum bundle flow that consumes that service. Do not close this issue until the #383 service contract is implemented and integrated for Caution-backed participants.

Cross-repository implementation dependencies

This platform feature depends on Locksmith/Keymaker work tracked separately:

The platform API/CLI/UI work should treat these as prerequisites before closing this issue: Keymaker must accept/generate V1 bundles from structured key material, Locksmith must verify/load current proofed V1 bundles and reject unsupported legacy formats, and the WebAuthn signed transport plan from caution/locksmith#7 must be implemented for Caution-backed shard recryption.

## Current status — 2026-09-24 **The API/CLI/dashboard feature is implemented. Service access, final acceptance and review remain open.** Guided dashboard creation is no longer a missing feature. Published PR heads checked on 2026-09-24: [Platform `1f7e296`](https://codeberg.org/caution/platform/commit/1f7e2963932ac616ba6c4f0e9553112cb548ce72), [Locksmith `9f702bb`](https://codeberg.org/caution/locksmith/commit/9f702bbf465bc4968e0fa57adcbbc366a1c6977c), [Bootproof `821b5c6`](https://codeberg.org/caution/bootproof/commit/821b5c63e80f082f6d67ba3695c11416933489ec). Platform's dependency/model/mock/default-runtime pins are aligned at Locksmith `d2876e9`; subsequent Locksmith changes concern examples, configuration, documentation and terminology. These are published implementation states, not merged/deployed-state claims. Done: organization-member/key discovery; signed API/CLI generation; external-PGP, passkey and mixed holders; independent certificate/Keymaker proof checks; storage/download/manage operations; guided dashboard creation with manual public-PGP additions, explicit approval-method selection, threshold and review; passkey eligibility and 64-credential bounds; native cancellation and browser-relay cleanup; updated setup/recovery documentation. [Current product contract](https://codeberg.org/caution/platform/src/commit/1f7e2963932ac616ba6c4f0e9553112cb548ce72/docs/org-user-quorums.md). Separate explicit ImportedV0 import/recovery and policy-free ImportedV0 packaging are implemented. They do not add V0 generation, automatic fallback from failed V1 verification, or earlier-V1 migration. [Legacy scope](https://codeberg.org/caution/platform/src/commit/1f7e2963932ac616ba6c4f0e9553112cb548ce72/docs/legacy-v0.md). Remaining: - [#349](https://codeberg.org/caution/platform/issues/349): actual network restrictions and hosted Keymaker access control; issuance bearer auth alone does not meet the API-network-only requirement. - [#383](https://codeberg.org/caution/platform/issues/383) / [Locksmith #12](https://codeberg.org/caution/locksmith/issues/12): security/lifecycle acceptance, effective revocation and root/token recovery. Credential/member removal currently does not revoke historical bundle release authority. - Decide whether generation needs owner/admin authorization beyond the current authenticated-member/signed-request policy; this is an open product policy, not an implemented gate. - Record exact-candidate real-Nitro/hardware/browser/negative/restart acceptance and finish review/merge. Existing successful operator recovery reports should be attached to their revisions/PCRs. Accepted scope: operator-configured URLs and trust files; no endpoint database; Keymaker owns one-shot serialization and Platform does not add a queue. Restart supervision/replacement is implemented; it does not supply caller authorization. The September 23 review was on `44a475d` / `c33e35e`; this status refresh did not rerun the full stack. ## Implemented CLI behavior `caution secret init` (`new` remains an alias) supports explicit per-holder custody: ```sh caution secret init --holder alice=external-pgp --holder bob=webauthn --threshold 2 ``` Username/UUID selectors and registered PGP registration-ID/full-fingerprint selection resolve to exact organization members/keys. One selected PGP certificate or one derived certificate with a credential snapshot represents each organization holder; multiple passkeys do not increase quorum weight. Interactive confirmation shows custody and threshold. Missing/ambiguous/ineligible selections fail before generation; there is no silent Caution-backed fallback. Existing `--from-org-users`/`--caution-backed` selectors remain documented, and manual/direct PGP-only generation uses current V1. CLI output/download retains the complete proof envelope. `caution secret inspect` verifies persisted bundle evidence and exposes holder/context details; recovery supports native and browser approval. See the [creation contract](https://codeberg.org/caution/platform/src/commit/e38a05bf54dcd51f48971cbf2ca70884ffd8e812/docs/org-user-quorums.md) and [Platform recovery and validation](https://codeberg.org/caution/platform/src/commit/e38a05bf54dcd51f48971cbf2ca70884ffd8e812/docs/share-recovery.md). ## Implemented dashboard behavior The Secrets tab now provides a configure/review/create flow. It supports organization holders and manually added public PGP certificates, explicit passkey/external-PGP selection, threshold/count validation, a holder summary, signed creation, and an uncertain-outcome state without automatic retry. Multiple passkeys still authorize one share. Private-key uploads are rejected. Implementation and local UI/browser validation are documented in the [current dashboard section](https://codeberg.org/caution/platform/src/commit/1f7e2963932ac616ba6c4f0e9553112cb548ce72/docs/org-user-quorums.md). Real-authenticator and deployed service acceptance remain separate. ## Implemented API behavior API route paths (relative to the configured API base): - `GET /quorum-bundles/participants`: active organization members, registered public PGP keys and credential counts, without private keys or raw credential bindings. - `POST /quorum-bundles/from-org-users`: signed, authenticated hosted generation/storage. - `POST /quorum-bundles`: proof-verified upload; existing list/get/update/delete routes remain. Generation accepts optional `name`, required `threshold`, explicit `participants` (`user_id`, `key_source`, optional `pgp_key_id`), optional local `pgp_certificates`, `allow_caution_backed_keys` and `labels`. Key sources are `existing_pgp` and `caution_backed_pgp`. Hosted callers cannot set service URLs. Platform computes `max` from the assembled holders and validates threshold/count and independent key identities. The current handler resolves the authenticated user's organization and enforces selected-member/key eligibility; gateway-signed authorization is required for creation and bundle mutations. It does not introduce a separate owner/admin-only generation gate. Whether product policy should impose that additional role restriction remains an explicit decision below. Certificates, holder/credential associations and proof-bound quorum parameters are preserved through storage and full-bundle download. See the [API implementation](https://codeberg.org/caution/platform/src/commit/e38a05bf54dcd51f48971cbf2ca70884ffd8e812/src/api/src/org_quorum.rs). ## Keymaker and public key service configuration Hosted organization-user generation calls both services from Platform only. CLI/UI generation requests cannot supply or override service addresses. Use operator-managed `KEYMAKER_URL` and `PUBLIC_CERTIFICATE_SERVICE_URL`, together with independently provisioned PCR policies and the Caution CA. A database-backed static-IP registry is not required for this milestone. Missing/invalid required configuration fails affected operations closed. Direct PGP-only CLI generation remains a separate explicit mode; it does not override hosted configuration. Certificate issuance authentication is implemented by [Platform `5ebbe00`](https://codeberg.org/caution/platform/commit/5ebbe00ac395828806a1d0a9e083098770a3b2b1) and [Locksmith `30938f6`](https://codeberg.org/caution/locksmith/commit/30938f61864680c86fbfd108cf36ad5dced20453). Platform requires backend-only `PUBLIC_CERTIFICATE_SERVICE_TOKEN` (32 random bytes encoded as 64 hex characters), matching the custody service's encrypted vault input, and sends it only to `/v1/public-certificates` over HTTPS with redirects disabled. PGP-only creation does not need this token. The TLS terminator is trusted with the bearer credential; certificate/proof verification remains independent. The token is not forwarded to Keymaker and does not authorize shard release: public recryption routes retain WebAuthn approval. Hosted Keymaker access control and the original API-network-only reachability requirement are still outstanding; the bearer token does not make either service network-private. Certificate issuance and recryption still share one service/listener, with authentication applied only to issuance. Local/synthetic validation is recorded with those commits. Live issuance/recovery/restart acceptance for the current candidate is **not yet recorded**; token provisioning, deployment revisions and independent PCR-policy updates must be included in that record; see the [migration and acceptance runbook](https://codeberg.org/caution/locksmith/src/commit/30938f61864680c86fbfd108cf36ad5dced20453/docs/service-hardening.md). ## Keymaker concurrency Keymaker owns its single-use serialization and reset lifecycle, tracked in [Locksmith #2](https://codeberg.org/caution/locksmith/issues/2). Do not add a Platform semaphore or queue in this milestone. Platform sends one bounded generation attempt, propagates busy/error/timeout results, and does not retry generation automatically. A timeout can mean generation completed remotely. Each new quorum consumes a fresh Keymaker instance; configured host supervision now replaces terminated instances automatically. Recovery, approval retries and application enclave restarts do not consume Keymaker. Replacement downtime and lost-response outcomes remain explicit failures, without automatic generation replay. ## Current Keymaker contract The [shared model](https://codeberg.org/caution/locksmith/src/commit/2da3be50bebd2dfdc4d0d3a94d05f55be02e910c/crates/keymaker-models/src/lib.rs) defines: - Request: `GenerateQuorumRequest::V1`, with `bundle_id: [u8; 16]`, `label`, `threshold`, `max` and structured `keyring`. - Response: `GenerateQuorumResponse = Proofed<GenerateQuorumBundle>`. The outer object is `{data, necroproof}`; `data` is tagged `version: "V1"` and includes `bundle_id`, `label`, `keyring`, required `threshold`/`max`, `shardfile` and `public_key`. - Holders remain `Key::OpenPGP { cert }` or `Key::WebAuthn { credential, cert }`. Multiple credentials for one holder authorize one share. - UUIDs use canonical 16-byte representations. No legacy `keyring_hash` or inline payload proof is required. V0, unproofed and earlier V1 bundles missing required quorum parameters are unsupported. - For Caution-backed creation, the certificate service receives organization/count, generates the bundle UUID and returns proofed public certificates; Platform verifies that evidence and retains its UUID and credential associations when calling Keymaker. ## Implemented backend generation flow 1. Authenticate the requester, resolve their organization and validate the explicit request, active members, key-source eligibility, duplicate selections, labels and threshold. 2. Load selected registered/local public PGP certificates and snapshot current registered passkeys for Caution-backed holders. Resolve operator-configured URLs and independent trust inputs. 3. For WebAuthn/mixed creation, authenticate the certificate request with the backend bearer token; verify returned proof, CA certification, organization/bundle/index, certificate count and capabilities. Preserve the service-generated bundle UUID. PGP-only creation generates its own UUID and does not need certificate-service configuration. 4. Assemble ordered structured holders; retain credential associations and reject shared signing/encryption identities between holders. Equivalent encryption subkeys within one holder remain valid; ECDH identity ignores KDF hash/cipher differences. 5. Compute `max`, send one bounded current-V1 Keymaker generation request, verify the complete proofed response and compare requested bundle/labels/holders/quorum parameters. Keymaker owns single-use serialization/reset; busy/error/timeout never causes an automatic generation retry. 6. Store the complete proofed V1 envelope and return bundle metadata/public key. Later recovery/restarts do not consume Keymaker. ## Data/model status Registered user-owned public PGP keys and credential discovery are implemented. Hosted selection resolves exact active registrations and checks organization ownership; no new PGP-key table is pending for this flow. Service endpoints remain operator configuration, without a database endpoint registry. Guided dashboard creation is implemented. Remaining work is service access/security, acceptance evidence and the optional owner/admin policy decision. Existing bundles sharing encryption material are not repaired by stricter new-generation checks and need separate assessment/migration if present. ## Security requirements - Caution-backed keys must be explicitly selected by CLI/UI/API; do not generate them silently. - The API, not the CLI, must enforce organization membership and key-source eligibility. - Only organization members may be selected. - Requester authorization must be enforced server-side. - Generated Caution-backed material/certificates must be bound to the organization, user, bundle, purpose, and policy. - Public key service responses must be verified before returned certificates are included in the Keymaker keyring. - Duplicate certificates must not create duplicate quorum participants unless explicitly intended and documented. - Final keyring assembly must be deterministic. - Keymaker and public certificate service URLs are global operator-controlled server configuration. - CLI/UI generation requests must not include or override internal service IPs, ports, or URLs. - The API uses configured service base URLs and fixed endpoint paths; hosted requests cannot override them. - Hosted Keymaker and certificate issuance must be reachable only from the platform API network boundary. This network restriction remains outstanding; the implemented issuance bearer check is application authentication, and public recryption must remain available. - Keymaker enforces single-use serialization/reset; Platform does not add its own semaphore or queue. - Platform generation attempts are bounded and never automatically retried after success, error, timeout or malformed responses. - Missing or invalid required service/trust configuration must fail closed with a clear operator-facing error. - Do not log or expose secrets, private key material, raw bearer tokens, shard contents, raw request bodies, or decrypted values. ## Documentation updates After the feature lands, update CLI and user-facing docs to explain: - `caution secret new --from-org-users`; - when and why to use `--caution-backed`; - how Caution-backed OpenPGP keys differ from user-provided OpenPGP keys; - what happens for users who already have PGP keys vs users who do not; - how threshold/max are calculated when mixing existing PGP keys and Caution-backed keys; - where generated quorum bundles appear in the dashboard; - the security model and migration guidance for existing manual `caution secret new <keyring>` users. Do not consider the feature complete without docs. If docs are deferred to a later PR, the implementation PR should use `Refs #...` rather than closing this issue. ## Acceptance criteria - API exposes authenticated discovery for eligible organization users and available key sources. - API exposes authenticated generation/storage for quorum bundles from selected organization users. - API distinguishes existing user-provided PGP certificates from Caution-backed PGP certificates. - API validates membership, authorization, duplicate selections, selected key-source availability, and threshold/max. - API requires explicit Caution-backed selection before deriving/generated Caution-backed PGP material. - API assembles a deterministic Keymaker `v1::keyring: Vec<Key>` from selected existing OpenPGP and Caution/public-key-service-derived WebAuthn certificates. - Platform loads global operator-configured Keymaker/public certificate service URLs and independent trust files. - Organization-user quorum generation resolves both service URLs server-side. - CLI/UI cannot override Keymaker or public key service addresses. - API uses operator-configured base URLs with fixed endpoint paths. - Keymaker owns single-use serialization; the API propagates bounded failures without automatic generation retries. - API calls Keymaker `/generate_quorum` with the current V1 request and preserves/verifies the complete proof-wrapped V1 response. Legacy V0 callers are unsupported. - API validates the V1 response fields that exist in current Keymaker models: `bundle_id`, `label`, `keyring`, `threshold`, `max`, `shardfile`, and `public_key`. - API stores the resulting V1 response in existing organization quorum bundle storage and returns the stored bundle id and Keymaker public key. - API returns clear errors when required service URLs or trust configuration are missing/invalid. - CLI supports `caution secret init` (alias `new`), explicit per-holder custody and the documented `--from-org-users`/`--caution-backed` selectors. - CLI fails closed when selected users lack PGP keys and Caution-backed generation was not selected. - Dashboard Secrets page includes a guided create flow and clearly labels existing PGP vs Caution-backed PGP participants before creation. - Existing manual keyring-file CLI usage remains available using current V1; legacy V0 wire/bundle compatibility is not implied. - Docs are updated for the CLI command, dashboard workflow, Caution-backed key behavior, and security model. ## Suggested tests - discovery endpoint only returns users in the requester's organization; - generation rejects users outside the organization, duplicate participants, unavailable key source, Caution-backed users when disabled, and `threshold > max`; - generation rejects malformed/mismatched Caution-backed certificate response; - generation assembles deterministic `GenerateQuorumRequest::V1` from mixed existing OpenPGP and Caution/public-key-service-derived WebAuthn certificates; - successful generation stores the typed Keymaker V1 response in `quorum_bundles`; - existing raw quorum bundle upload/list/get/update/delete behavior remains compatible; - generation fails clearly when a required service URL or trust file is missing/invalid; - generation ignores/rejects any request field attempting to set internal service address; - integration tests exercise Keymaker-owned single-use admission with concurrent generation requests; - busy/error/timeout responses do not cause automatic generation retries; - public certificate service URL comes from operator configuration, never hosted request input; - platform integration test or contract test proves the Keymaker route accepts the expected top-level V1 envelope before enabling organization-user generation. ## Remaining product and access decisions - Completed: the Secrets creation flow, holder/approval-method selection, threshold/review and signed creation/failure behavior. Retain real-device/deployment acceptance as a separate gate. - Complete hosted Keymaker access control and API-network-only reachability for generation/issuance while keeping WebAuthn-authorized recryption public. Bearer authentication does not enforce network isolation; current ingress provisioning does not preserve per-rule source CIDRs. - Decide whether to add an owner/admin-only generation policy beyond the current authenticated-organization-member/signed-request behavior. Do not describe such a gate as already implemented. - Complete retained service/lifecycle requirements under #383 and record exact-revision live acceptance before closure. The current CA-certified profile and fixed hash encodings are accepted/implemented; a general structure-hash registry remains deferred. Track production revocation/root-recovery work explicitly. Resolved implementation choices: canonical 16-byte UUIDs; proof-wrapped current V1 with required threshold/max; V1 Keymaker route; fixed participant/generation API routes; one selected registered PGP certificate or one derived certificate per organization holder; multiple passkeys as one share; server-computed max. These no longer need to be posed as open wire-format questions. ## In-repository prerequisite - https://codeberg.org/caution/platform/issues/383 — public certificate derivation service for Caution-backed/WebAuthn-derived OpenPGP certificates. Keep #383 separate from this issue: #383 defines and implements the certificate derivation/proof service, while this issue tracks the platform API/CLI/dashboard organization-user quorum bundle flow that consumes that service. Do not close this issue until the #383 service contract is implemented and integrated for Caution-backed participants. ## Cross-repository implementation dependencies This platform feature depends on Locksmith/Keymaker work tracked separately: - caution/locksmith#10: Keymaker: generate v1 quorum bundles from structured OpenPGP/WebAuthn keys — https://codeberg.org/caution/locksmith/issues/10 - caution/locksmith#11: Locksmith: verify and load proofed V1 quorum bundles — https://codeberg.org/caution/locksmith/issues/11 - caution/locksmith#12: Implement WebAuthn-signed shard recryption transport — https://codeberg.org/caution/locksmith/issues/12 The platform API/CLI/UI work should treat these as prerequisites before closing this issue: Keymaker must accept/generate V1 bundles from structured key material, Locksmith must verify/load current proofed V1 bundles and reject unsupported legacy formats, and the WebAuthn signed transport plan from `caution/locksmith#7` must be implemented for Caution-backed shard recryption.
caution-bot commented 2026-07-17 20:21:25 +00:00 (Migrated from codeberg.org)

Updated the issue body against latest caution/locksmith main (0bb7924). Keymaker models now have top-level V1-only envelopes while the legacy v0 structs still exist under generate_quorum::v0; the current Keymaker route still serves v0. I also corrected the V1 response fields to match current keymaker-models (bundle_id, label, keyring, shardfile, public_key) and left the [u8; 32] bundle-id representation and V1 route migration as explicit open questions.

Updated the issue body against latest `caution/locksmith` `main` (`0bb7924`). Keymaker models now have top-level V1-only envelopes while the legacy `v0` structs still exist under `generate_quorum::v0`; the current Keymaker route still serves `v0`. I also corrected the V1 response fields to match current `keymaker-models` (`bundle_id`, `label`, `keyring`, `shardfile`, `public_key`) and left the `[u8; 32]` bundle-id representation and V1 route migration as explicit open questions.
caution-bot commented 2026-07-18 21:46:06 +00:00 (Migrated from codeberg.org)

Added cross-repository dependency tracking for the Keymaker/Locksmith prerequisites:

Also cross-linked these from caution/locksmith#7, leaving that issue as the authoritative WebAuthn transport design thread.

Added cross-repository dependency tracking for the Keymaker/Locksmith prerequisites: - https://codeberg.org/caution/locksmith/issues/10 — Keymaker: generate v1 quorum bundles from structured OpenPGP/WebAuthn keys - https://codeberg.org/caution/locksmith/issues/11 — Locksmith: load v1 quorum bundles with v0 fallback and upgrade - https://codeberg.org/caution/locksmith/issues/12 — Implement WebAuthn-signed shard recryption transport Also cross-linked these from `caution/locksmith#7`, leaving that issue as the authoritative WebAuthn transport design thread.
vkobel commented 2026-09-17 15:04:07 +00:00 (Migrated from codeberg.org)

The API/CLI V1 flow and WebAuthn recovery are integrated and exercised end to end. Explicit custody selection, membership/eligibility checks, deterministic holder assembly, proof verification, storage and required-artifact deployment preflight are implemented.

Outstanding acceptance differences:

  • Dashboard supports bundle management but has no guided creation wizard; it directs users to the CLI.
  • Service addresses use operator-configured environment URLs rather than persisted active static-IP records.
  • No Platform single-permit Keymaker semaphore exists. Documentation intentionally assigns serialization/reset behavior to Locksmith #2; reconcile this issue with that decision.
  • Legacy V0 compatibility remains unresolved under Locksmith #10/#11. Retaining the manual CLI command does not preserve the old wire/bundle format.

Keep open until these items are implemented or explicitly removed from scope. Update older descriptions of WebAuthn recovery as blocked and record the completed E2E evidence.

The API/CLI V1 flow and WebAuthn recovery are integrated and exercised end to end. Explicit custody selection, membership/eligibility checks, deterministic holder assembly, proof verification, storage and required-artifact deployment preflight are implemented. Outstanding acceptance differences: - Dashboard supports bundle management but has no guided creation wizard; it directs users to the CLI. - Service addresses use operator-configured environment URLs rather than persisted active static-IP records. - No Platform single-permit Keymaker semaphore exists. Documentation intentionally assigns serialization/reset behavior to Locksmith #2; reconcile this issue with that decision. - Legacy V0 compatibility remains unresolved under Locksmith #10/#11. Retaining the manual CLI command does not preserve the old wire/bundle format. Keep open until these items are implemented or explicitly removed from scope. Update older descriptions of WebAuthn recovery as blocked and record the completed E2E evidence.
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
public/platform#384
No description provided.