Lock boundary availability and owner-admin entitlement model
This commit is contained in:
parent
a97fb275db
commit
bfc374b9ce
@ -35,6 +35,7 @@ docs/
|
|||||||
roadmap-status.md
|
roadmap-status.md
|
||||||
membership-pricing-policy.md
|
membership-pricing-policy.md
|
||||||
membership-tier-extension.md
|
membership-tier-extension.md
|
||||||
|
availability-boundary-model.md
|
||||||
wallet-ownership-payment-model.md
|
wallet-ownership-payment-model.md
|
||||||
catalog-distribution-policy.md
|
catalog-distribution-policy.md
|
||||||
failure-state-matrix.md
|
failure-state-matrix.md
|
||||||
@ -63,6 +64,7 @@ docs/
|
|||||||
membership-gating-vectors.md
|
membership-gating-vectors.md
|
||||||
member-channel-vectors.md
|
member-channel-vectors.md
|
||||||
governance-install-vectors.md
|
governance-install-vectors.md
|
||||||
|
availability-boundary-vectors.md
|
||||||
deployment/
|
deployment/
|
||||||
README.md
|
README.md
|
||||||
public-surface-checklist.md
|
public-surface-checklist.md
|
||||||
|
|||||||
@ -11,6 +11,9 @@ Content-Type: application/json
|
|||||||
|
|
||||||
{
|
{
|
||||||
"wallet": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
|
"wallet": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
|
||||||
|
"org_root_id": "org.acme.root",
|
||||||
|
"principal_id": "human.joshua",
|
||||||
|
"principal_role": "org_root_owner",
|
||||||
"device_id": "desktop-7f6f3a9b",
|
"device_id": "desktop-7f6f3a9b",
|
||||||
"launcher_version": "0.2.0",
|
"launcher_version": "0.2.0",
|
||||||
"platform": "macos",
|
"platform": "macos",
|
||||||
@ -86,8 +89,13 @@ Authorization: Bearer <wallet-session>
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"wallet": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
|
"wallet": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
|
||||||
|
"org_root_id": "org.acme.root",
|
||||||
|
"principal_id": "human.joshua",
|
||||||
|
"principal_role": "org_root_owner",
|
||||||
"membership_status": "active",
|
"membership_status": "active",
|
||||||
"entitlement_status": "active",
|
"entitlement_status": "active",
|
||||||
|
"access_class": "connected",
|
||||||
|
"availability_state": "active",
|
||||||
"activation_status": "active",
|
"activation_status": "active",
|
||||||
"latest_runtime_version": "1.0.0",
|
"latest_runtime_version": "1.0.0",
|
||||||
"policy_hash": "sha256:f10419ac..."
|
"policy_hash": "sha256:f10419ac..."
|
||||||
@ -103,3 +111,52 @@ Authorization: Bearer <wallet-session>
|
|||||||
"correlation_id": "req_01J9B6BJBVKY3N6WQ7TQM2R2P5"
|
"correlation_id": "req_01J9B6BJBVKY3N6WQ7TQM2R2P5"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## `POST /governance/lease/heartbeat`
|
||||||
|
|
||||||
|
Request:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"wallet": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
|
||||||
|
"org_root_id": "org.acme.root",
|
||||||
|
"principal_id": "human.joshua",
|
||||||
|
"device_id": "desktop-7f6f3a9b"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Success (`200`):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "lease_refreshed",
|
||||||
|
"availability_state": "active",
|
||||||
|
"lease_expires_at": "2026-03-19T01:05:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## `POST /governance/lease/offline-renew`
|
||||||
|
|
||||||
|
Request:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"wallet": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
|
||||||
|
"org_root_id": "org.acme.root",
|
||||||
|
"principal_id": "human.joshua",
|
||||||
|
"renewal_bundle": {
|
||||||
|
"bundle_id": "rb_01J9B6D4R0E4W8N6H2A1Q9V7PT",
|
||||||
|
"signed_payload": "base64:ZXhhbXBsZQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Success (`200`):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "renewal_applied",
|
||||||
|
"availability_state": "active",
|
||||||
|
"renewed_until": "2027-02-18T00:00:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@ -22,7 +22,9 @@ Success (`200`):
|
|||||||
"policies": {
|
"policies": {
|
||||||
"member_only": true,
|
"member_only": true,
|
||||||
"workspace_bound": true,
|
"workspace_bound": true,
|
||||||
"transferable": false
|
"transferable": false,
|
||||||
|
"internal_use_only": true,
|
||||||
|
"multi_tenant": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -38,6 +40,10 @@ Request:
|
|||||||
"wallet": "0x3ea6cbf98d23e2cf7b6f4f9bb1fb4f50b710f2d5",
|
"wallet": "0x3ea6cbf98d23e2cf7b6f4f9bb1fb4f50b710f2d5",
|
||||||
"payer_wallet": "0x2299547f6fA9A8f9b6d9aEA9F9D8A4B53C8A0e11",
|
"payer_wallet": "0x2299547f6fA9A8f9b6d9aEA9F9D8A4B53C8A0e11",
|
||||||
"offer_id": "edut.governance.core",
|
"offer_id": "edut.governance.core",
|
||||||
|
"org_root_id": "org.acme.root",
|
||||||
|
"principal_id": "human.joshua",
|
||||||
|
"principal_role": "org_root_owner",
|
||||||
|
"workspace_id": "workspace.work.acme.exec",
|
||||||
"ownership_proof": "0x9f20..."
|
"ownership_proof": "0x9f20..."
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -50,6 +56,9 @@ Success (`200`):
|
|||||||
"wallet": "0x3ea6cbf98d23e2cf7b6f4f9bb1fb4f50b710f2d5",
|
"wallet": "0x3ea6cbf98d23e2cf7b6f4f9bb1fb4f50b710f2d5",
|
||||||
"payer_wallet": "0x2299547f6fA9A8f9b6d9aEA9F9D8A4B53C8A0e11",
|
"payer_wallet": "0x2299547f6fA9A8f9b6d9aEA9F9D8A4B53C8A0e11",
|
||||||
"offer_id": "edut.governance.core",
|
"offer_id": "edut.governance.core",
|
||||||
|
"org_root_id": "org.acme.root",
|
||||||
|
"principal_id": "human.joshua",
|
||||||
|
"principal_role": "org_root_owner",
|
||||||
"currency": "USDC",
|
"currency": "USDC",
|
||||||
"amount": "500.00",
|
"amount": "500.00",
|
||||||
"amount_atomic": "500000000",
|
"amount_atomic": "500000000",
|
||||||
@ -76,6 +85,8 @@ Success (`200`):
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"policy_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
"policy_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
|
"access_class": "connected",
|
||||||
|
"availability_state": "active",
|
||||||
"expires_at": "2026-02-17T07:44:30Z",
|
"expires_at": "2026-02-17T07:44:30Z",
|
||||||
"tx": {
|
"tx": {
|
||||||
"to": "0x2222222222222222222222222222222222222222",
|
"to": "0x2222222222222222222222222222222222222222",
|
||||||
@ -110,6 +121,10 @@ Request:
|
|||||||
"wallet": "0x3ea6cbf98d23e2cf7b6f4f9bb1fb4f50b710f2d5",
|
"wallet": "0x3ea6cbf98d23e2cf7b6f4f9bb1fb4f50b710f2d5",
|
||||||
"payer_wallet": "0x2299547f6fA9A8f9b6d9aEA9F9D8A4B53C8A0e11",
|
"payer_wallet": "0x2299547f6fA9A8f9b6d9aEA9F9D8A4B53C8A0e11",
|
||||||
"offer_id": "edut.governance.core",
|
"offer_id": "edut.governance.core",
|
||||||
|
"org_root_id": "org.acme.root",
|
||||||
|
"principal_id": "human.joshua",
|
||||||
|
"principal_role": "org_root_owner",
|
||||||
|
"workspace_id": "workspace.work.acme.exec",
|
||||||
"tx_hash": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
"tx_hash": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
||||||
"chain_id": 8453
|
"chain_id": 8453
|
||||||
}
|
}
|
||||||
@ -122,9 +137,14 @@ Success (`200`):
|
|||||||
"status": "entitlement_active",
|
"status": "entitlement_active",
|
||||||
"entitlement_id": "ent:8453:0x3ea6cbf98d23e2cf7b6f4f9bb1fb4f50b710f2d5:000001",
|
"entitlement_id": "ent:8453:0x3ea6cbf98d23e2cf7b6f4f9bb1fb4f50b710f2d5:000001",
|
||||||
"offer_id": "edut.governance.core",
|
"offer_id": "edut.governance.core",
|
||||||
|
"org_root_id": "org.acme.root",
|
||||||
|
"principal_id": "human.joshua",
|
||||||
|
"principal_role": "org_root_owner",
|
||||||
"wallet": "0x3ea6cbf98d23e2cf7b6f4f9bb1fb4f50b710f2d5",
|
"wallet": "0x3ea6cbf98d23e2cf7b6f4f9bb1fb4f50b710f2d5",
|
||||||
"tx_hash": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
"tx_hash": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
||||||
"policy_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
"policy_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
|
"access_class": "connected",
|
||||||
|
"availability_state": "active",
|
||||||
"activated_at": "2026-02-17T07:46:02Z"
|
"activated_at": "2026-02-17T07:46:02Z"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -141,7 +161,10 @@ Success (`200`):
|
|||||||
"offer_id": "edut.crm.pro.annual",
|
"offer_id": "edut.crm.pro.annual",
|
||||||
"wallet_address": "0x3ea6cbf98d23e2cf7b6f4f9bb1fb4f50b710f2d5",
|
"wallet_address": "0x3ea6cbf98d23e2cf7b6f4f9bb1fb4f50b710f2d5",
|
||||||
"workspace_id": "workspace.work.acme",
|
"workspace_id": "workspace.work.acme",
|
||||||
|
"org_root_id": "org.acme.root",
|
||||||
"state": "active",
|
"state": "active",
|
||||||
|
"access_class": "connected",
|
||||||
|
"availability_state": "grace",
|
||||||
"policy_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
"policy_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
"issued_at": "2026-02-17T07:46:02Z"
|
"issued_at": "2026-02-17T07:46:02Z"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,9 @@ Content-Type: application/json
|
|||||||
"chain_id": 8453,
|
"chain_id": 8453,
|
||||||
"device_id": "desktop-7f6f3a9b",
|
"device_id": "desktop-7f6f3a9b",
|
||||||
"platform": "desktop",
|
"platform": "desktop",
|
||||||
|
"org_root_id": "org.acme.root",
|
||||||
|
"principal_id": "human.joshua",
|
||||||
|
"principal_role": "org_root_owner",
|
||||||
"app_version": "0.1.0",
|
"app_version": "0.1.0",
|
||||||
"push_provider": "none"
|
"push_provider": "none"
|
||||||
}
|
}
|
||||||
@ -45,6 +48,8 @@ Authorization: Bearer <wallet-session>
|
|||||||
{
|
{
|
||||||
"wallet": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
|
"wallet": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
|
||||||
"device_id": "desktop-7f6f3a9b",
|
"device_id": "desktop-7f6f3a9b",
|
||||||
|
"org_root_id": "org.acme.root",
|
||||||
|
"principal_id": "human.joshua",
|
||||||
"events": [
|
"events": [
|
||||||
{
|
{
|
||||||
"event_id": "evt_1031",
|
"event_id": "evt_1031",
|
||||||
@ -55,6 +60,7 @@ Authorization: Bearer <wallet-session>
|
|||||||
"dedupe_key": "platform_update:0.1.1",
|
"dedupe_key": "platform_update:0.1.1",
|
||||||
"requires_ack": true,
|
"requires_ack": true,
|
||||||
"policy_hash": "sha256:8b903f0d3a...",
|
"policy_hash": "sha256:8b903f0d3a...",
|
||||||
|
"visibility_scope": "member",
|
||||||
"payload": {
|
"payload": {
|
||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
"channel": "stable"
|
"channel": "stable"
|
||||||
@ -101,3 +107,41 @@ Content-Type: application/json
|
|||||||
"correlation_id": "req_01J9A4Q9GPDXDNZEWJ2FJS6F5R"
|
"correlation_id": "req_01J9A4Q9GPDXDNZEWJ2FJS6F5R"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Owner Support Ticket
|
||||||
|
|
||||||
|
### Request
|
||||||
|
|
||||||
|
```http
|
||||||
|
POST /member/channel/support/ticket
|
||||||
|
Authorization: Bearer <wallet-session>
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"wallet": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
|
||||||
|
"org_root_id": "org.acme.root",
|
||||||
|
"principal_id": "human.joshua",
|
||||||
|
"category": "health_diagnostic",
|
||||||
|
"summary": "Availability state has remained in continuity for 26 hours."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Response
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "accepted",
|
||||||
|
"ticket_id": "st_01J9A6X5VPE31MBBN9Y2BRS5A0",
|
||||||
|
"created_at": "2026-02-17T20:45:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Member Admin Attempt Error
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": "contact_your_org_admin",
|
||||||
|
"code": "owner_role_required",
|
||||||
|
"correlation_id": "req_01J9A6ZC0SYF5A0M8AP8BNX7B2"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@ -77,6 +77,52 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/InstallStatusResponse'
|
$ref: '#/components/schemas/InstallStatusResponse'
|
||||||
|
/governance/lease/heartbeat:
|
||||||
|
post:
|
||||||
|
summary: Refresh connected-class availability lease for org boundary.
|
||||||
|
operationId: refreshGovernanceLeaseHeartbeat
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/LeaseHeartbeatRequest'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Lease refreshed.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/LeaseHeartbeatResponse'
|
||||||
|
'403':
|
||||||
|
description: Boundary or entitlement invalid.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ErrorResponse'
|
||||||
|
/governance/lease/offline-renew:
|
||||||
|
post:
|
||||||
|
summary: Apply signed offline renewal package for sovereign class.
|
||||||
|
operationId: applyOfflineRenewalPackage
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/OfflineRenewRequest'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Offline renewal accepted.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/OfflineRenewResponse'
|
||||||
|
'409':
|
||||||
|
description: Renewal package invalid or stale.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ErrorResponse'
|
||||||
components:
|
components:
|
||||||
securitySchemes:
|
securitySchemes:
|
||||||
WalletSession:
|
WalletSession:
|
||||||
@ -94,6 +140,13 @@ components:
|
|||||||
properties:
|
properties:
|
||||||
wallet:
|
wallet:
|
||||||
type: string
|
type: string
|
||||||
|
org_root_id:
|
||||||
|
type: string
|
||||||
|
principal_id:
|
||||||
|
type: string
|
||||||
|
principal_role:
|
||||||
|
type: string
|
||||||
|
enum: [workspace_member, org_root_owner]
|
||||||
device_id:
|
device_id:
|
||||||
type: string
|
type: string
|
||||||
launcher_version:
|
launcher_version:
|
||||||
@ -212,12 +265,25 @@ components:
|
|||||||
properties:
|
properties:
|
||||||
wallet:
|
wallet:
|
||||||
type: string
|
type: string
|
||||||
|
org_root_id:
|
||||||
|
type: string
|
||||||
|
principal_id:
|
||||||
|
type: string
|
||||||
|
principal_role:
|
||||||
|
type: string
|
||||||
|
enum: [workspace_member, org_root_owner]
|
||||||
membership_status:
|
membership_status:
|
||||||
type: string
|
type: string
|
||||||
enum: [active, none, suspended, revoked, unknown]
|
enum: [active, none, suspended, revoked, unknown]
|
||||||
entitlement_status:
|
entitlement_status:
|
||||||
type: string
|
type: string
|
||||||
enum: [active, none, suspended, revoked, unknown]
|
enum: [active, none, suspended, revoked, unknown]
|
||||||
|
access_class:
|
||||||
|
type: string
|
||||||
|
enum: [connected, sovereign, unknown]
|
||||||
|
availability_state:
|
||||||
|
type: string
|
||||||
|
enum: [active, grace, continuity, parked, unknown]
|
||||||
activation_status:
|
activation_status:
|
||||||
type: string
|
type: string
|
||||||
enum: [not_installed, pending, active, blocked]
|
enum: [not_installed, pending, active, blocked]
|
||||||
@ -227,6 +293,71 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
reason:
|
reason:
|
||||||
type: string
|
type: string
|
||||||
|
LeaseHeartbeatRequest:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- wallet
|
||||||
|
- org_root_id
|
||||||
|
- principal_id
|
||||||
|
- device_id
|
||||||
|
properties:
|
||||||
|
wallet:
|
||||||
|
type: string
|
||||||
|
org_root_id:
|
||||||
|
type: string
|
||||||
|
principal_id:
|
||||||
|
type: string
|
||||||
|
device_id:
|
||||||
|
type: string
|
||||||
|
LeaseHeartbeatResponse:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- status
|
||||||
|
- availability_state
|
||||||
|
- lease_expires_at
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
enum: [lease_refreshed]
|
||||||
|
availability_state:
|
||||||
|
type: string
|
||||||
|
enum: [active, grace, continuity, parked]
|
||||||
|
lease_expires_at:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
OfflineRenewRequest:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- wallet
|
||||||
|
- org_root_id
|
||||||
|
- principal_id
|
||||||
|
- renewal_bundle
|
||||||
|
properties:
|
||||||
|
wallet:
|
||||||
|
type: string
|
||||||
|
org_root_id:
|
||||||
|
type: string
|
||||||
|
principal_id:
|
||||||
|
type: string
|
||||||
|
renewal_bundle:
|
||||||
|
type: object
|
||||||
|
additionalProperties: true
|
||||||
|
OfflineRenewResponse:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- status
|
||||||
|
- availability_state
|
||||||
|
- renewed_until
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
enum: [renewal_applied]
|
||||||
|
availability_state:
|
||||||
|
type: string
|
||||||
|
enum: [active, grace, continuity, parked]
|
||||||
|
renewed_until:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
ErrorResponse:
|
ErrorResponse:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
|
|||||||
@ -134,16 +134,20 @@ components:
|
|||||||
type: integer
|
type: integer
|
||||||
chain_id:
|
chain_id:
|
||||||
type: integer
|
type: integer
|
||||||
policies:
|
policies:
|
||||||
type: object
|
type: object
|
||||||
required: [member_only, workspace_bound, transferable]
|
required: [member_only, workspace_bound, transferable, internal_use_only, multi_tenant]
|
||||||
properties:
|
properties:
|
||||||
member_only:
|
member_only:
|
||||||
type: boolean
|
type: boolean
|
||||||
workspace_bound:
|
workspace_bound:
|
||||||
type: boolean
|
type: boolean
|
||||||
transferable:
|
transferable:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
internal_use_only:
|
||||||
|
type: boolean
|
||||||
|
multi_tenant:
|
||||||
|
type: boolean
|
||||||
CheckoutQuoteRequest:
|
CheckoutQuoteRequest:
|
||||||
type: object
|
type: object
|
||||||
required: [wallet, offer_id]
|
required: [wallet, offer_id]
|
||||||
@ -158,6 +162,15 @@ components:
|
|||||||
description: Optional wallet paying the quote transaction when different from ownership wallet.
|
description: Optional wallet paying the quote transaction when different from ownership wallet.
|
||||||
offer_id:
|
offer_id:
|
||||||
type: string
|
type: string
|
||||||
|
org_root_id:
|
||||||
|
type: string
|
||||||
|
description: Economic boundary identifier for suite entitlement checks.
|
||||||
|
principal_id:
|
||||||
|
type: string
|
||||||
|
description: Human principal requesting checkout.
|
||||||
|
principal_role:
|
||||||
|
type: string
|
||||||
|
enum: [workspace_member, org_root_owner]
|
||||||
workspace_id:
|
workspace_id:
|
||||||
type: string
|
type: string
|
||||||
ownership_proof:
|
ownership_proof:
|
||||||
@ -179,6 +192,13 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
offer_id:
|
offer_id:
|
||||||
type: string
|
type: string
|
||||||
|
org_root_id:
|
||||||
|
type: string
|
||||||
|
principal_id:
|
||||||
|
type: string
|
||||||
|
principal_role:
|
||||||
|
type: string
|
||||||
|
enum: [workspace_member, org_root_owner]
|
||||||
currency:
|
currency:
|
||||||
type: string
|
type: string
|
||||||
amount:
|
amount:
|
||||||
@ -207,6 +227,12 @@ components:
|
|||||||
tx:
|
tx:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
|
access_class:
|
||||||
|
type: string
|
||||||
|
enum: [connected, sovereign]
|
||||||
|
availability_state:
|
||||||
|
type: string
|
||||||
|
enum: [active, grace, continuity, parked]
|
||||||
QuoteLineItem:
|
QuoteLineItem:
|
||||||
type: object
|
type: object
|
||||||
required: [kind, amount_atomic, decimals, currency, label]
|
required: [kind, amount_atomic, decimals, currency, label]
|
||||||
@ -240,6 +266,15 @@ components:
|
|||||||
description: Optional payment wallet for tx provenance when different from ownership wallet.
|
description: Optional payment wallet for tx provenance when different from ownership wallet.
|
||||||
offer_id:
|
offer_id:
|
||||||
type: string
|
type: string
|
||||||
|
org_root_id:
|
||||||
|
type: string
|
||||||
|
principal_id:
|
||||||
|
type: string
|
||||||
|
principal_role:
|
||||||
|
type: string
|
||||||
|
enum: [workspace_member, org_root_owner]
|
||||||
|
workspace_id:
|
||||||
|
type: string
|
||||||
tx_hash:
|
tx_hash:
|
||||||
type: string
|
type: string
|
||||||
pattern: '^0x[a-fA-F0-9]{64}$'
|
pattern: '^0x[a-fA-F0-9]{64}$'
|
||||||
@ -256,6 +291,13 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
offer_id:
|
offer_id:
|
||||||
type: string
|
type: string
|
||||||
|
org_root_id:
|
||||||
|
type: string
|
||||||
|
principal_id:
|
||||||
|
type: string
|
||||||
|
principal_role:
|
||||||
|
type: string
|
||||||
|
enum: [workspace_member, org_root_owner]
|
||||||
wallet:
|
wallet:
|
||||||
type: string
|
type: string
|
||||||
tx_hash:
|
tx_hash:
|
||||||
@ -265,6 +307,12 @@ components:
|
|||||||
activated_at:
|
activated_at:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
|
access_class:
|
||||||
|
type: string
|
||||||
|
enum: [connected, sovereign]
|
||||||
|
availability_state:
|
||||||
|
type: string
|
||||||
|
enum: [active, grace, continuity, parked]
|
||||||
Entitlement:
|
Entitlement:
|
||||||
type: object
|
type: object
|
||||||
required: [entitlement_id, offer_id, wallet_address, state]
|
required: [entitlement_id, offer_id, wallet_address, state]
|
||||||
@ -277,9 +325,17 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
workspace_id:
|
workspace_id:
|
||||||
type: string
|
type: string
|
||||||
|
org_root_id:
|
||||||
|
type: string
|
||||||
state:
|
state:
|
||||||
type: string
|
type: string
|
||||||
enum: [active, suspended, revoked, expired]
|
enum: [active, suspended, revoked, expired]
|
||||||
|
access_class:
|
||||||
|
type: string
|
||||||
|
enum: [connected, sovereign]
|
||||||
|
availability_state:
|
||||||
|
type: string
|
||||||
|
enum: [active, grace, continuity, parked]
|
||||||
policy_hash:
|
policy_hash:
|
||||||
type: string
|
type: string
|
||||||
issued_at:
|
issued_at:
|
||||||
|
|||||||
@ -127,6 +127,29 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/ErrorResponse'
|
$ref: '#/components/schemas/ErrorResponse'
|
||||||
|
/member/channel/support/ticket:
|
||||||
|
post:
|
||||||
|
summary: Open support/admin ticket (org root owner only).
|
||||||
|
operationId: createOwnerSupportTicket
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/SupportTicketRequest'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Support ticket accepted.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/SupportTicketResponse'
|
||||||
|
'403':
|
||||||
|
description: Principal is not org root owner.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ErrorResponse'
|
||||||
components:
|
components:
|
||||||
securitySchemes:
|
securitySchemes:
|
||||||
WalletSession:
|
WalletSession:
|
||||||
@ -141,6 +164,9 @@ components:
|
|||||||
- chain_id
|
- chain_id
|
||||||
- device_id
|
- device_id
|
||||||
- platform
|
- platform
|
||||||
|
- org_root_id
|
||||||
|
- principal_id
|
||||||
|
- principal_role
|
||||||
- app_version
|
- app_version
|
||||||
properties:
|
properties:
|
||||||
wallet:
|
wallet:
|
||||||
@ -155,6 +181,15 @@ components:
|
|||||||
platform:
|
platform:
|
||||||
type: string
|
type: string
|
||||||
enum: [ios, android, desktop]
|
enum: [ios, android, desktop]
|
||||||
|
org_root_id:
|
||||||
|
type: string
|
||||||
|
description: Organization boundary id for channel scoping.
|
||||||
|
principal_id:
|
||||||
|
type: string
|
||||||
|
description: Human principal id for this session.
|
||||||
|
principal_role:
|
||||||
|
type: string
|
||||||
|
enum: [workspace_member, org_root_owner]
|
||||||
app_version:
|
app_version:
|
||||||
type: string
|
type: string
|
||||||
push_provider:
|
push_provider:
|
||||||
@ -212,6 +247,8 @@ components:
|
|||||||
required:
|
required:
|
||||||
- wallet
|
- wallet
|
||||||
- device_id
|
- device_id
|
||||||
|
- org_root_id
|
||||||
|
- principal_id
|
||||||
- events
|
- events
|
||||||
- next_cursor
|
- next_cursor
|
||||||
- server_time
|
- server_time
|
||||||
@ -220,6 +257,10 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
device_id:
|
device_id:
|
||||||
type: string
|
type: string
|
||||||
|
org_root_id:
|
||||||
|
type: string
|
||||||
|
principal_id:
|
||||||
|
type: string
|
||||||
events:
|
events:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
@ -251,6 +292,9 @@ components:
|
|||||||
- platform_update
|
- platform_update
|
||||||
- publisher_update
|
- publisher_update
|
||||||
- membership_policy
|
- membership_policy
|
||||||
|
- admin_health
|
||||||
|
- admin_config
|
||||||
|
- admin_update
|
||||||
created_at:
|
created_at:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
@ -268,6 +312,10 @@ components:
|
|||||||
payload:
|
payload:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
|
visibility_scope:
|
||||||
|
type: string
|
||||||
|
enum: [member, owner_admin]
|
||||||
|
default: member
|
||||||
EventAckRequest:
|
EventAckRequest:
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
@ -309,3 +357,41 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
correlation_id:
|
correlation_id:
|
||||||
type: string
|
type: string
|
||||||
|
SupportTicketRequest:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- wallet
|
||||||
|
- org_root_id
|
||||||
|
- principal_id
|
||||||
|
- category
|
||||||
|
- summary
|
||||||
|
properties:
|
||||||
|
wallet:
|
||||||
|
type: string
|
||||||
|
org_root_id:
|
||||||
|
type: string
|
||||||
|
principal_id:
|
||||||
|
type: string
|
||||||
|
category:
|
||||||
|
type: string
|
||||||
|
enum: [admin_support, health_diagnostic, boundary_issue, update_control]
|
||||||
|
summary:
|
||||||
|
type: string
|
||||||
|
context:
|
||||||
|
type: object
|
||||||
|
additionalProperties: true
|
||||||
|
SupportTicketResponse:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- status
|
||||||
|
- ticket_id
|
||||||
|
- created_at
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
enum: [accepted]
|
||||||
|
ticket_id:
|
||||||
|
type: string
|
||||||
|
created_at:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
|||||||
@ -24,11 +24,18 @@ Member communication is delivered through EDUT app channels after wallet sign-in
|
|||||||
3. Platform updates and required migration actions.
|
3. Platform updates and required migration actions.
|
||||||
4. Publisher updates for offers a member owns.
|
4. Publisher updates for offers a member owns.
|
||||||
5. Membership policy changes that affect purchase or activation behavior.
|
5. Membership policy changes that affect purchase or activation behavior.
|
||||||
|
6. Availability state transitions (`grace`, `continuity`, `parked`) and required recovery actions.
|
||||||
|
|
||||||
## Gate Rule
|
## Gate Rule
|
||||||
|
|
||||||
No active membership -> no app access channel.
|
No active membership -> no app access channel.
|
||||||
|
|
||||||
|
Admin plane gate:
|
||||||
|
|
||||||
|
1. `org_root_owner` role can access support/admin classes (health diagnostics, config/update controls).
|
||||||
|
2. `workspace_member` role receives daily-use events only.
|
||||||
|
3. Member admin attempts return deterministic guidance: `contact_your_org_admin`.
|
||||||
|
|
||||||
## Deterministic Delivery Rules
|
## Deterministic Delivery Rules
|
||||||
|
|
||||||
1. Notification eligibility is computed from wallet-authenticated entitlement state.
|
1. Notification eligibility is computed from wallet-authenticated entitlement state.
|
||||||
@ -36,6 +43,7 @@ No active membership -> no app access channel.
|
|||||||
3. Membership revocation/suspension immediately suppresses member-channel delivery.
|
3. Membership revocation/suspension immediately suppresses member-channel delivery.
|
||||||
4. No marketing list fan-out disconnected from entitlement state.
|
4. No marketing list fan-out disconnected from entitlement state.
|
||||||
5. Event polling inbox is canonical; push transport is optional acceleration.
|
5. Event polling inbox is canonical; push transport is optional acceleration.
|
||||||
|
6. Boundary mismatch and parked-state events must include exact remediation steps.
|
||||||
|
|
||||||
## Contract References
|
## Contract References
|
||||||
|
|
||||||
|
|||||||
100
docs/availability-boundary-model.md
Normal file
100
docs/availability-boundary-model.md
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
# Availability and Boundary Model (v1)
|
||||||
|
|
||||||
|
This document defines deterministic licensing behavior for paid EDUT operation without per-seat SaaS metering.
|
||||||
|
|
||||||
|
## Core Invariant
|
||||||
|
|
||||||
|
`One Suite License = One Economic Boundary`
|
||||||
|
|
||||||
|
1. A suite license is bound to one `org_root_id`.
|
||||||
|
2. Unlimited internal workspaces are allowed under that same `org_root_id`.
|
||||||
|
3. Cross-boundary paid execution is blocked unless the target boundary has its own suite license.
|
||||||
|
|
||||||
|
## Identity and Rights Layers
|
||||||
|
|
||||||
|
1. Human membership credential (`membership_token`):
|
||||||
|
- required for each acting human principal.
|
||||||
|
2. Org suite entitlement (`suite_entitlement`):
|
||||||
|
- bound to `org_root_id`;
|
||||||
|
- enables paid execution for workspaces inside that boundary.
|
||||||
|
3. Human access class (`access_class`):
|
||||||
|
- `connected`: lower-cost, heartbeat-based availability;
|
||||||
|
- `sovereign`: premium local continuity with long-lived offline capsule.
|
||||||
|
|
||||||
|
Membership confirms principal identity. Suite entitlement confirms boundary rights. Access class controls availability mechanics.
|
||||||
|
|
||||||
|
## Availability State Machine
|
||||||
|
|
||||||
|
Runtime availability is deterministic and applies to paid execution:
|
||||||
|
|
||||||
|
1. `ACTIVE`
|
||||||
|
- lease/capsule valid;
|
||||||
|
- full paid execution allowed.
|
||||||
|
2. `GRACE`
|
||||||
|
- temporary missed renewal window;
|
||||||
|
- full execution continues while automatic recovery runs.
|
||||||
|
3. `CONTINUITY`
|
||||||
|
- prolonged renewal miss;
|
||||||
|
- existing operations continue, but growth actions are blocked:
|
||||||
|
- no new members,
|
||||||
|
- no new workspaces,
|
||||||
|
- no new tool installs,
|
||||||
|
- no new worker spawns.
|
||||||
|
4. `PARKED`
|
||||||
|
- renewal unresolved beyond continuity window;
|
||||||
|
- paid execution paused;
|
||||||
|
- read/search/export remains available.
|
||||||
|
|
||||||
|
## Renewal Sources by Access Class
|
||||||
|
|
||||||
|
1. `connected`
|
||||||
|
- requires periodic org-root heartbeat lease renewal.
|
||||||
|
2. `sovereign`
|
||||||
|
- uses long-lived local entitlement capsule;
|
||||||
|
- renews online or via signed offline transfer workflow.
|
||||||
|
|
||||||
|
Both classes converge to the same state machine (`ACTIVE -> GRACE -> CONTINUITY -> PARKED`) when renewal evidence ages out.
|
||||||
|
|
||||||
|
## Boundary Enforcement Rules
|
||||||
|
|
||||||
|
Every paid action must pass:
|
||||||
|
|
||||||
|
1. valid human membership;
|
||||||
|
2. workspace bound to `org_root_id`;
|
||||||
|
3. suite entitlement active for that `org_root_id`;
|
||||||
|
4. access-class availability state not `PARKED`;
|
||||||
|
5. connector/account boundary ownership compatible with workspace boundary.
|
||||||
|
|
||||||
|
If any check fails, system fails closed for paid execution and emits evidence.
|
||||||
|
|
||||||
|
## Delegation and Offboarding
|
||||||
|
|
||||||
|
1. Delegation can grant role capabilities in a workspace.
|
||||||
|
2. Delegation does not transfer suite ownership or boundary rights.
|
||||||
|
3. Offboarding revokes workspace delegation immediately.
|
||||||
|
4. Revoked principals cannot obtain new paid action tokens for that org boundary.
|
||||||
|
|
||||||
|
## Admin Plane Ownership Model
|
||||||
|
|
||||||
|
1. `org_root_owner` is the only role with:
|
||||||
|
- health diagnostics,
|
||||||
|
- update controls,
|
||||||
|
- configuration mutation rights,
|
||||||
|
- direct support channel access.
|
||||||
|
2. `workspace_member` role is limited to daily-use product actions.
|
||||||
|
3. Member attempts to access admin/support endpoints return deterministic guidance:
|
||||||
|
- `contact_your_org_admin`.
|
||||||
|
4. Support systems authenticate org-root ownership before accepting admin-level requests.
|
||||||
|
|
||||||
|
This creates natural anti-reseller friction: scaling external seats increases the reseller's support burden without shifting that burden to EDUT.
|
||||||
|
|
||||||
|
## UX Contract
|
||||||
|
|
||||||
|
1. No surprise data lockout: read/search/export survive `PARKED`.
|
||||||
|
2. Status must be visible in plain language:
|
||||||
|
- current state,
|
||||||
|
- what is still allowed,
|
||||||
|
- exact recovery action.
|
||||||
|
3. AI fallback and budget modes are separate from entitlement availability:
|
||||||
|
- token-budget fallback may reduce AI features;
|
||||||
|
- entitlement availability controls whether paid math execution remains authorized.
|
||||||
@ -22,6 +22,7 @@ This policy keeps public web minimal while allowing full commerce inside the lau
|
|||||||
2. Offer manifests require app session and rate limits.
|
2. Offer manifests require app session and rate limits.
|
||||||
3. Manifest payloads are short-TTL and signed.
|
3. Manifest payloads are short-TTL and signed.
|
||||||
4. Checkout endpoints require nonce-bound quotes and ownership-proof rules.
|
4. Checkout endpoints require nonce-bound quotes and ownership-proof rules.
|
||||||
|
5. Paid execution requests must include org-boundary claims and fail closed on mismatch.
|
||||||
|
|
||||||
## Legal Clarity Rule
|
## Legal Clarity Rule
|
||||||
|
|
||||||
|
|||||||
@ -2,13 +2,15 @@
|
|||||||
|
|
||||||
## Scope
|
## Scope
|
||||||
|
|
||||||
Operational procedures for membership mint and checkout confirmation dependency on chain state.
|
Operational procedures for membership mint, checkout confirmation, and availability lease/renewal dependency on chain state.
|
||||||
|
|
||||||
## Normal Operation
|
## Normal Operation
|
||||||
|
|
||||||
1. Primary RPC healthy.
|
1. Primary RPC healthy.
|
||||||
2. Confirmation endpoint verifies tx receipt and policy match.
|
2. Confirmation endpoint verifies tx receipt and policy match.
|
||||||
3. Membership state transitions to `membership_active` only on valid confirmation.
|
3. Membership state transitions to `membership_active` only on valid confirmation.
|
||||||
|
4. Connected-class lease heartbeats refresh availability before expiry.
|
||||||
|
5. Sovereign-class offline renewal bundles validate signature and policy hash before state promotion.
|
||||||
|
|
||||||
## Degraded Scenarios
|
## Degraded Scenarios
|
||||||
|
|
||||||
@ -42,6 +44,7 @@ Safe mode actions:
|
|||||||
1. Pause new confirmations.
|
1. Pause new confirmations.
|
||||||
2. Keep purchase state blocked.
|
2. Keep purchase state blocked.
|
||||||
3. Emit incident evidence.
|
3. Emit incident evidence.
|
||||||
|
4. Prevent availability promotions when renewal evidence is uncertain.
|
||||||
|
|
||||||
## Recovery
|
## Recovery
|
||||||
|
|
||||||
|
|||||||
103
docs/conformance/availability-boundary-vectors.md
Normal file
103
docs/conformance/availability-boundary-vectors.md
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
# Availability and Boundary Conformance Vectors (v1)
|
||||||
|
|
||||||
|
This document defines deterministic vectors for org-boundary enforcement and availability classes.
|
||||||
|
|
||||||
|
## Vector Group AB1: Org Boundary Binding
|
||||||
|
|
||||||
|
1. `AB1-001` workspace_within_org_root_allows_paid_action
|
||||||
|
- Given workspace `W1` bound to `org_root_id=ORG_A`
|
||||||
|
- And suite entitlement for `ORG_A` is active
|
||||||
|
- When paid action is requested inside `W1`
|
||||||
|
- Then action is allowed (subject to other gates)
|
||||||
|
|
||||||
|
2. `AB1-002` workspace_boundary_mismatch_blocks_paid_action
|
||||||
|
- Given workspace `W2` bound to `ORG_B`
|
||||||
|
- And requester entitlement bound only to `ORG_A`
|
||||||
|
- When paid action is requested in `W2`
|
||||||
|
- Then action is blocked with `boundary_mismatch`
|
||||||
|
|
||||||
|
3. `AB1-003` delegated_actor_no_boundary_transfer
|
||||||
|
- Given human from `ORG_A` delegated role in `ORG_B`
|
||||||
|
- And no active suite entitlement for `ORG_B`
|
||||||
|
- When paid action is requested
|
||||||
|
- Then action is blocked with `target_org_suite_required`
|
||||||
|
|
||||||
|
## Vector Group AB2: Connected Access Class
|
||||||
|
|
||||||
|
1. `AB2-001` connected_active_with_fresh_heartbeat
|
||||||
|
- Given `access_class=connected`
|
||||||
|
- And lease heartbeat age inside policy window
|
||||||
|
- Then availability state is `ACTIVE`
|
||||||
|
|
||||||
|
2. `AB2-002` connected_enters_grace_after_missed_heartbeat
|
||||||
|
- Given `access_class=connected`
|
||||||
|
- And heartbeat missed past active window but inside grace window
|
||||||
|
- Then state is `GRACE`
|
||||||
|
- And paid execution remains allowed
|
||||||
|
|
||||||
|
3. `AB2-003` connected_continuity_blocks_growth_actions
|
||||||
|
- Given `access_class=connected` in `CONTINUITY`
|
||||||
|
- When attempting growth action (new member/workspace/tool install/worker spawn)
|
||||||
|
- Then request is blocked with `continuity_growth_blocked`
|
||||||
|
|
||||||
|
4. `AB2-004` connected_parked_blocks_paid_execution
|
||||||
|
- Given `access_class=connected` in `PARKED`
|
||||||
|
- When paid action is requested
|
||||||
|
- Then action is blocked with `entitlement_parked`
|
||||||
|
- And read/search/export remains allowed
|
||||||
|
|
||||||
|
## Vector Group AB3: Sovereign Access Class
|
||||||
|
|
||||||
|
1. `AB3-001` sovereign_active_offline_with_valid_capsule
|
||||||
|
- Given `access_class=sovereign`
|
||||||
|
- And local entitlement capsule is valid
|
||||||
|
- And no network connectivity
|
||||||
|
- Then state remains `ACTIVE`
|
||||||
|
|
||||||
|
2. `AB3-002` sovereign_transitions_on_capsule_expiry
|
||||||
|
- Given `access_class=sovereign`
|
||||||
|
- And capsule renewal evidence ages past active window
|
||||||
|
- Then state transitions `ACTIVE -> GRACE -> CONTINUITY -> PARKED` by policy thresholds
|
||||||
|
|
||||||
|
3. `AB3-003` sovereign_offline_renewal_restores_active
|
||||||
|
- Given `access_class=sovereign` in `CONTINUITY` or `PARKED`
|
||||||
|
- When signed offline renewal package is applied and verified
|
||||||
|
- Then state becomes `ACTIVE`
|
||||||
|
|
||||||
|
## Vector Group AB4: Offboarding and Token Revocation
|
||||||
|
|
||||||
|
1. `AB4-001` offboarded_human_cannot_get_new_action_token
|
||||||
|
- Given human delegation revoked at time `T`
|
||||||
|
- When requesting new paid action token after `T`
|
||||||
|
- Then token issuance is denied
|
||||||
|
|
||||||
|
2. `AB4-002` offboarding_does_not_remove_local_read_access_snapshot
|
||||||
|
- Given org access revoked and local data retention policy active
|
||||||
|
- When user opens local history view
|
||||||
|
- Then read/search/export policy behaves per retention rules without re-enabling paid execution
|
||||||
|
|
||||||
|
## Vector Group AB5: Admin Plane Ownership Gating
|
||||||
|
|
||||||
|
1. `AB5-001` only_root_owner_can_open_support_channel
|
||||||
|
- Given principal role `workspace_member`
|
||||||
|
- When calling support/admin channel endpoint
|
||||||
|
- Then response is denied with `contact_your_org_admin`
|
||||||
|
|
||||||
|
2. `AB5-002` root_owner_receives_admin_health_events
|
||||||
|
- Given principal role `org_root_owner`
|
||||||
|
- When health/config/update admin events are emitted
|
||||||
|
- Then events are visible in owner stream
|
||||||
|
- And not visible in member-only streams
|
||||||
|
|
||||||
|
3. `AB5-003` member_cannot_mutate_admin_configuration
|
||||||
|
- Given principal role `workspace_member`
|
||||||
|
- When attempting org-level config mutation
|
||||||
|
- Then request is denied
|
||||||
|
|
||||||
|
## Pass Criteria
|
||||||
|
|
||||||
|
Build is conformant only when all vectors pass.
|
||||||
|
|
||||||
|
## Fail-Closed Rule
|
||||||
|
|
||||||
|
Unknown boundary binding, unknown availability state, or unverifiable renewal evidence must block paid execution by default.
|
||||||
@ -14,6 +14,9 @@ These vectors verify deterministic governance runtime installation and activatio
|
|||||||
8. `GV-008` entitlement revoked after activation forces status `blocked` until entitlement restored.
|
8. `GV-008` entitlement revoked after activation forces status `blocked` until entitlement restored.
|
||||||
9. `GV-009` membership suspended forces status `blocked` regardless of local runtime presence.
|
9. `GV-009` membership suspended forces status `blocked` regardless of local runtime presence.
|
||||||
10. `GV-010` unknown entitlement state fails closed and blocks activation.
|
10. `GV-010` unknown entitlement state fails closed and blocks activation.
|
||||||
|
11. `GV-011` workspace/org boundary mismatch blocks install token issuance.
|
||||||
|
12. `GV-012` availability state `parked` blocks install token issuance and activation.
|
||||||
|
13. `GV-013` non-owner principal role blocks governance install/update control paths.
|
||||||
|
|
||||||
## Pass Criteria
|
## Pass Criteria
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,9 @@ These vectors verify deterministic member communication behavior.
|
|||||||
8. `MC-008` Push unavailable -> event still available in poll inbox.
|
8. `MC-008` Push unavailable -> event still available in poll inbox.
|
||||||
9. `MC-009` Dedupe key collision attempt -> backend rejects duplicate event insertion for same member stream.
|
9. `MC-009` Dedupe key collision attempt -> backend rejects duplicate event insertion for same member stream.
|
||||||
10. `MC-010` Wallet mismatch between session and payload -> request rejected.
|
10. `MC-010` Wallet mismatch between session and payload -> request rejected.
|
||||||
|
11. `MC-011` Non-owner support ticket attempt -> denied with `contact_your_org_admin`.
|
||||||
|
12. `MC-012` Owner support ticket attempt -> accepted with ticket id.
|
||||||
|
13. `MC-013` Admin-class events are only visible to `org_root_owner` principal role.
|
||||||
|
|
||||||
## Pass Criteria
|
## Pass Criteria
|
||||||
|
|
||||||
|
|||||||
@ -148,6 +148,25 @@ This document defines deterministic pass/fail vectors for membership-gated comme
|
|||||||
3. E3 `audit_non_regression`
|
3. E3 `audit_non_regression`
|
||||||
- Once state reaches `membership_active`, audit log cannot be removed or mutated without append-only evidence entry
|
- Once state reaches `membership_active`, audit log cannot be removed or mutated without append-only evidence entry
|
||||||
|
|
||||||
|
## Vector Group H: Boundary and Availability Gate Hooks
|
||||||
|
|
||||||
|
1. H1 `checkout_block_boundary_mismatch`
|
||||||
|
- Given ownership wallet is bound to `org_root_id=ORG_A`
|
||||||
|
- And checkout target workspace is bound to `ORG_B`
|
||||||
|
- When quote is requested without valid ORG_B entitlement
|
||||||
|
- Then checkout is denied
|
||||||
|
|
||||||
|
2. H2 `checkout_block_availability_parked`
|
||||||
|
- Given membership is active
|
||||||
|
- And suite availability state for principal/workspace is `PARKED`
|
||||||
|
- When checkout confirm or paid activation is requested
|
||||||
|
- Then request is denied
|
||||||
|
|
||||||
|
3. H3 `continuity_blocks_growth_actions`
|
||||||
|
- Given availability state is `CONTINUITY`
|
||||||
|
- When action requests new workspace member, workspace creation, new tool install, or worker spawn
|
||||||
|
- Then request is denied with continuity policy reason
|
||||||
|
|
||||||
## Pass Criteria
|
## Pass Criteria
|
||||||
|
|
||||||
A build is conformant only when all vectors pass.
|
A build is conformant only when all vectors pass.
|
||||||
|
|||||||
@ -32,6 +32,18 @@ interface IEdutEntitlement {
|
|||||||
function mintEntitlement(bytes32 offerKey, address wallet, bytes32 policyHash) external returns (bytes32 entitlementId);
|
function mintEntitlement(bytes32 offerKey, address wallet, bytes32 policyHash) external returns (bytes32 entitlementId);
|
||||||
function entitlementState(bytes32 entitlementId) external view returns (uint8 state);
|
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
|
## Status Enums
|
||||||
@ -54,6 +66,20 @@ EntitlementState:
|
|||||||
1 = SUSPENDED
|
1 = SUSPENDED
|
||||||
2 = REVOKED
|
2 = REVOKED
|
||||||
3 = EXPIRED
|
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)
|
## API Surface (Backend)
|
||||||
@ -73,12 +99,15 @@ EntitlementState:
|
|||||||
3. `POST /marketplace/checkout/quote`
|
3. `POST /marketplace/checkout/quote`
|
||||||
4. `POST /marketplace/checkout/confirm`
|
4. `POST /marketplace/checkout/confirm`
|
||||||
5. `GET /marketplace/entitlements`
|
5. `GET /marketplace/entitlements`
|
||||||
|
6. `GET /marketplace/availability?org_root_id=...&principal_id=...`
|
||||||
|
|
||||||
## Governance Installer
|
## Governance Installer
|
||||||
|
|
||||||
1. `POST /governance/install/token`
|
1. `POST /governance/install/token`
|
||||||
2. `POST /governance/install/confirm`
|
2. `POST /governance/install/confirm`
|
||||||
3. `GET /governance/install/status`
|
3. `GET /governance/install/status`
|
||||||
|
4. `POST /governance/lease/heartbeat`
|
||||||
|
5. `POST /governance/lease/offline-renew`
|
||||||
|
|
||||||
## Issuer APIs
|
## Issuer APIs
|
||||||
|
|
||||||
@ -99,10 +128,15 @@ EntitlementState:
|
|||||||
- `expires_at`
|
- `expires_at`
|
||||||
2. Checkout confirm must fail closed if:
|
2. Checkout confirm must fail closed if:
|
||||||
- membership is not active,
|
- membership is not active,
|
||||||
|
- suite boundary checks fail (`org_root_id` mismatch),
|
||||||
|
- availability state is `PARKED`,
|
||||||
- quote expired,
|
- quote expired,
|
||||||
- tx amount/currency mismatch,
|
- tx amount/currency mismatch,
|
||||||
- policy hash mismatch.
|
- policy hash mismatch.
|
||||||
3. Entitlement activation must fail closed when state is not `ACTIVE`.
|
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
|
## Evidence Requirements
|
||||||
|
|
||||||
@ -114,7 +148,11 @@ Each successful purchase must emit/record:
|
|||||||
4. quote_id
|
4. quote_id
|
||||||
5. tx_hash and chain_id
|
5. tx_hash and chain_id
|
||||||
6. entitlement_id
|
6. entitlement_id
|
||||||
7. receipt timestamp
|
7. org_root_id
|
||||||
|
8. principal_id
|
||||||
|
9. access_class + availability_state snapshot
|
||||||
|
10. principal_role snapshot
|
||||||
|
11. receipt timestamp
|
||||||
|
|
||||||
## Compatibility Rule
|
## Compatibility Rule
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,9 @@ These invariants must hold for staging and production.
|
|||||||
3. Quote currency policy matches configured token addresses.
|
3. Quote currency policy matches configured token addresses.
|
||||||
4. Origin allowlist includes only approved domains.
|
4. Origin allowlist includes only approved domains.
|
||||||
5. Fail-closed default behavior enabled for unknown membership/entitlement states.
|
5. Fail-closed default behavior enabled for unknown membership/entitlement states.
|
||||||
|
6. Org boundary enforcement enabled for workspace-bound paid actions.
|
||||||
|
7. Availability state machine policy loaded with `ACTIVE/GRACE/CONTINUITY/PARKED`.
|
||||||
|
8. `PARKED` policy blocks paid execution while preserving read/export routes.
|
||||||
|
|
||||||
## Verification Checklist
|
## Verification Checklist
|
||||||
|
|
||||||
@ -16,3 +19,5 @@ These invariants must hold for staging and production.
|
|||||||
2. Confirm endpoint rejects tx on wrong chain.
|
2. Confirm endpoint rejects tx on wrong chain.
|
||||||
3. Checkout gate blocks non-members.
|
3. Checkout gate blocks non-members.
|
||||||
4. Runtime activation gate blocks non-active entitlements.
|
4. Runtime activation gate blocks non-active entitlements.
|
||||||
|
5. Boundary mismatch gate blocks paid execution.
|
||||||
|
6. `continuity` and `parked` transitions enforce expected behavior.
|
||||||
|
|||||||
@ -18,6 +18,10 @@ This matrix defines deterministic fail-closed behavior and user-facing outcomes.
|
|||||||
| Confirm | Node unavailable | RPC health | Fail closed | "Unable to confirm transaction. Purchase stays blocked." |
|
| Confirm | Node unavailable | RPC health | Fail closed | "Unable to confirm transaction. Purchase stays blocked." |
|
||||||
| Checkout | No membership | Gate check | Block purchase | "Membership required." |
|
| Checkout | No membership | Gate check | Block purchase | "Membership required." |
|
||||||
| Checkout | Membership suspended/revoked | Gate check | Block purchase | "Membership inactive. Contact support." |
|
| Checkout | Membership suspended/revoked | Gate check | Block purchase | "Membership inactive. Contact support." |
|
||||||
|
| Checkout | Workspace/org boundary mismatch | Boundary claim check | Block purchase | "Workspace boundary mismatch. Target org license required." |
|
||||||
|
| Entitlement Availability | Heartbeat/capsule renewal missed (within grace) | Lease policy engine | Enter `GRACE`, keep paid execution | "Connection delayed. System running in grace mode." |
|
||||||
|
| Entitlement Availability | Renewal still missing past grace | Lease policy engine | Enter `CONTINUITY`, block growth actions | "Continuity mode: existing operations continue, expansion paused." |
|
||||||
|
| Entitlement Availability | Renewal unresolved past continuity | Lease policy engine | Enter `PARKED`, pause paid execution | "Execution parked until entitlement is renewed." |
|
||||||
| Governance Install | Install token expired | TTL check | Block install | "Install token expired. Request a new install token." |
|
| Governance Install | Install token expired | TTL check | Block install | "Install token expired. Request a new install token." |
|
||||||
| Governance Install | Package hash mismatch | Package verifier | Block activation | "Package verification failed." |
|
| Governance Install | Package hash mismatch | Package verifier | Block activation | "Package verification failed." |
|
||||||
| Governance Install | Policy hash mismatch | Runtime verifier | Block activation | "Policy mismatch. Install blocked." |
|
| Governance Install | Policy hash mismatch | Runtime verifier | Block activation | "Policy mismatch. Install blocked." |
|
||||||
@ -28,3 +32,4 @@ This matrix defines deterministic fail-closed behavior and user-facing outcomes.
|
|||||||
1. Unknown state defaults to blocked.
|
1. Unknown state defaults to blocked.
|
||||||
2. No failed transition may promote membership or entitlement state.
|
2. No failed transition may promote membership or entitlement state.
|
||||||
3. Every reject path produces structured audit evidence.
|
3. Every reject path produces structured audit evidence.
|
||||||
|
4. `PARKED` must preserve read/search/export pathways.
|
||||||
|
|||||||
@ -7,11 +7,14 @@ This spec defines deterministic installation of the governance runtime after mem
|
|||||||
1. Launcher is installed and wallet is initialized locally.
|
1. Launcher is installed and wallet is initialized locally.
|
||||||
2. Membership is active for ownership wallet.
|
2. Membership is active for ownership wallet.
|
||||||
3. Governance entitlement is active for ownership wallet.
|
3. Governance entitlement is active for ownership wallet.
|
||||||
|
4. Workspace target boundary matches active suite entitlement `org_root_id`.
|
||||||
|
5. Availability state for acting principal is not `PARKED`.
|
||||||
|
6. Acting principal role for install/update control is `ORG_ROOT_OWNER`.
|
||||||
|
|
||||||
## Install Flow
|
## Install Flow
|
||||||
|
|
||||||
1. Launcher requests governance install token from backend.
|
1. Launcher requests governance install token from backend.
|
||||||
2. Backend verifies membership and governance entitlement status.
|
2. Backend verifies membership, governance entitlement, org boundary, and availability state.
|
||||||
3. Backend returns signed install bundle metadata:
|
3. Backend returns signed install bundle metadata:
|
||||||
- package url
|
- package url
|
||||||
- package hash
|
- package hash
|
||||||
@ -44,6 +47,8 @@ Failure states:
|
|||||||
3. Any policy hash mismatch blocks activation.
|
3. Any policy hash mismatch blocks activation.
|
||||||
4. Activation requires both launcher and runtime verification passes.
|
4. Activation requires both launcher and runtime verification passes.
|
||||||
5. Reinstall with same package hash must be idempotent.
|
5. Reinstall with same package hash must be idempotent.
|
||||||
|
6. Boundary mismatch or `PARKED` availability state blocks install token issuance.
|
||||||
|
7. Non-owner principal role blocks install/update control paths.
|
||||||
|
|
||||||
## Ownership vs Payment Wallet
|
## Ownership vs Payment Wallet
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,8 @@ This checklist maps launcher-governance install behavior to backend requirements
|
|||||||
1. `POST /governance/install/token`
|
1. `POST /governance/install/token`
|
||||||
2. `POST /governance/install/confirm`
|
2. `POST /governance/install/confirm`
|
||||||
3. `GET /governance/install/status`
|
3. `GET /governance/install/status`
|
||||||
|
4. `POST /governance/lease/heartbeat`
|
||||||
|
5. `POST /governance/lease/offline-renew`
|
||||||
|
|
||||||
## Contract Source
|
## Contract Source
|
||||||
|
|
||||||
@ -19,6 +21,9 @@ This checklist maps launcher-governance install behavior to backend requirements
|
|||||||
2. Install token issuance requires active governance entitlement.
|
2. Install token issuance requires active governance entitlement.
|
||||||
3. Confirm path must validate package hash and runtime version against issued token.
|
3. Confirm path must validate package hash and runtime version against issued token.
|
||||||
4. Status must fail closed when entitlement state is unknown.
|
4. Status must fail closed when entitlement state is unknown.
|
||||||
|
5. Install token issuance must fail closed on org boundary mismatch.
|
||||||
|
6. `availability_state=parked` must block token issuance and activation.
|
||||||
|
7. Install/update control actions require principal role `org_root_owner`.
|
||||||
|
|
||||||
## Persistence Requirements
|
## Persistence Requirements
|
||||||
|
|
||||||
@ -39,7 +44,8 @@ This checklist maps launcher-governance install behavior to backend requirements
|
|||||||
1. Metrics for token issuance success/fail.
|
1. Metrics for token issuance success/fail.
|
||||||
2. Metrics for confirm success/fail.
|
2. Metrics for confirm success/fail.
|
||||||
3. Metrics for activation blocked by membership/entitlement.
|
3. Metrics for activation blocked by membership/entitlement.
|
||||||
4. Correlation IDs for all state transitions.
|
4. Metrics for activation blocked by boundary mismatch or parked availability.
|
||||||
|
5. Correlation IDs for all state transitions.
|
||||||
|
|
||||||
## Done Criteria
|
## Done Criteria
|
||||||
|
|
||||||
|
|||||||
@ -17,14 +17,17 @@ All marketplace endpoints require authenticated app/session context.
|
|||||||
1. Quote endpoint must deny checkout when membership is not active.
|
1. Quote endpoint must deny checkout when membership is not active.
|
||||||
2. Confirm endpoint must verify quote policy hash and tx match.
|
2. Confirm endpoint must verify quote policy hash and tx match.
|
||||||
3. Entitlement state must default fail-closed for unknown values.
|
3. Entitlement state must default fail-closed for unknown values.
|
||||||
|
4. Quote/confirm must deny cross-boundary paid execution when `org_root_id` does not match active suite entitlement.
|
||||||
|
5. `availability_state=parked` must block paid execution paths.
|
||||||
|
|
||||||
## Store Dependency Mapping
|
## Store Dependency Mapping
|
||||||
|
|
||||||
1. Store catalog requests `/marketplace/offers` (fallback to local JSON until live).
|
1. Store catalog requests `/marketplace/offers` (fallback to local JSON until live).
|
||||||
2. Store quote action posts selected `offer_id` and ownership wallet.
|
2. Store quote action posts selected `offer_id` and ownership wallet.
|
||||||
3. Optional payer wallet may differ and must include ownership proof.
|
3. Optional payer wallet may differ and must include ownership proof.
|
||||||
4. Store expects quote payload with tx execution fields.
|
4. Store sends org-boundary context (`org_root_id`, `principal_id`, `workspace_id`) when available.
|
||||||
5. Store confirm path expects `entitlement_active` response.
|
5. Store expects quote payload with tx execution fields.
|
||||||
|
6. Store confirm path expects `entitlement_active` response.
|
||||||
|
|
||||||
## Quote Response Requirements
|
## Quote Response Requirements
|
||||||
|
|
||||||
@ -40,6 +43,8 @@ All marketplace endpoints require authenticated app/session context.
|
|||||||
10. `policy_hash`
|
10. `policy_hash`
|
||||||
11. `expires_at`
|
11. `expires_at`
|
||||||
12. `tx` execution object or equivalent fields
|
12. `tx` execution object or equivalent fields
|
||||||
|
13. `org_root_id` (when workspace-bound)
|
||||||
|
14. `availability_state` and `access_class` snapshot
|
||||||
|
|
||||||
## Confirm Response Requirements
|
## Confirm Response Requirements
|
||||||
|
|
||||||
@ -51,6 +56,8 @@ All marketplace endpoints require authenticated app/session context.
|
|||||||
6. `tx_hash`
|
6. `tx_hash`
|
||||||
7. `policy_hash`
|
7. `policy_hash`
|
||||||
8. `activated_at`
|
8. `activated_at`
|
||||||
|
9. `org_root_id` and `principal_id` (when provided)
|
||||||
|
10. `availability_state` snapshot
|
||||||
|
|
||||||
## Persistence Requirements
|
## Persistence Requirements
|
||||||
|
|
||||||
@ -66,6 +73,7 @@ All marketplace endpoints require authenticated app/session context.
|
|||||||
4. Idempotent confirm handling for repeated tx hash submissions.
|
4. Idempotent confirm handling for repeated tx hash submissions.
|
||||||
5. Ownership wallet proof validation when payer wallet differs.
|
5. Ownership wallet proof validation when payer wallet differs.
|
||||||
6. Bundled membership component must be explicit in quote line items when included.
|
6. Bundled membership component must be explicit in quote line items when included.
|
||||||
|
7. Continuity policy enforcement: growth actions blocked when `availability_state=continuity`.
|
||||||
|
|
||||||
## Done Criteria
|
## Done Criteria
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ This checklist defines backend requirements for app-native member communication.
|
|||||||
2. `POST /member/channel/device/unregister`
|
2. `POST /member/channel/device/unregister`
|
||||||
3. `GET /member/channel/events`
|
3. `GET /member/channel/events`
|
||||||
4. `POST /member/channel/events/{event_id}/ack`
|
4. `POST /member/channel/events/{event_id}/ack`
|
||||||
|
5. `POST /member/channel/support/ticket` (owner-only)
|
||||||
|
|
||||||
## Contract Source
|
## Contract Source
|
||||||
|
|
||||||
@ -21,6 +22,7 @@ This checklist defines backend requirements for app-native member communication.
|
|||||||
3. Event ids and dedupe keys are immutable once emitted.
|
3. Event ids and dedupe keys are immutable once emitted.
|
||||||
4. Event ordering is monotonic by server sequence.
|
4. Event ordering is monotonic by server sequence.
|
||||||
5. `ack` is idempotent per `event_id` + `device_id`.
|
5. `ack` is idempotent per `event_id` + `device_id`.
|
||||||
|
6. Admin/support channel actions require principal role `org_root_owner`.
|
||||||
|
|
||||||
## Data Requirements
|
## Data Requirements
|
||||||
|
|
||||||
@ -30,6 +32,7 @@ Persist at minimum:
|
|||||||
2. Membership status snapshot at event emission time
|
2. Membership status snapshot at event emission time
|
||||||
3. Event envelope (`event_id`, class, title/body, payload, policy_hash, dedupe_key)
|
3. Event envelope (`event_id`, class, title/body, payload, policy_hash, dedupe_key)
|
||||||
4. Delivery and ack timestamps
|
4. Delivery and ack timestamps
|
||||||
|
5. Principal role snapshot used for channel eligibility
|
||||||
|
|
||||||
## Security Requirements
|
## Security Requirements
|
||||||
|
|
||||||
@ -37,6 +40,7 @@ Persist at minimum:
|
|||||||
2. Validate wallet in request matches authenticated session wallet.
|
2. Validate wallet in request matches authenticated session wallet.
|
||||||
3. Reject event polling for suspended/revoked memberships.
|
3. Reject event polling for suspended/revoked memberships.
|
||||||
4. Protect against cursor tampering and replay.
|
4. Protect against cursor tampering and replay.
|
||||||
|
5. Reject support ticket creation for non-owner roles with `contact_your_org_admin`.
|
||||||
|
|
||||||
## Observability Requirements
|
## Observability Requirements
|
||||||
|
|
||||||
@ -51,3 +55,4 @@ Persist at minimum:
|
|||||||
2. Push loss does not lose events because inbox polling is canonical.
|
2. Push loss does not lose events because inbox polling is canonical.
|
||||||
3. Membership status changes immediately gate event visibility.
|
3. Membership status changes immediately gate event visibility.
|
||||||
4. API behavior matches OpenAPI contract and examples.
|
4. API behavior matches OpenAPI contract and examples.
|
||||||
|
5. Admin/support controls are never exposed to non-owner principals.
|
||||||
|
|||||||
@ -14,6 +14,9 @@
|
|||||||
4. Member app channel endpoints for device registration and event polling.
|
4. Member app channel endpoints for device registration and event polling.
|
||||||
5. Governance installer endpoints for signed package authorization and activation confirmation.
|
5. Governance installer endpoints for signed package authorization and activation confirmation.
|
||||||
6. Marketplace catalog/checkout auth gates so production commerce is app-session scoped.
|
6. Marketplace catalog/checkout auth gates so production commerce is app-session scoped.
|
||||||
|
7. Org boundary claim resolution (`org_root_id` binding) for workspace-targeted paid actions.
|
||||||
|
8. Availability class transitions (`connected`/`sovereign`) and lease/capsule state resolution.
|
||||||
|
9. Principal role resolution (`org_root_owner` vs `workspace_member`) for admin/support gating.
|
||||||
|
|
||||||
## Runtime/Kernel Responsibilities
|
## Runtime/Kernel Responsibilities
|
||||||
|
|
||||||
@ -21,9 +24,14 @@
|
|||||||
2. Fail-closed behavior for uncertain states.
|
2. Fail-closed behavior for uncertain states.
|
||||||
3. Evidence receipt generation and retention.
|
3. Evidence receipt generation and retention.
|
||||||
4. Signed package verification and policy hash checks before governance activation.
|
4. Signed package verification and policy hash checks before governance activation.
|
||||||
|
5. Availability state machine enforcement (`ACTIVE -> GRACE -> CONTINUITY -> PARKED`).
|
||||||
|
6. Growth-action block enforcement during `CONTINUITY`.
|
||||||
|
7. Paid execution pause enforcement during `PARKED`.
|
||||||
|
8. Owner-only enforcement for admin health/config/update/support operations.
|
||||||
|
|
||||||
## Required Integration Contract
|
## Required Integration Contract
|
||||||
|
|
||||||
1. Backend API shape follows `docs/api/secret-system.openapi.yaml`.
|
1. Backend API shape follows `docs/api/secret-system.openapi.yaml`.
|
||||||
2. Policy/offer/entitlement payloads validate against schemas.
|
2. Policy/offer/entitlement payloads validate against schemas.
|
||||||
3. Runtime consumes entitlement state and policy hash from backend evidence.
|
3. Runtime consumes entitlement state and policy hash from backend evidence.
|
||||||
|
4. Paid action requests carry boundary claim inputs (`org_root_id`, `workspace_id`, `principal_id`).
|
||||||
|
|||||||
@ -16,6 +16,9 @@ Validate end-to-end behavior from wallet intent to membership-gated checkout and
|
|||||||
8. Governance install token denied when membership or governance entitlement is inactive.
|
8. Governance install token denied when membership or governance entitlement is inactive.
|
||||||
9. Governance install confirm denied when package hash/policy hash mismatches issued token.
|
9. Governance install confirm denied when package hash/policy hash mismatches issued token.
|
||||||
10. Governance runtime activation succeeds only after signed package verification + entitlement active.
|
10. Governance runtime activation succeeds only after signed package verification + entitlement active.
|
||||||
|
11. Boundary mismatch blocks checkout and governance install token issuance.
|
||||||
|
12. `continuity` state allows existing execution but blocks growth actions.
|
||||||
|
13. `parked` state blocks paid execution while preserving read/export endpoints.
|
||||||
|
|
||||||
## Artifacts
|
## Artifacts
|
||||||
|
|
||||||
|
|||||||
@ -31,6 +31,14 @@ The launcher is free and intentionally limited to onboarding and control-plane f
|
|||||||
2. Membership purchase is optional in free mode.
|
2. Membership purchase is optional in free mode.
|
||||||
3. Governance purchase is blocked until membership is active.
|
3. Governance purchase is blocked until membership is active.
|
||||||
4. Free mode remains useful for readiness and wallet setup.
|
4. Free mode remains useful for readiness and wallet setup.
|
||||||
|
5. Launcher must surface availability class and current state (`active`, `grace`, `continuity`, `parked`) in plain language.
|
||||||
|
|
||||||
|
## Availability and Boundary Rules
|
||||||
|
|
||||||
|
1. Paid execution rights are boundary-scoped to an `org_root_id`.
|
||||||
|
2. Launcher must include boundary context in install/checkout requests when workspace-bound.
|
||||||
|
3. `continuity` state blocks growth actions (new members/workspaces/tool installs).
|
||||||
|
4. `parked` state pauses paid execution but preserves visibility/read pathways.
|
||||||
|
|
||||||
## Value Contract
|
## Value Contract
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ This matrix prevents drift between public surfaces and legal posture.
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Landing (`public/index.html`) | Wallet signature + paid membership unlocks access | Investment, yield, appreciation claims |
|
| Landing (`public/index.html`) | Wallet signature + paid membership unlocks access | Investment, yield, appreciation claims |
|
||||||
| Store (`public/store/index.html`) | Membership required for purchasing offers | "Membership includes all products forever" |
|
| Store (`public/store/index.html`) | Membership required for purchasing offers | "Membership includes all products forever" |
|
||||||
| Terms (`public/terms/index.html`) | Membership is utility access; licenses separate | Equity/ownership implications |
|
| Terms (`public/terms/index.html`) | Membership is utility access; licenses separate; internal-use boundary rights by default | Equity/ownership implications or sublicensing-by-default claims |
|
||||||
| Privacy (`public/privacy/index.html`) | Wallet/signature processing and app-channel member communication model | Hidden collection claims inconsistent with implementation |
|
| Privacy (`public/privacy/index.html`) | Wallet/signature processing and app-channel member communication model | Hidden collection claims inconsistent with implementation |
|
||||||
| Vision/spec docs | Deterministic governance and fail-closed controls | Speculative financial framing |
|
| Vision/spec docs | Deterministic governance and fail-closed controls | Speculative financial framing |
|
||||||
|
|
||||||
@ -16,3 +16,5 @@ This matrix prevents drift between public surfaces and legal posture.
|
|||||||
2. Any copy introducing financial upside claims is blocked.
|
2. Any copy introducing financial upside claims is blocked.
|
||||||
3. Any change to legal-critical copy requires review against this matrix.
|
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.
|
4. First checkout totals must disclose line-item composition when membership activation is bundled.
|
||||||
|
5. Copy must not imply resale, sublicensing, or service-bureau rights unless explicitly licensed.
|
||||||
|
6. Copy must not imply direct admin/support access for non-owner member roles.
|
||||||
|
|||||||
@ -15,17 +15,21 @@ This gate controls deploy/no-deploy decisions for membership-gated commerce chan
|
|||||||
1. `docs/conformance/membership-gating-vectors.md`: all vectors pass.
|
1. `docs/conformance/membership-gating-vectors.md`: all vectors pass.
|
||||||
2. `docs/conformance/member-channel-vectors.md`: all vectors pass.
|
2. `docs/conformance/member-channel-vectors.md`: all vectors pass.
|
||||||
3. `docs/conformance/governance-install-vectors.md`: all vectors pass.
|
3. `docs/conformance/governance-install-vectors.md`: all vectors pass.
|
||||||
4. OpenAPI and implementation remain compatible.
|
4. `docs/conformance/availability-boundary-vectors.md`: all vectors pass.
|
||||||
5. Signature replay tests pass.
|
5. OpenAPI and implementation remain compatible.
|
||||||
6. Quote expiry tests pass.
|
6. Signature replay tests pass.
|
||||||
7. Tx mismatch tests pass.
|
7. Quote expiry tests pass.
|
||||||
8. Membership gate blocks non-members in all checkout paths.
|
8. Tx mismatch tests pass.
|
||||||
9. Member channel blocks inactive memberships.
|
9. Membership gate blocks non-members in all checkout paths.
|
||||||
10. Governance activation blocks inactive/unknown entitlement states.
|
10. Member channel blocks inactive memberships.
|
||||||
11. Terms/privacy copy still match utility-access framing.
|
11. Governance activation blocks inactive/unknown entitlement states.
|
||||||
12. Structured logs and metrics are emitted for each state transition.
|
12. Boundary mismatch paths fail closed for paid execution.
|
||||||
13. Bundled membership line-item disclosure is present on first checkout quotes.
|
13. `PARKED` availability state blocks paid execution while preserving read/export paths.
|
||||||
14. Public web deployment blocks anonymous production catalog and quote endpoints.
|
14. Admin/support channel endpoints are owner-gated (`org_root_owner` only).
|
||||||
|
15. Terms/privacy copy still match utility-access framing.
|
||||||
|
16. Structured logs and metrics are emitted for each state transition.
|
||||||
|
17. Bundled membership line-item disclosure is present on first checkout quotes.
|
||||||
|
18. Public web deployment blocks anonymous production catalog and quote endpoints.
|
||||||
|
|
||||||
## No-Deploy Triggers
|
## No-Deploy Triggers
|
||||||
|
|
||||||
@ -38,6 +42,9 @@ This gate controls deploy/no-deploy decisions for membership-gated commerce chan
|
|||||||
7. Any breaking API change without version bump and migration note.
|
7. Any breaking API change without version bump and migration note.
|
||||||
8. Any checkout quote total that cannot be reconciled to disclosed line items.
|
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.
|
9. Any production public route exposing active catalog/checkout without app session auth.
|
||||||
|
10. Any boundary mismatch path that still allows paid execution.
|
||||||
|
11. Any `PARKED` state that still allows paid execution.
|
||||||
|
12. Any non-owner path that can open admin/support channel actions.
|
||||||
|
|
||||||
## Evidence Bundle Required for Release
|
## Evidence Bundle Required for Release
|
||||||
|
|
||||||
|
|||||||
@ -117,3 +117,26 @@ This roadmap is intentionally step-based and dependency-ordered. No timeline com
|
|||||||
2. Production catalog and checkout require app-session auth.
|
2. Production catalog and checkout require app-session auth.
|
||||||
3. Public preview routes are disabled by default and noindexed.
|
3. Public preview routes are disabled by default and noindexed.
|
||||||
4. Release gate blocks deploys that expose anonymous production catalog access.
|
4. Release gate blocks deploys that expose anonymous production catalog access.
|
||||||
|
|
||||||
|
## Step 18: Lock Boundary + Availability Class Model
|
||||||
|
|
||||||
|
1. Suite entitlement binds to one `org_root_id` economic boundary.
|
||||||
|
2. Unlimited internal workspaces allowed inside same boundary.
|
||||||
|
3. Cross-boundary paid execution fails closed without target boundary entitlement.
|
||||||
|
4. Access classes freeze to two values only:
|
||||||
|
- `connected` (heartbeat-based)
|
||||||
|
- `sovereign` (long-lived local capsule)
|
||||||
|
5. Availability state machine is deterministic:
|
||||||
|
- `ACTIVE -> GRACE -> CONTINUITY -> PARKED`
|
||||||
|
6. `CONTINUITY` blocks growth actions while preserving existing execution.
|
||||||
|
7. `PARKED` preserves read/search/export while pausing paid execution.
|
||||||
|
|
||||||
|
## Step 19: Lock Owner-Gated Admin Plane
|
||||||
|
|
||||||
|
1. Principal roles freeze to:
|
||||||
|
- `org_root_owner`
|
||||||
|
- `workspace_member`
|
||||||
|
2. Admin controls (health, updates, config) are owner-only.
|
||||||
|
3. Support channel is owner-only for org-boundary issues.
|
||||||
|
4. Member admin attempts return deterministic guidance (`contact_your_org_admin`).
|
||||||
|
5. Admin event classes are never delivered to non-owner streams.
|
||||||
|
|||||||
@ -20,6 +20,8 @@ Status key:
|
|||||||
10. Add issuer layer interfaces and manifest schema: `DONE`
|
10. Add issuer layer interfaces and manifest schema: `DONE`
|
||||||
11. Harden policy/legal surfaces for utility-access framing: `DONE`
|
11. Harden policy/legal surfaces for utility-access framing: `DONE`
|
||||||
12. Add conformance vectors for fail-closed gating: `DONE`
|
12. Add conformance vectors for fail-closed gating: `DONE`
|
||||||
|
13. Freeze org-boundary + availability class model (`connected`/`sovereign`): `DONE`
|
||||||
|
14. Freeze owner-gated admin/support plane (`org_root_owner` vs `workspace_member`): `DONE`
|
||||||
|
|
||||||
## This Repo Specifically (web)
|
## This Repo Specifically (web)
|
||||||
|
|
||||||
@ -48,6 +50,8 @@ Implemented now:
|
|||||||
21. Public web store preview is noindex and disabled by default unless explicit internal preview mode is enabled.
|
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.
|
22. Catalog distribution and public-surface deployment guardrails are documented for launcher-only commerce.
|
||||||
23. Local split repos (`launcher`, `governance`, `contracts`) are initialized with seed commits and a publish runbook.
|
23. Local split repos (`launcher`, `governance`, `contracts`) are initialized with seed commits and a publish runbook.
|
||||||
|
24. Boundary and availability model documented with deterministic state machine and conformance vectors.
|
||||||
|
25. Owner-gated admin/support model documented in API contracts, terms, and conformance vectors.
|
||||||
|
|
||||||
Remaining in this repo:
|
Remaining in this repo:
|
||||||
|
|
||||||
@ -63,3 +67,4 @@ Cross-repo dependencies (kernel/backend/contracts):
|
|||||||
4. Implement runtime entitlement gate and evidence receipts.
|
4. Implement runtime entitlement gate and evidence receipts.
|
||||||
5. Implement member app channel APIs and deterministic event stream storage.
|
5. Implement member app channel APIs and deterministic event stream storage.
|
||||||
6. Implement governance install token/confirm/status APIs and signed package delivery.
|
6. Implement governance install token/confirm/status APIs and signed package delivery.
|
||||||
|
7. Implement org-root boundary claims and access class state transitions in runtime/API responses.
|
||||||
|
|||||||
@ -41,6 +41,20 @@
|
|||||||
],
|
],
|
||||||
"pattern": "^[a-z0-9][a-z0-9._-]{2,127}$"
|
"pattern": "^[a-z0-9][a-z0-9._-]{2,127}$"
|
||||||
},
|
},
|
||||||
|
"org_root_id": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"pattern": "^[a-z0-9][a-z0-9._-]{2,127}$"
|
||||||
|
},
|
||||||
|
"principal_id": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"pattern": "^[a-z0-9][a-z0-9._-]{2,127}$"
|
||||||
|
},
|
||||||
"state": {
|
"state": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
@ -50,6 +64,30 @@
|
|||||||
"expired"
|
"expired"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"access_class": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"enum": [
|
||||||
|
"connected",
|
||||||
|
"sovereign",
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"availability_state": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"enum": [
|
||||||
|
"active",
|
||||||
|
"grace",
|
||||||
|
"continuity",
|
||||||
|
"parked",
|
||||||
|
null
|
||||||
|
]
|
||||||
|
},
|
||||||
"purchase": {
|
"purchase": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
|||||||
@ -9,7 +9,10 @@
|
|||||||
"price": "499.00",
|
"price": "499.00",
|
||||||
"currency": "USDC",
|
"currency": "USDC",
|
||||||
"member_only": true,
|
"member_only": true,
|
||||||
"workspace_bound": false
|
"workspace_bound": false,
|
||||||
|
"transferable": false,
|
||||||
|
"internal_use_only": true,
|
||||||
|
"multi_tenant": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"offer_id": "edut.crm.pro.annual",
|
"offer_id": "edut.crm.pro.annual",
|
||||||
@ -18,7 +21,10 @@
|
|||||||
"price": "199.00",
|
"price": "199.00",
|
||||||
"currency": "USDC",
|
"currency": "USDC",
|
||||||
"member_only": true,
|
"member_only": true,
|
||||||
"workspace_bound": true
|
"workspace_bound": true,
|
||||||
|
"transferable": false,
|
||||||
|
"internal_use_only": true,
|
||||||
|
"multi_tenant": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"offer_id": "edut.invoicing.core.annual",
|
"offer_id": "edut.invoicing.core.annual",
|
||||||
@ -27,7 +33,10 @@
|
|||||||
"price": "99.00",
|
"price": "99.00",
|
||||||
"currency": "USDC",
|
"currency": "USDC",
|
||||||
"member_only": true,
|
"member_only": true,
|
||||||
"workspace_bound": true
|
"workspace_bound": true,
|
||||||
|
"transferable": false,
|
||||||
|
"internal_use_only": true,
|
||||||
|
"multi_tenant": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"published_at": "2026-02-17T00:00:00Z"
|
"published_at": "2026-02-17T00:00:00Z"
|
||||||
|
|||||||
@ -15,6 +15,8 @@
|
|||||||
"member_only": true,
|
"member_only": true,
|
||||||
"workspace_bound": true,
|
"workspace_bound": true,
|
||||||
"transferable": false,
|
"transferable": false,
|
||||||
|
"internal_use_only": true,
|
||||||
|
"multi_tenant": false,
|
||||||
"max_per_wallet": 5,
|
"max_per_wallet": 5,
|
||||||
"requires_admin_approval": false
|
"requires_admin_approval": false
|
||||||
},
|
},
|
||||||
|
|||||||
@ -14,7 +14,17 @@
|
|||||||
"items": {
|
"items": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"required": ["offer_id", "title", "price", "currency", "member_only"],
|
"required": [
|
||||||
|
"offer_id",
|
||||||
|
"title",
|
||||||
|
"price",
|
||||||
|
"currency",
|
||||||
|
"member_only",
|
||||||
|
"workspace_bound",
|
||||||
|
"transferable",
|
||||||
|
"internal_use_only",
|
||||||
|
"multi_tenant"
|
||||||
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"offer_id": { "type": "string" },
|
"offer_id": { "type": "string" },
|
||||||
"title": { "type": "string" },
|
"title": { "type": "string" },
|
||||||
@ -22,7 +32,10 @@
|
|||||||
"price": { "type": "string" },
|
"price": { "type": "string" },
|
||||||
"currency": { "type": "string", "enum": ["USDC", "ETH"] },
|
"currency": { "type": "string", "enum": ["USDC", "ETH"] },
|
||||||
"member_only": { "type": "boolean" },
|
"member_only": { "type": "boolean" },
|
||||||
"workspace_bound": { "type": "boolean" }
|
"workspace_bound": { "type": "boolean" },
|
||||||
|
"transferable": { "type": "boolean" },
|
||||||
|
"internal_use_only": { "type": "boolean" },
|
||||||
|
"multi_tenant": { "type": "boolean" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -83,7 +83,9 @@
|
|||||||
"required": [
|
"required": [
|
||||||
"member_only",
|
"member_only",
|
||||||
"workspace_bound",
|
"workspace_bound",
|
||||||
"transferable"
|
"transferable",
|
||||||
|
"internal_use_only",
|
||||||
|
"multi_tenant"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"member_only": {
|
"member_only": {
|
||||||
@ -95,6 +97,12 @@
|
|||||||
"transferable": {
|
"transferable": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"internal_use_only": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"multi_tenant": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"max_per_wallet": {
|
"max_per_wallet": {
|
||||||
"type": [
|
"type": [
|
||||||
"integer",
|
"integer",
|
||||||
|
|||||||
@ -102,6 +102,8 @@ When launch activation opens, this record becomes the continuity bridge for depl
|
|||||||
2. Membership is not a product/module license.
|
2. Membership is not a product/module license.
|
||||||
3. Product rights are granted by separate entitlement purchases.
|
3. Product rights are granted by separate entitlement purchases.
|
||||||
4. The same wallet carries the full identity and entitlement chain.
|
4. The same wallet carries the full identity and entitlement chain.
|
||||||
|
5. Suite entitlements are bound to an org boundary (`org_root_id`), with unlimited internal workspaces under that boundary.
|
||||||
|
6. Human access classes (`connected`, `sovereign`) control renewal mechanics but share one deterministic availability state machine.
|
||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,8 @@ This model separates ownership rights from payment source for deterministic enti
|
|||||||
|
|
||||||
Entitlements are minted to `ownership_wallet` only.
|
Entitlements are minted to `ownership_wallet` only.
|
||||||
|
|
||||||
|
For workspace-bound paid rights, entitlement claims must also bind to `org_root_id`.
|
||||||
|
|
||||||
## Authorization Rule
|
## Authorization Rule
|
||||||
|
|
||||||
When payment wallet differs from ownership wallet, backend requires ownership-wallet authorization proof for quote/confirm binding.
|
When payment wallet differs from ownership wallet, backend requires ownership-wallet authorization proof for quote/confirm binding.
|
||||||
@ -26,11 +28,14 @@ When payment wallet differs from ownership wallet, backend requires ownership-wa
|
|||||||
|
|
||||||
Runtime activation checks ownership wallet entitlement state only.
|
Runtime activation checks ownership wallet entitlement state only.
|
||||||
|
|
||||||
|
For workspace-bound execution, runtime also checks boundary claim compatibility (`workspace.org_root_id` == `entitlement.org_root_id`).
|
||||||
|
|
||||||
## Why
|
## Why
|
||||||
|
|
||||||
1. Supports simple user funding options.
|
1. Supports simple user funding options.
|
||||||
2. Keeps entitlement ownership deterministic and auditable.
|
2. Keeps entitlement ownership deterministic and auditable.
|
||||||
3. Prevents accidental activation tied to transient funding wallets.
|
3. Prevents accidental activation tied to transient funding wallets.
|
||||||
|
4. Prevents cross-boundary reuse of a single entitlement across unrelated organizations.
|
||||||
|
|
||||||
## Non-Goals
|
## Non-Goals
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,9 @@
|
|||||||
"currency": "USDC",
|
"currency": "USDC",
|
||||||
"member_only": true,
|
"member_only": true,
|
||||||
"workspace_bound": false,
|
"workspace_bound": false,
|
||||||
"transferable": false
|
"transferable": false,
|
||||||
|
"internal_use_only": true,
|
||||||
|
"multi_tenant": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"offer_id": "edut.crm.pro.annual",
|
"offer_id": "edut.crm.pro.annual",
|
||||||
@ -19,7 +21,9 @@
|
|||||||
"currency": "USDC",
|
"currency": "USDC",
|
||||||
"member_only": true,
|
"member_only": true,
|
||||||
"workspace_bound": true,
|
"workspace_bound": true,
|
||||||
"transferable": false
|
"transferable": false,
|
||||||
|
"internal_use_only": true,
|
||||||
|
"multi_tenant": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"offer_id": "edut.invoicing.core.annual",
|
"offer_id": "edut.invoicing.core.annual",
|
||||||
@ -29,7 +33,9 @@
|
|||||||
"currency": "USDC",
|
"currency": "USDC",
|
||||||
"member_only": true,
|
"member_only": true,
|
||||||
"workspace_bound": true,
|
"workspace_bound": true,
|
||||||
"transferable": false
|
"transferable": false,
|
||||||
|
"internal_use_only": true,
|
||||||
|
"multi_tenant": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -167,6 +167,15 @@
|
|||||||
<h2>Products, Licensing, and Availability</h2>
|
<h2>Products, Licensing, and Availability</h2>
|
||||||
<p>Edut may offer software licenses, modules, deployment services, and related tools. Descriptions, availability, and requirements may change without notice. Additional product-specific terms may apply at purchase or activation time and, in case of conflict, those specific terms control for that product.</p>
|
<p>Edut may offer software licenses, modules, deployment services, and related tools. Descriptions, availability, and requirements may change without notice. Additional product-specific terms may apply at purchase or activation time and, in case of conflict, those specific terms control for that product.</p>
|
||||||
|
|
||||||
|
<h2>License Scope and Boundary</h2>
|
||||||
|
<p>Unless explicitly stated otherwise in writing, product licenses grant internal-use rights within the licensed organization boundary and do not grant sublicensing, resale, service-bureau, or redistribution rights. A license purchased for one organization boundary does not automatically authorize paid execution in a separate organization boundary.</p>
|
||||||
|
|
||||||
|
<h2>Availability Classes and Continuity States</h2>
|
||||||
|
<p>Edut may apply deterministic availability classes to licensed operation (for example connected and sovereign classes) and may enforce staged continuity states when renewal evidence is missing. In continuity states, Edut may pause expansion actions (such as adding members or installing new paid tools) before pausing paid execution. Data visibility and export pathways may remain available even when paid execution is paused.</p>
|
||||||
|
|
||||||
|
<h2>Administrative Control and Support Access</h2>
|
||||||
|
<p>Administrative controls for an organization boundary (including health diagnostics, update controls, and configuration changes) may be restricted to the verified organization root owner role. Workspace member roles may be limited to daily-use capabilities and may be required to contact their organization administrator for admin-level requests. Edut may provide direct support channels only to verified organization root owners for boundary-scoped issues.</p>
|
||||||
|
|
||||||
<h2>Payments</h2>
|
<h2>Payments</h2>
|
||||||
<p>Where paid offerings are available, you agree to pay applicable charges at checkout. Accepted payment methods may vary by offering. Unless required by law or stated otherwise in writing, fees are non-refundable.</p>
|
<p>Where paid offerings are available, you agree to pay applicable charges at checkout. Accepted payment methods may vary by offering. Unless required by law or stated otherwise in writing, fees are non-refundable.</p>
|
||||||
<p>For first-time purchases, EDUT may bundle membership activation with a license purchase in a single checkout total. When bundled, checkout displays the line-item composition (for example, membership activation plus license component) before transaction confirmation.</p>
|
<p>For first-time purchases, EDUT may bundle membership activation with a license purchase in a single checkout total. When bundled, checkout displays the line-item composition (for example, membership activation plus license component) before transaction confirmation.</p>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user