diff --git a/README.md b/README.md index 8566e24..7cc32fe 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ docs/ roadmap-status.md membership-pricing-policy.md membership-tier-extension.md + wallet-ownership-payment-model.md failure-state-matrix.md legal-copy-matrix.md localization-qa-matrix.md @@ -47,8 +48,11 @@ docs/ public-trust-page-spec.md migration-policy-v1-to-v2.md issuer-onboarding-pack.md + launcher-free-tier-spec.md release-gate.md app-channel-spec.md + governance-install-spec.md + repo-boundary-blueprint.md review-notes.md platform-spec-alignment-review.md contracts/ @@ -56,6 +60,7 @@ docs/ conformance/ membership-gating-vectors.md member-channel-vectors.md + governance-install-vectors.md deployment/ README.md chain-config.template.json @@ -65,14 +70,17 @@ docs/ secret-system.openapi.yaml marketplace.openapi.yaml member-channel.openapi.yaml + governance-installer.openapi.yaml examples/ secret-system.examples.md marketplace.examples.md member-channel.examples.md + governance-installer.examples.md handoff/ membership-backend-checklist.md marketplace-backend-checklist.md member-channel-backend-checklist.md + governance-backend-checklist.md schemas/ offer.v1.schema.json entitlement.v1.schema.json diff --git a/docs/api/examples/governance-installer.examples.md b/docs/api/examples/governance-installer.examples.md new file mode 100644 index 0000000..5447924 --- /dev/null +++ b/docs/api/examples/governance-installer.examples.md @@ -0,0 +1,105 @@ +# Governance Installer API Examples + +## Create Install Token + +### Request + +```http +POST /governance/install/token +Authorization: Bearer +Content-Type: application/json + +{ + "wallet": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", + "device_id": "desktop-7f6f3a9b", + "launcher_version": "0.2.0", + "platform": "macos", + "current_runtime_version": "0.0.0" +} +``` + +### Response + +```json +{ + "install_token": "git_01J9B6A97WQG8GNYM4ZBX8E2NQ", + "install_token_expires_at": "2026-02-18T01:05:00Z", + "wallet": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", + "entitlement_id": "ent_governance_001", + "package": { + "runtime_version": "1.0.0", + "package_url": "https://cdn.edut.ai/runtime/governance/1.0.0/macos-arm64.pkg", + "package_hash": "sha256:09f6d64f...", + "signature": "ed25519:8db9...", + "signer_key_id": "governance-signer-2026-01", + "policy_hash": "sha256:f10419ac...", + "rollout_channel": "stable" + } +} +``` + +## Confirm Install + +### Request + +```http +POST /governance/install/confirm +Authorization: Bearer +Content-Type: application/json + +{ + "install_token": "git_01J9B6A97WQG8GNYM4ZBX8E2NQ", + "wallet": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", + "device_id": "desktop-7f6f3a9b", + "entitlement_id": "ent_governance_001", + "package_hash": "sha256:09f6d64f...", + "runtime_version": "1.0.0", + "installed_at": "2026-02-18T01:01:48Z", + "launcher_receipt_hash": "sha256:8102d437..." +} +``` + +### Response + +```json +{ + "status": "governance_active", + "wallet": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", + "device_id": "desktop-7f6f3a9b", + "entitlement_id": "ent_governance_001", + "runtime_version": "1.0.0", + "activated_at": "2026-02-18T01:01:50Z" +} +``` + +## Install Status + +### Request + +```http +GET /governance/install/status?wallet=0x742d35Cc6634C0532925a3b844Bc454e4438f44e&device_id=desktop-7f6f3a9b +Authorization: Bearer +``` + +### Response + +```json +{ + "wallet": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", + "membership_status": "active", + "entitlement_status": "active", + "activation_status": "active", + "latest_runtime_version": "1.0.0", + "policy_hash": "sha256:f10419ac..." +} +``` + +## Error: Entitlement Inactive + +```json +{ + "error": "entitlement_inactive", + "code": "entitlement_inactive", + "correlation_id": "req_01J9B6BJBVKY3N6WQ7TQM2R2P5" +} +``` diff --git a/docs/api/examples/marketplace.examples.md b/docs/api/examples/marketplace.examples.md index 2539b44..9434f38 100644 --- a/docs/api/examples/marketplace.examples.md +++ b/docs/api/examples/marketplace.examples.md @@ -8,14 +8,14 @@ Success (`200`): { "offers": [ { - "offer_id": "edut.crm.pro.annual", + "offer_id": "edut.governance.core", "issuer_id": "edut.firstparty", - "title": "EDUT CRM Pro", - "summary": "Workspace-bound CRM module.", + "title": "EDUT Governance Core", + "summary": "First paid runtime license.", "status": "active", "pricing": { "currency": "USDC", - "amount_atomic": "199000000", + "amount_atomic": "499000000", "decimals": 6, "chain_id": 8453 }, @@ -36,8 +36,9 @@ Request: ```json { "wallet": "0x3ea6cbf98d23e2cf7b6f4f9bb1fb4f50b710f2d5", - "offer_id": "edut.crm.pro.annual", - "workspace_id": "workspace.work.acme" + "payer_wallet": "0x2299547f6fA9A8f9b6d9aEA9F9D8A4B53C8A0e11", + "offer_id": "edut.governance.core", + "ownership_proof": "0x9f20..." } ``` @@ -47,10 +48,11 @@ Success (`200`): { "quote_id": "cq_01HZZXFQ27ZP6MP0V2R9M6V3KX", "wallet": "0x3ea6cbf98d23e2cf7b6f4f9bb1fb4f50b710f2d5", - "offer_id": "edut.crm.pro.annual", + "payer_wallet": "0x2299547f6fA9A8f9b6d9aEA9F9D8A4B53C8A0e11", + "offer_id": "edut.governance.core", "currency": "USDC", - "amount": "199.00", - "amount_atomic": "199000000", + "amount": "499.00", + "amount_atomic": "499000000", "decimals": 6, "policy_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "expires_at": "2026-02-17T07:44:30Z", @@ -79,7 +81,8 @@ Request: { "quote_id": "cq_01HZZXFQ27ZP6MP0V2R9M6V3KX", "wallet": "0x3ea6cbf98d23e2cf7b6f4f9bb1fb4f50b710f2d5", - "offer_id": "edut.crm.pro.annual", + "payer_wallet": "0x2299547f6fA9A8f9b6d9aEA9F9D8A4B53C8A0e11", + "offer_id": "edut.governance.core", "tx_hash": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "chain_id": 8453 } @@ -91,7 +94,7 @@ Success (`200`): { "status": "entitlement_active", "entitlement_id": "ent:8453:0x3ea6cbf98d23e2cf7b6f4f9bb1fb4f50b710f2d5:000001", - "offer_id": "edut.crm.pro.annual", + "offer_id": "edut.governance.core", "wallet": "0x3ea6cbf98d23e2cf7b6f4f9bb1fb4f50b710f2d5", "tx_hash": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "policy_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", diff --git a/docs/api/governance-installer.openapi.yaml b/docs/api/governance-installer.openapi.yaml new file mode 100644 index 0000000..44cdea5 --- /dev/null +++ b/docs/api/governance-installer.openapi.yaml @@ -0,0 +1,241 @@ +openapi: 3.1.0 +info: + title: EDUT Governance Installer API + version: 1.0.0 + description: | + Deterministic governance install authorization and package metadata retrieval. +servers: + - url: https://api.edut.ai +security: + - WalletSession: [] +paths: + /governance/install/token: + post: + summary: Authorize governance install for ownership wallet. + operationId: createGovernanceInstallToken + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/InstallTokenRequest' + responses: + '200': + description: Install authorization token and signed package metadata. + content: + application/json: + schema: + $ref: '#/components/schemas/InstallTokenResponse' + '403': + description: Membership or governance entitlement inactive. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /governance/install/confirm: + post: + summary: Confirm successful local install evidence. + operationId: confirmGovernanceInstall + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/InstallConfirmRequest' + responses: + '200': + description: Install confirmed and runtime activation allowed. + content: + application/json: + schema: + $ref: '#/components/schemas/InstallConfirmResponse' + '409': + description: Policy mismatch or stale install token. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /governance/install/status: + get: + summary: Resolve governance activation eligibility and latest runtime package for wallet. + operationId: getGovernanceInstallStatus + parameters: + - in: query + name: wallet + required: true + schema: + type: string + - in: query + name: device_id + required: false + schema: + type: string + responses: + '200': + description: Current governance install and entitlement status. + content: + application/json: + schema: + $ref: '#/components/schemas/InstallStatusResponse' +components: + securitySchemes: + WalletSession: + type: http + scheme: bearer + bearerFormat: EDUT-WALLET-SESSION + schemas: + InstallTokenRequest: + type: object + required: + - wallet + - device_id + - launcher_version + - platform + properties: + wallet: + type: string + device_id: + type: string + launcher_version: + type: string + platform: + type: string + enum: [macos, windows, linux] + current_runtime_version: + type: string + InstallTokenResponse: + type: object + required: + - install_token + - install_token_expires_at + - wallet + - entitlement_id + - package + properties: + install_token: + type: string + install_token_expires_at: + type: string + format: date-time + wallet: + type: string + entitlement_id: + type: string + package: + $ref: '#/components/schemas/GovernancePackage' + GovernancePackage: + type: object + required: + - runtime_version + - package_url + - package_hash + - signature + - signer_key_id + - policy_hash + properties: + runtime_version: + type: string + package_url: + type: string + format: uri + package_hash: + type: string + signature: + type: string + signer_key_id: + type: string + policy_hash: + type: string + rollout_channel: + type: string + enum: [stable, canary] + default: stable + InstallConfirmRequest: + type: object + required: + - install_token + - wallet + - device_id + - entitlement_id + - package_hash + - runtime_version + - installed_at + properties: + install_token: + type: string + wallet: + type: string + device_id: + type: string + entitlement_id: + type: string + package_hash: + type: string + runtime_version: + type: string + installed_at: + type: string + format: date-time + launcher_receipt_hash: + type: string + InstallConfirmResponse: + type: object + required: + - status + - wallet + - device_id + - entitlement_id + - runtime_version + - activated_at + properties: + status: + type: string + enum: [governance_active] + wallet: + type: string + device_id: + type: string + entitlement_id: + type: string + runtime_version: + type: string + activated_at: + type: string + format: date-time + InstallStatusResponse: + type: object + required: + - wallet + - membership_status + - entitlement_status + - activation_status + properties: + wallet: + type: string + membership_status: + type: string + enum: [active, none, suspended, revoked, unknown] + entitlement_status: + type: string + enum: [active, none, suspended, revoked, unknown] + activation_status: + type: string + enum: [not_installed, pending, active, blocked] + latest_runtime_version: + type: string + policy_hash: + type: string + reason: + type: string + ErrorResponse: + type: object + required: + - error + - code + properties: + error: + type: string + code: + type: string + correlation_id: + type: string diff --git a/docs/api/marketplace.openapi.yaml b/docs/api/marketplace.openapi.yaml index 6a6f1ec..74c5909 100644 --- a/docs/api/marketplace.openapi.yaml +++ b/docs/api/marketplace.openapi.yaml @@ -144,10 +144,18 @@ components: wallet: type: string pattern: '^0x[a-fA-F0-9]{40}$' + description: Ownership wallet that will receive entitlement. + payer_wallet: + type: string + pattern: '^0x[a-fA-F0-9]{40}$' + description: Optional wallet paying the quote transaction when different from ownership wallet. offer_id: type: string workspace_id: type: string + ownership_proof: + type: string + description: Optional ownership-wallet signature proving entitlement recipient approval when payer differs. CheckoutQuoteResponse: type: object required: [quote_id, wallet, offer_id, currency, amount_atomic, policy_hash, expires_at] @@ -156,6 +164,8 @@ components: type: string wallet: type: string + payer_wallet: + type: string offer_id: type: string currency: @@ -183,6 +193,11 @@ components: wallet: type: string pattern: '^0x[a-fA-F0-9]{40}$' + description: Ownership wallet bound to entitlement. + payer_wallet: + type: string + pattern: '^0x[a-fA-F0-9]{40}$' + description: Optional payment wallet for tx provenance when different from ownership wallet. offer_id: type: string tx_hash: diff --git a/docs/conformance/governance-install-vectors.md b/docs/conformance/governance-install-vectors.md new file mode 100644 index 0000000..637171e --- /dev/null +++ b/docs/conformance/governance-install-vectors.md @@ -0,0 +1,26 @@ +# Conformance Vectors: Governance Install and Activation v1 + +These vectors verify deterministic governance runtime installation and activation gates. + +## Vector Set + +1. `GV-001` install token requires active membership. +2. `GV-002` install token requires active governance entitlement. +3. `GV-003` expired install token blocks confirm. +4. `GV-004` package hash mismatch blocks activation. +5. `GV-005` runtime version mismatch blocks activation. +6. `GV-006` valid install confirm yields `governance_active`. +7. `GV-007` replayed install confirm is idempotent and no duplicate activation side effects. +8. `GV-008` entitlement revoked after activation forces status `blocked` until entitlement restored. +9. `GV-009` membership suspended forces status `blocked` regardless of local runtime presence. +10. `GV-010` unknown entitlement state fails closed and blocks activation. + +## Pass Criteria + +1. All vectors pass in CI and staging. +2. Any vector failure blocks release per release gate. +3. Evidence artifact includes vector id, payload fingerprint, and correlation id. + +## Fail-Closed Rule + +Any uncertainty in membership state, entitlement state, install token validity, package hash, signature, or policy hash must block activation by default. diff --git a/docs/conformance/membership-gating-vectors.md b/docs/conformance/membership-gating-vectors.md index 22ed6b5..7ce7c42 100644 --- a/docs/conformance/membership-gating-vectors.md +++ b/docs/conformance/membership-gating-vectors.md @@ -100,6 +100,18 @@ This document defines deterministic pass/fail vectors for membership-gated comme - When runtime activation is requested - Then activation fails closed +## Vector Group F: Ownership Wallet vs Payment Wallet + +1. F1 `quote_allow_distinct_payer_with_proof` +- Given ownership wallet A, payer wallet B, and valid ownership proof +- When checkout quote is requested +- Then quote is issued for ownership wallet A and records payer wallet B + +2. F2 `quote_block_distinct_payer_without_proof` +- Given ownership wallet A and payer wallet B without ownership proof +- When checkout quote is requested +- Then quote is denied + ## Vector Group E: Evidence Integrity 1. E1 `receipt_fields_complete` diff --git a/docs/contracts/membership-platform-interfaces.md b/docs/contracts/membership-platform-interfaces.md index fb55409..1ec6100 100644 --- a/docs/contracts/membership-platform-interfaces.md +++ b/docs/contracts/membership-platform-interfaces.md @@ -74,6 +74,12 @@ EntitlementState: 4. `POST /marketplace/checkout/confirm` 5. `GET /marketplace/entitlements` +## Governance Installer + +1. `POST /governance/install/token` +2. `POST /governance/install/confirm` +3. `GET /governance/install/status` + ## Issuer APIs 1. `POST /issuer/offers/upsert` @@ -84,7 +90,8 @@ EntitlementState: 1. Every checkout quote must include: - `quote_id` - - `wallet` + - `wallet` (ownership wallet) + - `payer_wallet` (optional) - `offer_id` - `currency` - `amount_atomic` diff --git a/docs/failure-state-matrix.md b/docs/failure-state-matrix.md index a244968..27e4121 100644 --- a/docs/failure-state-matrix.md +++ b/docs/failure-state-matrix.md @@ -9,6 +9,7 @@ This matrix defines deterministic fail-closed behavior and user-facing outcomes. | Verify | Intent expired | TTL check | Reject verify | "Intent expired. Start again." | | Verify | Signature mismatch | Signature recovery | Reject verify + audit entry | "Signature could not be verified." | | Quote | Signature not verified | State check | Deny quote | "Verify wallet signature first." | +| Quote | Distinct payer without ownership proof | Proof validator | Deny quote | "Ownership authorization is required." | | Quote | Quote expired | TTL check | Deny confirm | "Quote expired. Request a new quote." | | Mint | Wallet reject tx | Wallet provider | No state change | "Membership mint was not approved." | | Confirm | Wrong chain | Chain check | Reject confirm | "Transaction is on an unsupported chain." | @@ -17,6 +18,9 @@ This matrix defines deterministic fail-closed behavior and user-facing outcomes. | Confirm | Node unavailable | RPC health | Fail closed | "Unable to confirm transaction. Purchase stays blocked." | | Checkout | No membership | Gate check | Block purchase | "Membership required." | | Checkout | Membership suspended/revoked | Gate check | Block purchase | "Membership inactive. Contact support." | +| Governance Install | Install token expired | TTL check | Block install | "Install token expired. Request a new install token." | +| Governance Install | Package hash mismatch | Package verifier | Block activation | "Package verification failed." | +| Governance Install | Policy hash mismatch | Runtime verifier | Block activation | "Policy mismatch. Install blocked." | | Activation | Entitlement not active | Gate check | Block runtime | "License inactive. Activation blocked." | ## Invariants diff --git a/docs/governance-install-spec.md b/docs/governance-install-spec.md new file mode 100644 index 0000000..894f394 --- /dev/null +++ b/docs/governance-install-spec.md @@ -0,0 +1,71 @@ +# Governance Install Specification (First Paid License) + +This spec defines deterministic installation of the governance runtime after membership and governance entitlement purchase. + +## Preconditions + +1. Launcher is installed and wallet is initialized locally. +2. Membership is active for ownership wallet. +3. Governance entitlement is active for ownership wallet. + +## Install Flow + +1. Launcher requests governance install token from backend. +2. Backend verifies membership and governance entitlement status. +3. Backend returns signed install bundle metadata: +- package url +- package hash +- signer key id +- policy hash +- expiry +4. Launcher downloads package. +5. Launcher verifies package hash. +6. Launcher verifies package signature against trusted signer set. +7. Launcher writes immutable install receipt locally. +8. Launcher hands off to governance runtime bootstrap. +9. Governance runtime re-verifies entitlement receipt and policy hash. +10. Runtime activation state transitions to `ACTIVE`. + +## Activation State Machine + +`NOT_INSTALLED` -> `DOWNLOADED` -> `VERIFIED` -> `BOOTSTRAPPED` -> `ACTIVE` + +Failure states: + +- `VERIFY_FAILED` +- `RECEIPT_INVALID` +- `ENTITLEMENT_INACTIVE` +- `POLICY_MISMATCH` + +## Deterministic Rules + +1. Any missing signature/hash mismatch blocks install. +2. Any inactive/unknown entitlement blocks activation. +3. Any policy hash mismatch blocks activation. +4. Activation requires both launcher and runtime verification passes. +5. Reinstall with same package hash must be idempotent. + +## Ownership vs Payment Wallet + +1. Entitlement ownership wallet controls activation rights. +2. Payment wallet may differ from ownership wallet. +3. Activation checks only ownership wallet + entitlement state. + +## Evidence Requirements + +Each successful install must persist evidence containing: + +1. ownership wallet +2. entitlement id +3. package hash +4. signer key id +5. policy hash +6. activation timestamp +7. launcher version +8. runtime version + +## Non-Goals + +1. Running governance runtime before entitlement verification. +2. Trusting unsigned packages. +3. Allowing active runtime on revoked entitlement. diff --git a/docs/handoff/governance-backend-checklist.md b/docs/handoff/governance-backend-checklist.md new file mode 100644 index 0000000..f7aebb4 --- /dev/null +++ b/docs/handoff/governance-backend-checklist.md @@ -0,0 +1,49 @@ +# Backend Handoff Checklist: Governance Install and Activation + +This checklist maps launcher-governance install behavior to backend requirements. + +## Required Endpoints + +1. `POST /governance/install/token` +2. `POST /governance/install/confirm` +3. `GET /governance/install/status` + +## Contract Source + +1. `docs/api/governance-installer.openapi.yaml` +2. `docs/api/examples/governance-installer.examples.md` + +## Required Gate Behavior + +1. Install token issuance requires active membership. +2. Install token issuance requires active governance entitlement. +3. Confirm path must validate package hash and runtime version against issued token. +4. Status must fail closed when entitlement state is unknown. + +## Persistence Requirements + +1. Install token issuance record with expiry. +2. Package metadata snapshot bound to install token. +3. Confirm event record with wallet, device_id, entitlement_id, package hash. +4. Activation state record and immutable evidence receipt hash. + +## Security Requirements + +1. Install token TTL enforcement. +2. Wallet/session matching on all requests. +3. Idempotent confirm by install token + device + package hash. +4. Reject stale or replayed install confirmations. + +## Observability Requirements + +1. Metrics for token issuance success/fail. +2. Metrics for confirm success/fail. +3. Metrics for activation blocked by membership/entitlement. +4. Correlation IDs for all state transitions. + +## Done Criteria + +1. Launcher can install governance only when entitlement is active. +2. Runtime cannot activate if package signature/hash checks fail. +3. `governance_active` status is deterministic and auditable. +4. API implementation matches OpenAPI contract. diff --git a/docs/handoff/marketplace-backend-checklist.md b/docs/handoff/marketplace-backend-checklist.md index a4e9e6e..01ad8f9 100644 --- a/docs/handoff/marketplace-backend-checklist.md +++ b/docs/handoff/marketplace-backend-checklist.md @@ -19,30 +19,33 @@ This checklist maps store behavior to required marketplace backend implementatio ## Store Dependency Mapping 1. Store catalog requests `/marketplace/offers` (fallback to local JSON until live). -2. Store quote action posts selected `offer_id` and wallet. -3. Store expects quote payload with tx execution fields. -4. Store confirm path expects `entitlement_active` response. +2. Store quote action posts selected `offer_id` and ownership wallet. +3. Optional payer wallet may differ and must include ownership proof. +4. Store expects quote payload with tx execution fields. +5. Store confirm path expects `entitlement_active` response. ## Quote Response Requirements 1. `quote_id` -2. `wallet` -3. `offer_id` -4. `currency` -5. `amount` or `amount_atomic + decimals` -6. `policy_hash` -7. `expires_at` -8. `tx` execution object or equivalent fields +2. `wallet` (ownership wallet) +3. `payer_wallet` (optional) +4. `offer_id` +5. `currency` +6. `amount` or `amount_atomic + decimals` +7. `policy_hash` +8. `expires_at` +9. `tx` execution object or equivalent fields ## Confirm Response Requirements 1. `status = entitlement_active` 2. `entitlement_id` 3. `offer_id` -4. `wallet` -5. `tx_hash` -6. `policy_hash` -7. `activated_at` +4. `wallet` (ownership wallet) +5. `payer_wallet` (optional) +6. `tx_hash` +7. `policy_hash` +8. `activated_at` ## Persistence Requirements @@ -56,6 +59,7 @@ This checklist maps store behavior to required marketplace backend implementatio 2. Quote TTL enforcement. 3. Tx chain, amount, and destination validation. 4. Idempotent confirm handling for repeated tx hash submissions. +5. Ownership wallet proof validation when payer wallet differs. ## Done Criteria diff --git a/docs/implementation-mapping.md b/docs/implementation-mapping.md index 40b13b5..f9e2811 100644 --- a/docs/implementation-mapping.md +++ b/docs/implementation-mapping.md @@ -12,12 +12,14 @@ 2. Deterministic state transitions and persistence. 3. Chain verification and policy hash enforcement. 4. Member app channel endpoints for device registration and event polling. +5. Governance installer endpoints for signed package authorization and activation confirmation. ## Runtime/Kernel Responsibilities 1. Membership and entitlement gates at activation points. 2. Fail-closed behavior for uncertain states. 3. Evidence receipt generation and retention. +4. Signed package verification and policy hash checks before governance activation. ## Required Integration Contract diff --git a/docs/integration-test-plan.md b/docs/integration-test-plan.md index 411c6a0..2648cec 100644 --- a/docs/integration-test-plan.md +++ b/docs/integration-test-plan.md @@ -2,7 +2,7 @@ ## Objective -Validate end-to-end behavior from wallet intent to membership-gated checkout. +Validate end-to-end behavior from wallet intent to membership-gated checkout and governance activation. ## E2E Scenarios @@ -13,6 +13,9 @@ Validate end-to-end behavior from wallet intent to membership-gated checkout. 5. Membership suspended blocks checkout. 6. Active membership enables checkout quote. 7. Entitlement non-active blocks runtime activation. +8. Governance install token denied when membership or governance entitlement is inactive. +9. Governance install confirm denied when package hash/policy hash mismatches issued token. +10. Governance runtime activation succeeds only after signed package verification + entitlement active. ## Artifacts diff --git a/docs/launcher-free-tier-spec.md b/docs/launcher-free-tier-spec.md new file mode 100644 index 0000000..92d905b --- /dev/null +++ b/docs/launcher-free-tier-spec.md @@ -0,0 +1,39 @@ +# Launcher Free-Tier Specification + +The launcher is free and intentionally limited to onboarding and control-plane functions. + +## Scope Included (Free) + +1. App install and first-run flow. +2. Local wallet create/import/recovery UX. +3. Device readiness checks (cpu, memory, disk, os compatibility). +4. Membership status display. +5. Governance purchase/install prompts and status. +6. App-native member notification inbox. + +## Scope Excluded (Paid / Protected) + +1. Governance runtime internals. +2. Deterministic card pipeline execution. +3. Paid module execution logic. +4. Private scoring and policy internals. + +## Security Rules + +1. Launcher never stores server-side private keys. +2. Launcher verifies signed package manifests before install. +3. Launcher cannot activate governance runtime without active entitlement. +4. Unknown entitlement state blocks protected feature activation. + +## UX Rules + +1. User can exit and resume setup at any point. +2. Membership purchase is optional in free mode. +3. Governance purchase is blocked until membership is active. +4. Free mode remains useful for readiness and wallet setup. + +## Value Contract + +1. Free launcher gives control and visibility. +2. Paid governance unlocks execution. +3. Additional paid licenses extend capabilities after governance activation. diff --git a/docs/release-gate.md b/docs/release-gate.md index 52b053e..1aa915b 100644 --- a/docs/release-gate.md +++ b/docs/release-gate.md @@ -14,14 +14,16 @@ This gate controls deploy/no-deploy decisions for membership-gated commerce chan 1. `docs/conformance/membership-gating-vectors.md`: all vectors pass. 2. `docs/conformance/member-channel-vectors.md`: all vectors pass. -3. OpenAPI and implementation remain compatible. -4. Signature replay tests pass. -5. Quote expiry tests pass. -6. Tx mismatch tests pass. -7. Membership gate blocks non-members in all checkout paths. -8. Member channel blocks inactive memberships. -9. Terms/privacy copy still match utility-access framing. -10. Structured logs and metrics are emitted for each state transition. +3. `docs/conformance/governance-install-vectors.md`: all vectors pass. +4. OpenAPI and implementation remain compatible. +5. Signature replay tests pass. +6. Quote expiry tests pass. +7. Tx mismatch tests pass. +8. Membership gate blocks non-members in all checkout paths. +9. Member channel blocks inactive memberships. +10. Governance activation blocks inactive/unknown entitlement states. +11. Terms/privacy copy still match utility-access framing. +12. Structured logs and metrics are emitted for each state transition. ## No-Deploy Triggers @@ -29,8 +31,9 @@ This gate controls deploy/no-deploy decisions for membership-gated commerce chan 2. Any path that allows purchase without active membership. 3. Any activation path that proceeds with non-active entitlement. 4. Any member channel path serving events to suspended/revoked memberships. -5. Any missing audit evidence on successful purchase. -6. Any breaking API change without version bump and migration note. +5. Any governance runtime activation without valid signed package verification. +6. Any missing audit evidence on successful purchase. +7. Any breaking API change without version bump and migration note. ## Evidence Bundle Required for Release diff --git a/docs/repo-boundary-blueprint.md b/docs/repo-boundary-blueprint.md new file mode 100644 index 0000000..e827317 --- /dev/null +++ b/docs/repo-boundary-blueprint.md @@ -0,0 +1,65 @@ +# EDUT Repo Boundary Blueprint + +This blueprint defines long-lived repository separation by trust boundary. + +## Repository Map + +1. `web` (public) +- Public landing/store surfaces +- Legal pages and public trust facts +- OpenAPI contracts and implementation handoff docs +- No proprietary kernel algorithms + +2. `launcher` (controlled distribution) +- Free installer shell +- Local wallet create/import UX +- Device readiness checks +- Updater and package verifier +- No paid governance runtime internals + +3. `governance` (private) +- Deterministic kernel runtime +- Activation and policy execution engine +- Card pipeline internals and scoring logic +- Protected IP modules and signed package build + +4. `contracts` (public/auditable) +- Membership and entitlement contracts +- ABI and deployment artifacts +- Contract conformance vectors + +## Data Ownership Boundaries + +1. `web` owns public copy and API contract documents. +2. `launcher` owns local identity UX and package verification logic. +3. `governance` owns runtime decisions and private implementation. +4. `contracts` owns settlement and on-chain entitlement primitives. + +## Release Dependency Chain + +1. Contract release publishes addresses and ABI. +2. Web release points at versioned API and contract addresses. +3. Launcher release trusts specific signer keys and policy hashes. +4. Governance release packages signed runtimes for entitled installs. + +## Security Boundary Rules + +1. Launcher must verify governance package signature before install. +2. Governance must verify entitlement receipt before activation. +3. Unknown entitlement state fails closed. +4. Private kernel code never ships in public web artifacts. + +## Minimal First Paid Path + +1. User installs free launcher. +2. User creates/imports local EDUT wallet. +3. User mints membership. +4. User purchases governance offer. +5. Launcher downloads signed governance package. +6. Governance activates only with valid entitlement receipt. + +## Non-Goals + +1. Single monorepo that grants broad access to private kernel internals. +2. Public distribution of paid runtime logic before entitlement checks. +3. Coupling payment wallet and ownership wallet by force. diff --git a/docs/roadmap-membership-platform.md b/docs/roadmap-membership-platform.md index dbb42c9..5159579 100644 --- a/docs/roadmap-membership-platform.md +++ b/docs/roadmap-membership-platform.md @@ -96,3 +96,17 @@ This roadmap is intentionally step-based and dependency-ordered. No timeline com 2. Deliver deterministic event inbox (polling canonical, push optional). 3. Gate event visibility by active membership status. 4. Track ack receipts with immutable event ids and dedupe keys. + +## Step 15: Ship Free Launcher Control Plane + +1. Release free launcher with local wallet setup and readiness checks. +2. Keep launcher useful without paid runtime activation. +3. Expose membership and governance state clearly in-app. +4. Ensure setup is resumable across sessions. + +## Step 16: Lock Governance Paid Install Path + +1. Governance is first paid license after membership activation. +2. Install requires signed package metadata and hash verification. +3. Activation requires active governance entitlement and matching policy hash. +4. Runtime blocks execution when membership/entitlement status is suspended, revoked, or unknown. diff --git a/docs/roadmap-status.md b/docs/roadmap-status.md index 891488c..fc86955 100644 --- a/docs/roadmap-status.md +++ b/docs/roadmap-status.md @@ -42,11 +42,14 @@ Implemented now: 15. Dedicated marketplace OpenAPI contract and examples. 16. Member app channel contract, examples, backend handoff checklist, and conformance vectors. 17. Download endpoints now validate wallet membership status before authorizing channel messaging. +18. Governance install API contract, examples, backend handoff checklist, and conformance vectors. +19. Repo boundary blueprint and free launcher specification aligned with first paid governance model. Remaining in this repo: 1. Wire live store checkout flow to production marketplace APIs when available. 2. Replace deployment templates with real contract addresses after chain deployment. +3. Add launcher/governance install UI that consumes governance installer APIs. Cross-repo dependencies (kernel/backend/contracts): @@ -55,3 +58,4 @@ Cross-repo dependencies (kernel/backend/contracts): 3. Implement checkout APIs and entitlement mint pipeline. 4. Implement runtime entitlement gate and evidence receipts. 5. Implement member app channel APIs and deterministic event stream storage. +6. Implement governance install token/confirm/status APIs and signed package delivery. diff --git a/docs/schemas/examples/launch-offers-catalog.v1.example.json b/docs/schemas/examples/launch-offers-catalog.v1.example.json index 3fb1870..79fdae5 100644 --- a/docs/schemas/examples/launch-offers-catalog.v1.example.json +++ b/docs/schemas/examples/launch-offers-catalog.v1.example.json @@ -2,6 +2,15 @@ "schema_version": "launch_offers_catalog.v1", "catalog_id": "launch-2026-operator", "offers": [ + { + "offer_id": "edut.governance.core", + "title": "EDUT Governance Core", + "summary": "First paid runtime license. Activates deterministic governance runtime.", + "price": "499.00", + "currency": "USDC", + "member_only": true, + "workspace_bound": false + }, { "offer_id": "edut.crm.pro.annual", "title": "EDUT CRM Pro", diff --git a/docs/secret-system-spec.md b/docs/secret-system-spec.md index 9905a82..a45a244 100644 --- a/docs/secret-system-spec.md +++ b/docs/secret-system-spec.md @@ -54,6 +54,7 @@ Post-mint success -> app download links (Desktop/iOS/Android) 2. Membership is not a product/module license. 3. Offer-specific licenses/entitlements are purchased separately. 4. Membership purchase delivers initial platform access (download entry point) immediately after activation. +5. Entitlement ownership wallet is the runtime authority; payment wallet may differ when authorized by ownership-wallet proof. ## Infrastructure diff --git a/docs/wallet-ownership-payment-model.md b/docs/wallet-ownership-payment-model.md new file mode 100644 index 0000000..c969c19 --- /dev/null +++ b/docs/wallet-ownership-payment-model.md @@ -0,0 +1,38 @@ +# Wallet Ownership and Payment Model + +This model separates ownership rights from payment source for deterministic entitlement control. + +## Roles + +1. Ownership wallet +- Holds membership and license entitlements. +- Determines activation rights for governance and modules. +- Used for runtime entitlement checks. + +2. Payment wallet +- Pays membership/license quote transactions. +- May differ from ownership wallet. +- Does not automatically gain activation rights. + +## Required Rule + +Entitlements are minted to `ownership_wallet` only. + +## Authorization Rule + +When payment wallet differs from ownership wallet, backend requires ownership-wallet authorization proof for quote/confirm binding. + +## Activation Rule + +Runtime activation checks ownership wallet entitlement state only. + +## Why + +1. Supports simple user funding options. +2. Keeps entitlement ownership deterministic and auditable. +3. Prevents accidental activation tied to transient funding wallets. + +## Non-Goals + +1. Treating payment wallet as ownership wallet by default. +2. Activating runtime from payment evidence without ownership entitlement binding. diff --git a/public/store/index.html b/public/store/index.html index c9c7c67..3792220 100644 --- a/public/store/index.html +++ b/public/store/index.html @@ -332,13 +332,13 @@ setCheckoutLog('Offer catalog loaded: ' + payload.offers.length + ' offers.'); } catch (err) { state.offers = [{ - offer_id: 'edut.crm.pro.annual', - title: 'EDUT CRM Pro (fallback)', - summary: 'Fallback offer loaded because catalog fetch failed.', - price: '199.00', + offer_id: 'edut.governance.core', + title: 'EDUT Governance Core (fallback)', + summary: 'Fallback governance offer loaded because catalog fetch failed.', + price: '499.00', currency: 'USDC', member_only: true, - workspace_bound: true, + workspace_bound: false, transferable: false, }]; state.selectedOfferId = state.offers[0].offer_id; diff --git a/public/store/offers.json b/public/store/offers.json index 11bfc2b..9396432 100644 --- a/public/store/offers.json +++ b/public/store/offers.json @@ -1,6 +1,16 @@ { "catalog_id": "launch-2026-operator", "offers": [ + { + "offer_id": "edut.governance.core", + "title": "EDUT Governance Core", + "summary": "First paid runtime license. Activates deterministic governance engine on entitled devices.", + "price": "499.00", + "currency": "USDC", + "member_only": true, + "workspace_bound": false, + "transferable": false + }, { "offer_id": "edut.crm.pro.annual", "title": "EDUT CRM Pro",