160 lines
5.1 KiB
Markdown
160 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/membership/quote`
|
|
4. `POST /secret/membership/confirm`
|
|
5. `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.
|