web/docs/secret-system-spec.md

10 KiB

Edut Secret System - Wallet-First Designation + Membership Spec

Overview

The Edut onboarding flow is deterministic and wallet-first:

  1. Visitor requests designation intent from edut.ai.
  2. Server issues one-time typed-data payload (nonce, deadline, price, currency).
  3. Visitor signs intent with wallet (identity proof, no value transfer).
  4. Server verifies signature and creates/updates designation record.
  5. Visitor mints paid EDUT membership on-chain (intent proof).
  6. Server confirms transaction and marks membership active.
  7. Visitor downloads the EDUT platform app from post-mint success links.

This flow is the pre-launch identity and commerce envelope. It is not a throwaway waitlist.

User Experience Sequence (Continue Flow)

  1. Initial page state: orb, identity text, footer links.
  2. First click anywhere: globe spin intensifies, continue appears.
  3. Click continue: wallet explainer appears.
  4. User selects I have a wallet or I need a wallet.
  5. I need a wallet shows install guidance and remains in-page.
  6. I have a wallet triggers wallet connection request.
  7. Page calls POST /secret/wallet/intent.
  8. Wallet signs EIP-712 typed intent.
  9. Page calls POST /secret/wallet/verify.
  10. Page requests membership quote via POST /secret/membership/quote.
  11. Wallet submits membership mint transaction on Base.
  12. Page confirms via POST /secret/membership/confirm and/or status poll.
  13. UI shows acknowledged · {token} when membership is active.
  14. Post-mint success state presents download your platform links (Desktop/iOS/Android).
  15. Download endpoints perform wallet membership status checks before channel authorization messaging.
  16. Member opens the app, signs in with the same wallet, and receives platform updates through app notifications.

Privacy and Terms links bypass flow and navigate normally.

Architecture

Landing page -> POST /secret/wallet/intent
Wallet signs typed intent (EIP-712)
Landing page -> POST /secret/wallet/verify
Landing page -> POST /secret/membership/quote
Wallet sends paid mint tx on Base
Landing page -> POST /secret/membership/confirm
Membership active -> acknowledged state
Post-mint success -> app download links (Desktop/iOS/Android)

Core Commerce Rule

  1. Membership is required to purchase marketplace offers.
  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

Service Domain / Endpoint Purpose
Landing UI edut.ai, edut.dev Continue flow + wallet intent/signature + membership mint UX
API api.edut.ai/secret/wallet/intent Create one-time designation intent
API api.edut.ai/secret/wallet/verify Verify signature and bind wallet identity
API api.edut.ai/secret/wallet/session/refresh Rotate wallet session token
API api.edut.ai/secret/wallet/session/revoke Revoke wallet session token
API api.edut.ai/secret/membership/quote Return current payable membership quote
API api.edut.ai/secret/membership/confirm Confirm membership tx and activation state
Chain Base Membership mint settlement and evidence
Database /var/lib/edut/secrets.db Durable designation + membership state

Deterministic State Machine

pending_signature -> signature_verified -> pending_membership_mint -> membership_active

Additional side states:

  • intent_expired
  • quote_expired
  • tx_unconfirmed
  • rejected (invalid signature, wrong chain, mismatched wallet)
  • rate_limited

Rules:

  1. No backwards transition except administrative recovery event with audit entry.
  2. membership_active requires successful on-chain payment confirmation.
  3. Signature and quote nonces are single-use; replay attempts are rejected.
  4. Acknowledged UI state requires membership_active.

API Contracts

1) Wallet Intent

POST /secret/wallet/intent

Request JSON:

{
  "address": "0xabc123...",
  "origin": "https://edut.ai",
  "locale": "en",
  "chain_id": 8453
}

Behavior:

  1. Normalize and validate wallet address format.
  2. Validate origin against allowlist.
  3. Enforce rate limits (IP + address + rolling windows).
  4. Generate designation code, auth_token, nonce, and intent TTL.
  5. Persist pending_signature state.
  6. Return typed-data envelope fields required for signing.

Response:

{
  "intent_id": "wi_...",
  "designation_code": "0217073045482",
  "display_token": "0217-0730-4548-2",
  "nonce": "f2e9...",
  "issued_at": "2026-02-17T07:30:45Z",
  "expires_at": "2026-02-17T07:40:45Z",
  "domain_name": "EDUT Designation",
  "chain_id": 8453,
  "verifying_contract": "0x0000000000000000000000000000000000000000"
}

2) Wallet Verify

POST /secret/wallet/verify

Request JSON:

{
  "intent_id": "wi_...",
  "address": "0xabc123...",
  "chain_id": 8453,
  "signature": "0x..."
}

Behavior:

  1. Load pending intent by intent_id.
  2. Verify not expired and not consumed.
  3. Reconstruct typed payload exactly as issued.
  4. Recover signer and compare to declared address.
  5. Validate chain allowlist and origin.
  6. Transition to signature_verified and pending_membership_mint.

Response:

{
  "status": "signature_verified",
  "designation_code": "0217073045482",
  "display_token": "0217-0730-4548-2",
  "verified_at": "2026-02-17T07:31:12Z",
  "session_token": "9f2c50f8a0f5d8d0b0efc4fa665e4032f31bb0c4c4f31b8c",
  "session_expires_at": "2026-03-18T07:31:12Z"
}

3) Wallet Session Lifecycle

POST /secret/wallet/session/refresh

Request JSON:

{
  "wallet": "0xabc123..."
}

Requirements:

  1. Valid wallet session token via Authorization: Bearer <token> or X-Edut-Session.
  2. Session wallet must match request wallet.

Behavior:

  1. Validate current token state (not expired/revoked, chain matches).
  2. Revoke the presented token.
  3. Issue a replacement token with fresh expiry.

Response:

{
  "status": "session_refreshed",
  "wallet": "0xabc123...",
  "session_token": "f9bc20f15ecf7fd53f1f4ba8ca774564a1098e6ed9db6f0f",
  "session_expires_at": "2026-03-18T07:42:10Z"
}

POST /secret/wallet/session/revoke

Request JSON:

{
  "wallet": "0xabc123..."
}

Requirements:

  1. Valid wallet session token via Authorization: Bearer <token> or X-Edut-Session.
  2. Session wallet must match request wallet.

Behavior:

  1. Validate current token state.
  2. Mark session as revoked immediately.

Response:

{
  "status": "session_revoked",
  "wallet": "0xabc123...",
  "revoked_at": "2026-02-17T07:34:02Z"
}

4) Membership Quote

POST /secret/membership/quote

Request JSON:

{
  "designation_code": "0217073045482",
  "address": "0xabc123...",
  "chain_id": 8453
}

Behavior:

  1. Verify signature_verified status for designation/address pair.
  2. Fetch current policy (currency, amount, deadline, contract).
  3. Return quote payload for client-side transaction submission.

Response:

{
  "quote_id": "mq_...",
  "chain_id": 8453,
  "currency": "USDC",
  "amount": "100.00",
  "amount_atomic": "100000000",
  "deadline": "2026-02-17T07:36:12Z",
  "contract_address": "0x...",
  "method": "mintMembership",
  "calldata": "0x..."
}

5) Membership Confirm

POST /secret/membership/confirm

Request JSON:

{
  "designation_code": "0217073045482",
  "quote_id": "mq_...",
  "tx_hash": "0x...",
  "address": "0xabc123...",
  "chain_id": 8453
}

Behavior:

  1. Validate quote ownership and expiry.
  2. Verify tx inclusion and success on allowed chain.
  3. Validate minted membership recipient and amount policy.
  4. Transition to membership_active.
  5. Emit activation evidence receipt.

Response:

{
  "status": "membership_active",
  "designation_code": "0217073045482",
  "display_token": "0217-0730-4548-2",
  "tx_hash": "0x...",
  "activated_at": "2026-02-17T07:33:09Z"
}

Security Controls

  1. Intent TTL and one-time nonce consumption.
  2. Quote TTL with explicit deadline.
  3. Strict origin allowlist for intent and verify endpoints.
  4. Chain allowlist enforcement.
  5. Signature and quote replay prevention.
  6. IP + address rate limits on all public endpoints.
  7. Deterministic audit trail for signature and payment confirmation.
  8. No private key handling server-side.

Data Model (SQLite)

File: /var/lib/edut/secrets.db

CREATE TABLE IF NOT EXISTS designations (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    code TEXT NOT NULL UNIQUE,
    auth_token TEXT NOT NULL,
    status TEXT NOT NULL DEFAULT 'pending_signature',
    wallet_address TEXT,
    chain_id INTEGER,
    intent_id TEXT UNIQUE,
    intent_nonce TEXT,
    intent_issued_at DATETIME,
    intent_expires_at DATETIME,
    signature TEXT,
    signature_verified_at DATETIME,
    membership_quote_id TEXT,
    membership_currency TEXT,
    membership_amount_atomic TEXT,
    membership_quote_expires_at DATETIME,
    membership_tx_hash TEXT,
    membership_activated_at DATETIME,
    origin TEXT,
    locale TEXT,
    created_at DATETIME DEFAULT (datetime('now'))
);

CREATE INDEX idx_designations_code ON designations(code);
CREATE INDEX idx_designations_wallet ON designations(wallet_address);
CREATE INDEX idx_designations_status ON designations(status);
CREATE INDEX idx_designations_intent ON designations(intent_id);
CREATE INDEX idx_designations_quote ON designations(membership_quote_id);
CREATE INDEX idx_designations_created ON designations(created_at);

Launch-Day Activation Messaging

At launch, membership_active records are eligible for access-level updates and marketplace onboarding.

NGINX Routing (Example)

location /secret/wallet/intent {
    proxy_pass http://127.0.0.1:9091;
}

location /secret/wallet/verify {
    proxy_pass http://127.0.0.1:9091;
}

location /secret/membership/quote {
    proxy_pass http://127.0.0.1:9091;
}

location /secret/membership/confirm {
    proxy_pass http://127.0.0.1:9091;
}

Summary

The wallet-first designation plus paid membership flow creates a deterministic two-factor identity and commitment chain:

  1. signature proves wallet control,
  2. paid mint proves intent,
  3. membership gates all future marketplace purchases.