web/docs/contracts/membership-platform-interfaces.md

162 lines
5.1 KiB
Markdown

# 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.