Add deterministic member app channel API and conformance docs
This commit is contained in:
parent
2e8348826f
commit
afe14c33d6
@ -55,6 +55,7 @@ docs/
|
|||||||
membership-platform-interfaces.md
|
membership-platform-interfaces.md
|
||||||
conformance/
|
conformance/
|
||||||
membership-gating-vectors.md
|
membership-gating-vectors.md
|
||||||
|
member-channel-vectors.md
|
||||||
deployment/
|
deployment/
|
||||||
README.md
|
README.md
|
||||||
chain-config.template.json
|
chain-config.template.json
|
||||||
@ -63,12 +64,15 @@ docs/
|
|||||||
api/
|
api/
|
||||||
secret-system.openapi.yaml
|
secret-system.openapi.yaml
|
||||||
marketplace.openapi.yaml
|
marketplace.openapi.yaml
|
||||||
|
member-channel.openapi.yaml
|
||||||
examples/
|
examples/
|
||||||
secret-system.examples.md
|
secret-system.examples.md
|
||||||
marketplace.examples.md
|
marketplace.examples.md
|
||||||
|
member-channel.examples.md
|
||||||
handoff/
|
handoff/
|
||||||
membership-backend-checklist.md
|
membership-backend-checklist.md
|
||||||
marketplace-backend-checklist.md
|
marketplace-backend-checklist.md
|
||||||
|
member-channel-backend-checklist.md
|
||||||
schemas/
|
schemas/
|
||||||
offer.v1.schema.json
|
offer.v1.schema.json
|
||||||
entitlement.v1.schema.json
|
entitlement.v1.schema.json
|
||||||
|
|||||||
103
docs/api/examples/member-channel.examples.md
Normal file
103
docs/api/examples/member-channel.examples.md
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
# Member App Channel API Examples
|
||||||
|
|
||||||
|
## Register Device Channel
|
||||||
|
|
||||||
|
### Request
|
||||||
|
|
||||||
|
```http
|
||||||
|
POST /member/channel/device/register
|
||||||
|
Authorization: Bearer <wallet-session>
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"wallet": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
|
||||||
|
"chain_id": 8453,
|
||||||
|
"device_id": "desktop-7f6f3a9b",
|
||||||
|
"platform": "desktop",
|
||||||
|
"app_version": "0.1.0",
|
||||||
|
"push_provider": "none"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Response
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"channel_binding_id": "ch_01J9A4MQQ6V7H1S0A7R7ME7D4J",
|
||||||
|
"status": "active",
|
||||||
|
"poll_interval_seconds": 30,
|
||||||
|
"server_time": "2026-02-17T20:43:18Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Poll Events
|
||||||
|
|
||||||
|
### Request
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /member/channel/events?wallet=0x742d35Cc6634C0532925a3b844Bc454e4438f44e&device_id=desktop-7f6f3a9b&cursor=evt_1030&limit=25
|
||||||
|
Authorization: Bearer <wallet-session>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Response
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"wallet": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
|
||||||
|
"device_id": "desktop-7f6f3a9b",
|
||||||
|
"events": [
|
||||||
|
{
|
||||||
|
"event_id": "evt_1031",
|
||||||
|
"class": "platform_update",
|
||||||
|
"created_at": "2026-02-17T20:42:11Z",
|
||||||
|
"title": "Platform update available",
|
||||||
|
"body": "A deterministic runtime update is ready for your current platform channel.",
|
||||||
|
"dedupe_key": "platform_update:0.1.1",
|
||||||
|
"requires_ack": true,
|
||||||
|
"policy_hash": "sha256:8b903f0d3a...",
|
||||||
|
"payload": {
|
||||||
|
"version": "0.1.1",
|
||||||
|
"channel": "stable"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"next_cursor": "evt_1031",
|
||||||
|
"server_time": "2026-02-17T20:43:20Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Acknowledge Event
|
||||||
|
|
||||||
|
### Request
|
||||||
|
|
||||||
|
```http
|
||||||
|
POST /member/channel/events/evt_1031/ack
|
||||||
|
Authorization: Bearer <wallet-session>
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"wallet": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
|
||||||
|
"device_id": "desktop-7f6f3a9b",
|
||||||
|
"acknowledged_at": "2026-02-17T20:43:25Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Response
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "acknowledged",
|
||||||
|
"event_id": "evt_1031",
|
||||||
|
"acknowledged_at": "2026-02-17T20:43:25Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Membership Inactive Error
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": "membership_inactive",
|
||||||
|
"code": "membership_inactive",
|
||||||
|
"correlation_id": "req_01J9A4Q9GPDXDNZEWJ2FJS6F5R"
|
||||||
|
}
|
||||||
|
```
|
||||||
311
docs/api/member-channel.openapi.yaml
Normal file
311
docs/api/member-channel.openapi.yaml
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
openapi: 3.1.0
|
||||||
|
info:
|
||||||
|
title: EDUT Member App Channel API
|
||||||
|
version: 1.0.0
|
||||||
|
description: |
|
||||||
|
Deterministic member communication channel contract.
|
||||||
|
App notifications are derived from wallet-authenticated membership and entitlement state.
|
||||||
|
servers:
|
||||||
|
- url: https://api.edut.ai
|
||||||
|
security:
|
||||||
|
- WalletSession: []
|
||||||
|
paths:
|
||||||
|
/member/channel/device/register:
|
||||||
|
post:
|
||||||
|
summary: Register or refresh a member app device channel binding.
|
||||||
|
operationId: registerMemberDevice
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/DeviceRegisterRequest'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Device channel binding active.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/DeviceRegisterResponse'
|
||||||
|
'403':
|
||||||
|
description: Membership is not active for this wallet.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ErrorResponse'
|
||||||
|
/member/channel/device/unregister:
|
||||||
|
post:
|
||||||
|
summary: Remove a device channel binding.
|
||||||
|
operationId: unregisterMemberDevice
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/DeviceUnregisterRequest'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Device channel binding removed.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/DeviceUnregisterResponse'
|
||||||
|
'404':
|
||||||
|
description: Device channel binding not found.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ErrorResponse'
|
||||||
|
/member/channel/events:
|
||||||
|
get:
|
||||||
|
summary: Poll deterministic member channel events.
|
||||||
|
operationId: listMemberChannelEvents
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: wallet
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: Wallet address tied to session.
|
||||||
|
- in: query
|
||||||
|
name: device_id
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: cursor
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: limit
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
minimum: 1
|
||||||
|
maximum: 100
|
||||||
|
default: 25
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Event page for in-app inbox rendering.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/EventListResponse'
|
||||||
|
'403':
|
||||||
|
description: Membership inactive or suspended.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ErrorResponse'
|
||||||
|
/member/channel/events/{event_id}/ack:
|
||||||
|
post:
|
||||||
|
summary: Acknowledge event delivery/read state.
|
||||||
|
operationId: acknowledgeMemberChannelEvent
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: event_id
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
requestBody:
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/EventAckRequest'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Event acknowledged.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/EventAckResponse'
|
||||||
|
'404':
|
||||||
|
description: Event not found.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ErrorResponse'
|
||||||
|
components:
|
||||||
|
securitySchemes:
|
||||||
|
WalletSession:
|
||||||
|
type: http
|
||||||
|
scheme: bearer
|
||||||
|
bearerFormat: EDUT-WALLET-SESSION
|
||||||
|
schemas:
|
||||||
|
DeviceRegisterRequest:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- wallet
|
||||||
|
- chain_id
|
||||||
|
- device_id
|
||||||
|
- platform
|
||||||
|
- app_version
|
||||||
|
properties:
|
||||||
|
wallet:
|
||||||
|
type: string
|
||||||
|
description: Hex wallet address.
|
||||||
|
chain_id:
|
||||||
|
type: integer
|
||||||
|
description: Active chain id in app session.
|
||||||
|
device_id:
|
||||||
|
type: string
|
||||||
|
description: Stable app-install identifier.
|
||||||
|
platform:
|
||||||
|
type: string
|
||||||
|
enum: [ios, android, desktop]
|
||||||
|
app_version:
|
||||||
|
type: string
|
||||||
|
push_provider:
|
||||||
|
type: string
|
||||||
|
enum: [apns, fcm, webpush, none]
|
||||||
|
default: none
|
||||||
|
push_token:
|
||||||
|
type: string
|
||||||
|
description: Provider token if push is enabled.
|
||||||
|
DeviceRegisterResponse:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- channel_binding_id
|
||||||
|
- status
|
||||||
|
- poll_interval_seconds
|
||||||
|
- server_time
|
||||||
|
properties:
|
||||||
|
channel_binding_id:
|
||||||
|
type: string
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
enum: [active]
|
||||||
|
poll_interval_seconds:
|
||||||
|
type: integer
|
||||||
|
minimum: 10
|
||||||
|
server_time:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
DeviceUnregisterRequest:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- wallet
|
||||||
|
- device_id
|
||||||
|
properties:
|
||||||
|
wallet:
|
||||||
|
type: string
|
||||||
|
device_id:
|
||||||
|
type: string
|
||||||
|
DeviceUnregisterResponse:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- status
|
||||||
|
- wallet
|
||||||
|
- device_id
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
enum: [removed]
|
||||||
|
wallet:
|
||||||
|
type: string
|
||||||
|
device_id:
|
||||||
|
type: string
|
||||||
|
EventListResponse:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- wallet
|
||||||
|
- device_id
|
||||||
|
- events
|
||||||
|
- next_cursor
|
||||||
|
- server_time
|
||||||
|
properties:
|
||||||
|
wallet:
|
||||||
|
type: string
|
||||||
|
device_id:
|
||||||
|
type: string
|
||||||
|
events:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/MemberEvent'
|
||||||
|
next_cursor:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
server_time:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
MemberEvent:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- event_id
|
||||||
|
- class
|
||||||
|
- created_at
|
||||||
|
- title
|
||||||
|
- body
|
||||||
|
- dedupe_key
|
||||||
|
- policy_hash
|
||||||
|
properties:
|
||||||
|
event_id:
|
||||||
|
type: string
|
||||||
|
class:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- offer_available
|
||||||
|
- entitlement_activated
|
||||||
|
- platform_update
|
||||||
|
- publisher_update
|
||||||
|
- membership_policy
|
||||||
|
created_at:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
|
body:
|
||||||
|
type: string
|
||||||
|
dedupe_key:
|
||||||
|
type: string
|
||||||
|
requires_ack:
|
||||||
|
type: boolean
|
||||||
|
default: true
|
||||||
|
policy_hash:
|
||||||
|
type: string
|
||||||
|
payload:
|
||||||
|
type: object
|
||||||
|
additionalProperties: true
|
||||||
|
EventAckRequest:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- wallet
|
||||||
|
- device_id
|
||||||
|
- acknowledged_at
|
||||||
|
properties:
|
||||||
|
wallet:
|
||||||
|
type: string
|
||||||
|
device_id:
|
||||||
|
type: string
|
||||||
|
acknowledged_at:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
EventAckResponse:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- status
|
||||||
|
- event_id
|
||||||
|
- acknowledged_at
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
enum: [acknowledged]
|
||||||
|
event_id:
|
||||||
|
type: string
|
||||||
|
acknowledged_at:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
ErrorResponse:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- error
|
||||||
|
- code
|
||||||
|
properties:
|
||||||
|
error:
|
||||||
|
type: string
|
||||||
|
code:
|
||||||
|
type: string
|
||||||
|
correlation_id:
|
||||||
|
type: string
|
||||||
@ -35,6 +35,14 @@ No active membership -> no app access channel.
|
|||||||
2. Delivery payloads must include deterministic event ids for dedupe and audit.
|
2. Delivery payloads must include deterministic event ids for dedupe and audit.
|
||||||
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.
|
||||||
|
|
||||||
|
## Contract References
|
||||||
|
|
||||||
|
1. `docs/api/member-channel.openapi.yaml`
|
||||||
|
2. `docs/api/examples/member-channel.examples.md`
|
||||||
|
3. `docs/handoff/member-channel-backend-checklist.md`
|
||||||
|
4. `docs/conformance/member-channel-vectors.md`
|
||||||
|
|
||||||
## Non-Goals
|
## Non-Goals
|
||||||
|
|
||||||
|
|||||||
22
docs/conformance/member-channel-vectors.md
Normal file
22
docs/conformance/member-channel-vectors.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Conformance Vectors: Member App Channel v1
|
||||||
|
|
||||||
|
These vectors verify deterministic member communication behavior.
|
||||||
|
|
||||||
|
## Vector Set
|
||||||
|
|
||||||
|
1. `MC-001` Register device with active membership -> returns `status=active`.
|
||||||
|
2. `MC-002` Register device with inactive membership -> returns `membership_inactive`.
|
||||||
|
3. `MC-003` Poll events with valid cursor -> returns monotonic events + next cursor.
|
||||||
|
4. `MC-004` Poll events with tampered cursor -> fail closed with validation error.
|
||||||
|
5. `MC-005` Ack existing event -> returns `status=acknowledged`.
|
||||||
|
6. `MC-006` Ack same event again -> idempotent success, no duplicate side effects.
|
||||||
|
7. `MC-007` Membership revoked after registration -> subsequent event poll blocked.
|
||||||
|
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.
|
||||||
|
10. `MC-010` Wallet mismatch between session and payload -> request rejected.
|
||||||
|
|
||||||
|
## Pass Criteria
|
||||||
|
|
||||||
|
1. All vectors pass in CI and staging.
|
||||||
|
2. Any failure blocks release per `docs/release-gate.md`.
|
||||||
|
3. Evidence artifact includes vector id, input, output, and correlation id.
|
||||||
53
docs/handoff/member-channel-backend-checklist.md
Normal file
53
docs/handoff/member-channel-backend-checklist.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# Backend Handoff Checklist: Member App Channel
|
||||||
|
|
||||||
|
This checklist defines backend requirements for app-native member communication.
|
||||||
|
|
||||||
|
## Required Endpoints
|
||||||
|
|
||||||
|
1. `POST /member/channel/device/register`
|
||||||
|
2. `POST /member/channel/device/unregister`
|
||||||
|
3. `GET /member/channel/events`
|
||||||
|
4. `POST /member/channel/events/{event_id}/ack`
|
||||||
|
|
||||||
|
## Contract Source
|
||||||
|
|
||||||
|
1. `docs/api/member-channel.openapi.yaml`
|
||||||
|
2. `docs/api/examples/member-channel.examples.md`
|
||||||
|
|
||||||
|
## Deterministic Rules
|
||||||
|
|
||||||
|
1. Wallet session is mandatory for all channel calls.
|
||||||
|
2. Membership status must be active for event delivery.
|
||||||
|
3. Event ids and dedupe keys are immutable once emitted.
|
||||||
|
4. Event ordering is monotonic by server sequence.
|
||||||
|
5. `ack` is idempotent per `event_id` + `device_id`.
|
||||||
|
|
||||||
|
## Data Requirements
|
||||||
|
|
||||||
|
Persist at minimum:
|
||||||
|
|
||||||
|
1. Device channel binding (`wallet`, `device_id`, `platform`, `push_provider`, `push_token`)
|
||||||
|
2. Membership status snapshot at event emission time
|
||||||
|
3. Event envelope (`event_id`, class, title/body, payload, policy_hash, dedupe_key)
|
||||||
|
4. Delivery and ack timestamps
|
||||||
|
|
||||||
|
## Security Requirements
|
||||||
|
|
||||||
|
1. Rate limit register/events/ack paths.
|
||||||
|
2. Validate wallet in request matches authenticated session wallet.
|
||||||
|
3. Reject event polling for suspended/revoked memberships.
|
||||||
|
4. Protect against cursor tampering and replay.
|
||||||
|
|
||||||
|
## Observability Requirements
|
||||||
|
|
||||||
|
1. Counter metrics per event class emitted.
|
||||||
|
2. Counter metrics for successful/failed ack calls.
|
||||||
|
3. Channel registration churn metrics by platform.
|
||||||
|
4. Correlation id in all responses and logs.
|
||||||
|
|
||||||
|
## Done Criteria
|
||||||
|
|
||||||
|
1. App can register channel and poll events deterministically.
|
||||||
|
2. Push loss does not lose events because inbox polling is canonical.
|
||||||
|
3. Membership status changes immediately gate event visibility.
|
||||||
|
4. API behavior matches OpenAPI contract and examples.
|
||||||
@ -11,6 +11,7 @@
|
|||||||
1. Intent/verify/quote/confirm/status endpoints.
|
1. Intent/verify/quote/confirm/status endpoints.
|
||||||
2. Deterministic state transitions and persistence.
|
2. Deterministic state transitions and persistence.
|
||||||
3. Chain verification and policy hash enforcement.
|
3. Chain verification and policy hash enforcement.
|
||||||
|
4. Member app channel endpoints for device registration and event polling.
|
||||||
|
|
||||||
## Runtime/Kernel Responsibilities
|
## Runtime/Kernel Responsibilities
|
||||||
|
|
||||||
|
|||||||
@ -13,21 +13,24 @@ This gate controls deploy/no-deploy decisions for membership-gated commerce chan
|
|||||||
## Deploy Criteria (All Required)
|
## Deploy Criteria (All Required)
|
||||||
|
|
||||||
1. `docs/conformance/membership-gating-vectors.md`: all vectors pass.
|
1. `docs/conformance/membership-gating-vectors.md`: all vectors pass.
|
||||||
2. OpenAPI and implementation remain compatible.
|
2. `docs/conformance/member-channel-vectors.md`: all vectors pass.
|
||||||
3. Signature replay tests pass.
|
3. OpenAPI and implementation remain compatible.
|
||||||
4. Quote expiry tests pass.
|
4. Signature replay tests pass.
|
||||||
5. Tx mismatch tests pass.
|
5. Quote expiry tests pass.
|
||||||
6. Membership gate blocks non-members in all checkout paths.
|
6. Tx mismatch tests pass.
|
||||||
7. Terms/privacy copy still match utility-access framing.
|
7. Membership gate blocks non-members in all checkout paths.
|
||||||
8. Structured logs and metrics are emitted for each state transition.
|
8. Member channel blocks inactive memberships.
|
||||||
|
9. Terms/privacy copy still match utility-access framing.
|
||||||
|
10. Structured logs and metrics are emitted for each state transition.
|
||||||
|
|
||||||
## No-Deploy Triggers
|
## No-Deploy Triggers
|
||||||
|
|
||||||
1. Any conformance vector failure.
|
1. Any conformance vector failure.
|
||||||
2. Any path that allows purchase without active membership.
|
2. Any path that allows purchase without active membership.
|
||||||
3. Any activation path that proceeds with non-active entitlement.
|
3. Any activation path that proceeds with non-active entitlement.
|
||||||
4. Any missing audit evidence on successful purchase.
|
4. Any member channel path serving events to suspended/revoked memberships.
|
||||||
5. Any breaking API change without version bump and migration note.
|
5. Any missing audit evidence on successful purchase.
|
||||||
|
6. Any breaking API change without version bump and migration note.
|
||||||
|
|
||||||
## Evidence Bundle Required for Release
|
## Evidence Bundle Required for Release
|
||||||
|
|
||||||
|
|||||||
@ -89,3 +89,10 @@ This roadmap is intentionally step-based and dependency-ordered. No timeline com
|
|||||||
- visit -> signature -> membership mint -> first entitlement purchase.
|
- visit -> signature -> membership mint -> first entitlement purchase.
|
||||||
2. Tune copy, wallet guidance, and pricing policy using deterministic metrics.
|
2. Tune copy, wallet guidance, and pricing policy using deterministic metrics.
|
||||||
3. Expand issuer ecosystem only after quality and support controls are stable.
|
3. Expand issuer ecosystem only after quality and support controls are stable.
|
||||||
|
|
||||||
|
## Step 14: Lock Member App Channel
|
||||||
|
|
||||||
|
1. Register device channels with wallet-authenticated session.
|
||||||
|
2. Deliver deterministic event inbox (polling canonical, push optional).
|
||||||
|
3. Gate event visibility by active membership status.
|
||||||
|
4. Track ack receipts with immutable event ids and dedupe keys.
|
||||||
|
|||||||
@ -40,6 +40,7 @@ Implemented now:
|
|||||||
13. Issuer onboarding pack, migration policy, trust page spec, and integration mapping docs.
|
13. Issuer onboarding pack, migration policy, trust page spec, and integration mapping docs.
|
||||||
14. Public `/trust` page scaffold aligned with trust-page spec.
|
14. Public `/trust` page scaffold aligned with trust-page spec.
|
||||||
15. Dedicated marketplace OpenAPI contract and examples.
|
15. Dedicated marketplace OpenAPI contract and examples.
|
||||||
|
16. Member app channel contract, examples, backend handoff checklist, and conformance vectors.
|
||||||
|
|
||||||
Remaining in this repo:
|
Remaining in this repo:
|
||||||
|
|
||||||
@ -52,3 +53,4 @@ Cross-repo dependencies (kernel/backend/contracts):
|
|||||||
2. Implement membership contract and membership status reads.
|
2. Implement membership contract and membership status reads.
|
||||||
3. Implement checkout APIs and entitlement mint pipeline.
|
3. Implement checkout APIs and entitlement mint pipeline.
|
||||||
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.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user