# EDUT Membership Platform Interfaces (v1) This document freezes interface targets for membership-gated commerce. ## Solidity Interfaces ```solidity interface IEdutMembership { event MembershipMinted(address indexed wallet, uint256 indexed tokenId, uint256 amountPaid, address currency); event MintPriceUpdated(address indexed currency, uint256 amountAtomic); event MembershipStatusUpdated(address indexed wallet, uint8 status); function mintMembership(address recipient) external payable returns (uint256 tokenId); function hasMembership(address wallet) external view returns (bool); function membershipStatus(address wallet) external view returns (uint8 status); function currentMintPrice() external view returns (address currency, uint256 amountAtomic); } interface IEdutOfferRegistry { event OfferUpserted(bytes32 indexed offerKey, bytes32 policyHash, address indexed issuer); event OfferStatusChanged(bytes32 indexed offerKey, uint8 status); function upsertOffer(bytes32 offerKey, bytes32 policyHash, bytes calldata encodedOffer) external; function setOfferStatus(bytes32 offerKey, uint8 status) external; function getOffer(bytes32 offerKey) external view returns (bytes memory encodedOffer); } interface IEdutEntitlement { event EntitlementMinted(bytes32 indexed entitlementId, bytes32 indexed offerKey, address indexed wallet); event EntitlementStateChanged(bytes32 indexed entitlementId, uint8 state); function mintEntitlement(bytes32 offerKey, address wallet, bytes32 policyHash) external returns (bytes32 entitlementId); function entitlementState(bytes32 entitlementId) external view returns (uint8 state); } interface IEdutSuiteEntitlement { event SuiteEntitlementBound(bytes32 indexed suiteEntitlementId, bytes32 indexed orgRootId, address indexed ownerWallet); event HumanAccessClassSet(bytes32 indexed orgRootId, bytes32 indexed principalId, uint8 accessClass); event HumanRoleSet(bytes32 indexed orgRootId, bytes32 indexed principalId, uint8 principalRole); event AvailabilityStateChanged(bytes32 indexed orgRootId, bytes32 indexed principalId, uint8 availabilityState); function bindSuiteEntitlement(bytes32 orgRootId, address ownerWallet, bytes32 policyHash) external returns (bytes32 suiteEntitlementId); function setHumanAccessClass(bytes32 orgRootId, bytes32 principalId, uint8 accessClass) external; function setHumanRole(bytes32 orgRootId, bytes32 principalId, uint8 principalRole) external; function availabilityState(bytes32 orgRootId, bytes32 principalId) external view returns (uint8 state); } ``` ## Status Enums ```text MembershipStatus: 0 = NONE 1 = ACTIVE 2 = SUSPENDED 3 = REVOKED OfferStatus: 0 = DRAFT 1 = ACTIVE 2 = PAUSED 3 = RETIRED EntitlementState: 0 = ACTIVE 1 = SUSPENDED 2 = REVOKED 3 = EXPIRED AccessClass: 0 = CONNECTED 1 = SOVEREIGN AvailabilityState: 0 = ACTIVE 1 = GRACE 2 = CONTINUITY 3 = PARKED PrincipalRole: 0 = WORKSPACE_MEMBER 1 = ORG_ROOT_OWNER ``` ## API Surface (Backend) ## Wallet + Membership 1. `POST /secret/wallet/intent` 2. `POST /secret/wallet/verify` 3. `POST /secret/wallet/session/refresh` 4. `POST /secret/wallet/session/revoke` 5. `POST /secret/membership/quote` 6. `POST /secret/membership/confirm` 7. `GET /secret/membership/status?designation_code=...` ## Marketplace 1. `GET /marketplace/offers` 2. `GET /marketplace/offers/{offer_id}` 3. `POST /marketplace/checkout/quote` 4. `POST /marketplace/checkout/confirm` 5. `GET /marketplace/entitlements` 6. `GET /marketplace/availability?org_root_id=...&principal_id=...` ## Governance Installer 1. `POST /governance/install/token` 2. `POST /governance/install/confirm` 3. `GET /governance/install/status` 4. `POST /governance/lease/heartbeat` 5. `POST /governance/lease/offline-renew` ## Issuer APIs 1. `POST /issuer/offers/upsert` 2. `POST /issuer/offers/{offer_id}/status` 3. `POST /issuer/manifests/upsert` ## Deterministic Gate Requirements 1. Every checkout quote must include: - `quote_id` - `wallet` (ownership wallet) - `payer_wallet` (optional) - `offer_id` - `currency` - `amount_atomic` - `policy_hash` - `expires_at` 2. Checkout confirm must fail closed if: - membership is not active, - suite boundary checks fail (`org_root_id` mismatch), - availability state is `PARKED`, - quote expired, - tx amount/currency mismatch, - policy hash mismatch. 3. Entitlement activation must fail closed when state is not `ACTIVE`. 4. Cross-boundary paid execution must fail closed unless target boundary has active suite entitlement. 5. `CONTINUITY` state must block growth actions (new member/workspace/install/worker spawn). 6. Admin operations (health/config/update/support ticket escalation) require `ORG_ROOT_OWNER` role. ## Evidence Requirements Each successful purchase must emit/record: 1. wallet 2. membership status snapshot 3. offer_id and policy_hash 4. quote_id 5. tx_hash and chain_id 6. entitlement_id 7. org_root_id 8. principal_id 9. access_class + availability_state snapshot 10. principal_role snapshot 11. receipt timestamp ## Compatibility Rule Interfaces can only evolve through additive changes in v1. Breaking changes require v2 namespace and migration plan.