diff --git a/README.md b/README.md index 7cc32fe..b34dbc7 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ docs/ membership-pricing-policy.md membership-tier-extension.md wallet-ownership-payment-model.md + catalog-distribution-policy.md failure-state-matrix.md legal-copy-matrix.md localization-qa-matrix.md @@ -63,6 +64,7 @@ docs/ governance-install-vectors.md deployment/ README.md + public-surface-checklist.md chain-config.template.json contract-addresses.template.json environment-invariants.md diff --git a/docs/api/examples/marketplace.examples.md b/docs/api/examples/marketplace.examples.md index 9434f38..eb98416 100644 --- a/docs/api/examples/marketplace.examples.md +++ b/docs/api/examples/marketplace.examples.md @@ -51,9 +51,30 @@ Success (`200`): "payer_wallet": "0x2299547f6fA9A8f9b6d9aEA9F9D8A4B53C8A0e11", "offer_id": "edut.governance.core", "currency": "USDC", - "amount": "499.00", - "amount_atomic": "499000000", + "amount": "500.00", + "amount_atomic": "500000000", + "total_amount": "505.00", + "total_amount_atomic": "505000000", "decimals": 6, + "membership_activation_included": true, + "line_items": [ + { + "kind": "license", + "label": "Governance Core License", + "amount": "500.00", + "amount_atomic": "500000000", + "decimals": 6, + "currency": "USDC" + }, + { + "kind": "membership", + "label": "EDUT Membership Activation", + "amount": "5.00", + "amount_atomic": "5000000", + "decimals": 6, + "currency": "USDC" + } + ], "policy_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "expires_at": "2026-02-17T07:44:30Z", "tx": { @@ -64,6 +85,12 @@ Success (`200`): } ``` +### Notes + +1. `amount`/`amount_atomic` represent the license component. +2. `total_amount`/`total_amount_atomic` represent the actual payable quote total. +3. First checkout can include membership activation as a separate line item. + Error (`403`): ```json diff --git a/docs/api/marketplace.openapi.yaml b/docs/api/marketplace.openapi.yaml index 74c5909..6860b5b 100644 --- a/docs/api/marketplace.openapi.yaml +++ b/docs/api/marketplace.openapi.yaml @@ -5,10 +5,12 @@ info: description: Membership-gated offer and entitlement commerce endpoints. servers: - url: https://api.edut.ai +security: + - AppSession: [] paths: /marketplace/offers: get: - summary: List active offers + summary: List active offers (launcher/app surface) responses: '200': description: Offer list @@ -98,6 +100,11 @@ paths: items: $ref: '#/components/schemas/Entitlement' components: + securitySchemes: + AppSession: + type: http + scheme: bearer + bearerFormat: EDUT-APP-SESSION schemas: Offer: type: object @@ -156,9 +163,13 @@ components: ownership_proof: type: string description: Optional ownership-wallet signature proving entitlement recipient approval when payer differs. + include_membership_if_missing: + type: boolean + default: true + description: If true, quote may bundle first-time membership fee into total. CheckoutQuoteResponse: type: object - required: [quote_id, wallet, offer_id, currency, amount_atomic, policy_hash, expires_at] + required: [quote_id, wallet, offer_id, currency, amount_atomic, total_amount_atomic, policy_hash, expires_at] properties: quote_id: type: string @@ -174,8 +185,20 @@ components: type: string amount_atomic: type: string + description: License amount component only. + total_amount: + type: string + description: Total payable amount for this checkout quote. + total_amount_atomic: + type: string decimals: type: integer + membership_activation_included: + type: boolean + line_items: + type: array + items: + $ref: '#/components/schemas/QuoteLineItem' policy_hash: type: string expires_at: @@ -184,6 +207,23 @@ components: tx: type: object additionalProperties: true + QuoteLineItem: + type: object + required: [kind, amount_atomic, decimals, currency, label] + properties: + kind: + type: string + enum: [license, membership, network_estimate] + label: + type: string + amount: + type: string + amount_atomic: + type: string + decimals: + type: integer + currency: + type: string CheckoutConfirmRequest: type: object required: [quote_id, wallet, offer_id, tx_hash, chain_id] diff --git a/docs/catalog-distribution-policy.md b/docs/catalog-distribution-policy.md new file mode 100644 index 0000000..0c99f26 --- /dev/null +++ b/docs/catalog-distribution-policy.md @@ -0,0 +1,35 @@ +# Catalog Distribution Policy + +This policy keeps public web minimal while allowing full commerce inside the launcher app. + +## Public Web (edut.ai) + +1. Public web remains identity and access surface. +2. Public web does not serve production catalog details. +3. Public web does not execute production checkout. +4. Public web may host internal preview routes that are noindex and disabled by default. + +## Launcher App Surface + +1. Launcher app is the canonical catalog and checkout surface. +2. Launcher fetches signed catalog manifests from marketplace APIs. +3. Launcher verifies manifest signature and hash before display. +4. Launcher checkout requires wallet session, ownership binding, and entitlement gating. + +## Anti-Scraping Posture + +1. No public, anonymous catalog endpoint for production offers. +2. Offer manifests require app session and rate limits. +3. Manifest payloads are short-TTL and signed. +4. Checkout endpoints require nonce-bound quotes and ownership-proof rules. + +## Legal Clarity Rule + +1. If first checkout bundles membership activation, quote must show line-item breakdown. +2. Checkout totals must reconcile to line-item amounts deterministically. + +## Non-Goals + +1. Marketing the catalog directly on public website pages. +2. Relying on obscurity as sole protection. +3. Activating runtime rights from unsigned catalog/quote data. diff --git a/docs/conformance/membership-gating-vectors.md b/docs/conformance/membership-gating-vectors.md index 7ce7c42..26de237 100644 --- a/docs/conformance/membership-gating-vectors.md +++ b/docs/conformance/membership-gating-vectors.md @@ -112,6 +112,22 @@ This document defines deterministic pass/fail vectors for membership-gated comme - When checkout quote is requested - Then quote is denied +## Vector Group G: Bundled First Checkout Transparency + +1. G1 `quote_bundle_membership_when_missing` +- Given active ownership wallet without membership and `include_membership_if_missing=true` +- When governance checkout quote is requested +- Then quote includes membership line item and `membership_activation_included=true` + +2. G2 `quote_excludes_membership_when_active` +- Given wallet with active membership +- When governance checkout quote is requested +- Then quote excludes membership line item and `membership_activation_included=false` + +3. G3 `quote_total_matches_line_items` +- Given any quote response with line items +- Then `total_amount_atomic` equals sum of line item `amount_atomic` values (excluding network_estimate) + ## Vector Group E: Evidence Integrity 1. E1 `receipt_fields_complete` diff --git a/docs/deployment/public-surface-checklist.md b/docs/deployment/public-surface-checklist.md new file mode 100644 index 0000000..a510bf3 --- /dev/null +++ b/docs/deployment/public-surface-checklist.md @@ -0,0 +1,30 @@ +# Public Surface Deployment Checklist + +This checklist prevents accidental public exposure of app-only commerce surfaces. + +## Required Production Settings + +1. `edut.ai` serves landing + legal + trust pages only. +2. `/store` route disabled or restricted for production public domain. +3. `/store/offers.json` not publicly served in production. +4. Marketplace APIs enforce app/session authentication. +5. Robots headers enforce noindex for any preview-only routes. + +## Header and Caching Controls + +1. Preview routes return `X-Robots-Tag: noindex, nofollow, noarchive, nosnippet`. +2. Catalog manifests use short cache TTL. +3. Quote responses disable shared cache and include anti-replay headers. + +## Verification Steps + +1. Run anonymous request to `/store` and confirm checkout is disabled. +2. Run anonymous request to `/store/offers.json` and confirm blocked/unavailable. +3. Confirm launcher-authenticated session can fetch catalog. +4. Confirm public web page has no links to active checkout surface. + +## Release Blockers + +1. Any production route exposes active catalog without app/session auth. +2. Any production route allows quote creation anonymously. +3. Any production route indexes preview checkout content. diff --git a/docs/handoff/marketplace-backend-checklist.md b/docs/handoff/marketplace-backend-checklist.md index 01ad8f9..59e0ded 100644 --- a/docs/handoff/marketplace-backend-checklist.md +++ b/docs/handoff/marketplace-backend-checklist.md @@ -10,6 +10,8 @@ This checklist maps store behavior to required marketplace backend implementatio 4. `POST /marketplace/checkout/confirm` 5. `GET /marketplace/entitlements?wallet=...` +All marketplace endpoints require authenticated app/session context. + ## Required Gate Behavior 1. Quote endpoint must deny checkout when membership is not active. @@ -32,9 +34,12 @@ This checklist maps store behavior to required marketplace backend implementatio 4. `offer_id` 5. `currency` 6. `amount` or `amount_atomic + decimals` -7. `policy_hash` -8. `expires_at` -9. `tx` execution object or equivalent fields +7. `total_amount` or `total_amount_atomic + decimals` +8. `membership_activation_included` +9. `line_items` with transparent breakdown (license + optional membership) +10. `policy_hash` +11. `expires_at` +12. `tx` execution object or equivalent fields ## Confirm Response Requirements @@ -60,6 +65,7 @@ This checklist maps store behavior to required marketplace backend implementatio 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. +6. Bundled membership component must be explicit in quote line items when included. ## Done Criteria diff --git a/docs/implementation-mapping.md b/docs/implementation-mapping.md index f9e2811..d105a0b 100644 --- a/docs/implementation-mapping.md +++ b/docs/implementation-mapping.md @@ -13,6 +13,7 @@ 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. +6. Marketplace catalog/checkout auth gates so production commerce is app-session scoped. ## Runtime/Kernel Responsibilities diff --git a/docs/legal-copy-matrix.md b/docs/legal-copy-matrix.md index 4906146..05f96b7 100644 --- a/docs/legal-copy-matrix.md +++ b/docs/legal-copy-matrix.md @@ -15,3 +15,4 @@ This matrix prevents drift between public surfaces and legal posture. 1. Membership language must always distinguish access rights from license rights. 2. Any copy introducing financial upside claims is blocked. 3. Any change to legal-critical copy requires review against this matrix. +4. First checkout totals must disclose line-item composition when membership activation is bundled. diff --git a/docs/release-gate.md b/docs/release-gate.md index 1aa915b..d10dedf 100644 --- a/docs/release-gate.md +++ b/docs/release-gate.md @@ -24,6 +24,8 @@ This gate controls deploy/no-deploy decisions for membership-gated commerce chan 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. +13. Bundled membership line-item disclosure is present on first checkout quotes. +14. Public web deployment blocks anonymous production catalog and quote endpoints. ## No-Deploy Triggers @@ -34,6 +36,8 @@ This gate controls deploy/no-deploy decisions for membership-gated commerce chan 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. +8. Any checkout quote total that cannot be reconciled to disclosed line items. +9. Any production public route exposing active catalog/checkout without app session auth. ## Evidence Bundle Required for Release diff --git a/docs/roadmap-membership-platform.md b/docs/roadmap-membership-platform.md index 5159579..65508b5 100644 --- a/docs/roadmap-membership-platform.md +++ b/docs/roadmap-membership-platform.md @@ -110,3 +110,10 @@ This roadmap is intentionally step-based and dependency-ordered. No timeline com 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. + +## Step 17: Enforce Launcher-Only Commerce Surface + +1. Public website remains identity/legal/trust surface. +2. Production catalog and checkout require app-session auth. +3. Public preview routes are disabled by default and noindexed. +4. Release gate blocks deploys that expose anonymous production catalog access. diff --git a/docs/roadmap-status.md b/docs/roadmap-status.md index 44ab464..1a59ebb 100644 --- a/docs/roadmap-status.md +++ b/docs/roadmap-status.md @@ -45,6 +45,8 @@ Implemented now: 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. 20. Store UI now supports distinct payer wallet overrides with ownership-proof signing before quote requests. +21. Public web store preview is noindex and disabled by default unless explicit internal preview mode is enabled. +22. Catalog distribution and public-surface deployment guardrails are documented for launcher-only commerce. Remaining in this repo: diff --git a/docs/vision.md b/docs/vision.md index 3f43b87..c9f12b3 100644 --- a/docs/vision.md +++ b/docs/vision.md @@ -52,6 +52,7 @@ The flow should feel controlled and ambient, not like a conventional signup form - `edut.dev`: developer-facing domain (same landing for now). - `api.edut.ai`: API endpoints for wallet intent/verify and membership quote/confirm. - `/privacy` and `/terms`: legal pages (English authoritative). +- Production catalog and checkout surfaces are launcher-app channels, not public web pages. ## Messaging Boundaries diff --git a/public/store/index.html b/public/store/index.html index bac908e..b6da34c 100644 --- a/public/store/index.html +++ b/public/store/index.html @@ -6,6 +6,7 @@ EDUT Store Preview +