@hyodotdev/openiap-commerce-protocol 0.0.0-bootstrap.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CONVENTION.md +168 -0
  2. package/DESIGN.md +1056 -0
  3. package/README.md +227 -5
  4. package/SPEC.md +1471 -0
  5. package/conformance/index.d.ts +303 -0
  6. package/conformance/index.mjs +2126 -0
  7. package/conformance/mock-provider.mjs +491 -0
  8. package/examples/entitlement-granted-no-subscription.json +12 -0
  9. package/examples/entitlement-revoked.json +21 -0
  10. package/examples/provider-capabilities.json +209 -0
  11. package/examples/store-event-mapping.json +287 -0
  12. package/examples/subscription-canceled.json +22 -0
  13. package/examples/subscription-product-changed.json +30 -0
  14. package/examples/subscription-renewed.json +29 -0
  15. package/examples/verify-purchase-request.json +6 -0
  16. package/examples/verify-purchase-result.json +7 -0
  17. package/generated/bindings/graphql-operations.json +87 -0
  18. package/generated/bindings/http-binding.json +143 -0
  19. package/generated/bindings/introspection-signature.json +320 -0
  20. package/generated/bindings/operations-sdl.json +4 -0
  21. package/generated/bindings/operations.graphql +366 -0
  22. package/generated/commerce-protocol.graphql +1219 -0
  23. package/generated/openapi/commerce-protocol.openapi.json +1413 -0
  24. package/generated/schemas/commerce-event.schema.json +499 -0
  25. package/generated/schemas/commerce-protocol.bundle.schema.json +1576 -0
  26. package/generated/schemas/operations.schema.json +578 -0
  27. package/generated/schemas/primitives.schema.json +101 -0
  28. package/generated/schemas/provider-capabilities.schema.json +205 -0
  29. package/generated/schemas/store-event-mapping.schema.json +211 -0
  30. package/generated/vectors/lifecycle.json +908 -0
  31. package/generated/vectors/operations.json +1122 -0
  32. package/package.json +62 -12
  33. package/schema/01-primitives.graphql +102 -0
  34. package/schema/02-commerce-event.graphql +195 -0
  35. package/schema/03-provider-capabilities.graphql +139 -0
  36. package/schema/04-store-event-mapping.graphql +98 -0
  37. package/schema/05-operations.graphql +461 -0
  38. package/schema/06-compiler-vocabulary.graphql +139 -0
  39. package/schema/07-protocol-metadata.graphql +76 -0
  40. package/src/index.d.ts +63 -0
  41. package/src/index.mjs +121 -0
  42. package/vectors/signatures.json +139 -0
package/README.md CHANGED
@@ -1,8 +1,230 @@
1
- # @hyodotdev/openiap-commerce-protocol
1
+ # OpenIAP Commerce Protocol
2
2
 
3
- This package registers the official npm name for the OpenIAP Commerce Protocol.
3
+ [![npm](https://img.shields.io/npm/v/@hyodotdev/openiap-commerce-protocol/latest)](https://www.npmjs.com/package/@hyodotdev/openiap-commerce-protocol)
4
4
 
5
- Version `0.0.0-bootstrap.0` contains package metadata only. It does not include
6
- a usable implementation. Functional releases will be published separately.
5
+ A vendor-neutral specification for the **server side** of in-app purchases.
7
6
 
8
- [Project source](https://github.com/hyodotdev/openiap/tree/main/specs/commerce-protocol) · [Documentation](https://openiap.dev)
7
+ OpenIAP normalizes the client-side purchase API across stores. This normalizes
8
+ the server side: one commerce vocabulary, one portable operation surface with
9
+ REST and GraphQL bindings, one event envelope, one webhook contract — so a
10
+ backend or an analytics pipeline can verify purchases, read entitlements, and
11
+ handle renewals, refunds, and entitlement changes from Apple, Google, Meta
12
+ Horizon, and Amazon without parsing any store-native payload, and can replace
13
+ the provider behind those calls without rewriting the integration.
14
+
15
+ Nothing in this contract routes through infrastructure the OpenIAP project
16
+ operates. Two parties exchange events directly, using a secret they share
17
+ between themselves, and validate offline. The project distributes the contract;
18
+ it does not sit in the path of anyone's commerce.
19
+
20
+ **[Read the specification →](./SPEC.md)**
21
+
22
+ ## Choose your role
23
+
24
+ A paywall specialist can supply the experience, a commerce service the purchase
25
+ and access decisions, and an analytics platform the event processing. An
26
+ integrated platform can supply several roles. Explore the [role map](https://openiap.dev/commerce-protocol#architecture)
27
+ and [AI integration brief](https://openiap.dev/commerce-example/integration-brief.md)
28
+ to connect your product to apps using OpenIAP. These product roles do not add
29
+ protocol profiles or a universal paywall API.
30
+
31
+ ## Start implementing
32
+
33
+ ```sh
34
+ npm install @hyodotdev/openiap-commerce-protocol
35
+ ```
36
+
37
+ Or use `pnpm add`, `yarn add`, or `bun add` with the same package name.
38
+
39
+ Give your AI the installed package's `SPEC.md`, `DESIGN.md`, and `generated/`
40
+ artifacts. The package supplies the contract; your AI implements the backend.
41
+
42
+ - **See what AI built:** the [recorded walkthrough](https://openiap.dev/commerce-protocol#build-walkthrough)
43
+ shows a real local HTTP + SQLite backend in six milestones, with captured
44
+ responses. The [IAPKit comparison](https://openiap.dev/commerce-protocol/implementation#iapkit) explains what was tested. Give the
45
+ [build brief](https://openiap.dev/commerce-example/build-brief.md)
46
+ to your AI to build the same flow in your own stack.
47
+ - **Integrate your backend:** [Use a provider](https://openiap.dev/commerce-protocol/getting-started)
48
+ walks through discovery, verification, account binding, and entitlement reads.
49
+ - **Build a provider:** [Build with AI](https://openiap.dev/commerce-protocol/implementation)
50
+ provides the brief, runnable example, and next implementation steps.
51
+ [DESIGN.md §5](./DESIGN.md#5-implementation-blueprint) contains the architecture
52
+ blueprint, storage keys, transaction boundaries, and recovery design.
53
+ - **Try the contract locally:** from the repository root, run `bun install`,
54
+ then `cd specs/commerce-protocol && bun run quickstart`. The
55
+ [development walkthrough](https://github.com/hyodotdev/openiap/blob/main/specs/commerce-protocol/scripts/quickstart.mjs) uses the in-memory mock,
56
+ checks authorization and binding behavior, and runs REST/GraphQL conformance.
57
+ It uses fixture evidence, opens no HTTP server, and does not validate real
58
+ store purchases. Its Ajv and GraphQL dependencies come from this package's
59
+ development setup.
60
+
61
+ [DESIGN.md](./DESIGN.md) explains why the boundaries sit where they do. It is
62
+ background, not normative: where the two disagree, `SPEC.md` is right. It is
63
+ also published as a PDF at
64
+ <https://www.openiap.dev/commerce-protocol-rationale.pdf>.
65
+
66
+ The contract sits between the stores and everything downstream of a backend:
67
+
68
+ ```mermaid
69
+ flowchart TB
70
+ stores["Apple / Google / Meta / Amazon<br/>the stores"]
71
+ backend["A backend that implements this spec<br/>IAPKit, another provider, or the adopter's own — in any language<br/><br/>verify → normalize → lifecycle → entitle"]
72
+ app["shipped application<br/>verification role (§5)"]
73
+ server["the adopter's backend<br/>server role (§5)"]
74
+ consumers["any consumer<br/>data pipeline / CRM / analytics"]
75
+
76
+ stores -->|"store-native notifications and APIs"| backend
77
+ app -->|"verifyPurchase, providerCapabilities (§4.1, §4.6)<br/>over REST (§6) or GraphQL (§7)"| backend
78
+ server -->|"those, plus subscriptionStatus, entitlements, bindPurchase, eraseUser (§4.2–§4.5)<br/>server role only — never a shipped app"| backend
79
+ backend -->|"OpenIAP Commerce Protocol events (§9)"| consumers
80
+ ```
81
+
82
+ ## Reviewing a change
83
+
84
+ Review only the authored surfaces, in this order:
85
+
86
+ 1. [`SPEC.md`](./SPEC.md) — behavior, operations, bindings, lifecycle,
87
+ transport, and compatibility.
88
+ 2. [`schema/`](./schema/) — the authored contract layers: wire structure, the
89
+ operation surface, and validation directives.
90
+ [`generated/commerce-protocol.graphql`](./generated/commerce-protocol.graphql)
91
+ is their generated single-file assembly (also exported at the package path
92
+ `@hyodotdev/openiap-commerce-protocol/commerce-protocol.graphql`).
93
+ 3. [`examples/`](./examples/) — representative documents and store mappings.
94
+ 4. [`vectors/signatures.json`](./vectors/signatures.json) — hand-authored
95
+ cryptographic truth cases.
96
+ 5. [`conformance/`](./conformance/) — the portable runner and its independent
97
+ mock provider.
98
+
99
+ Ignore `generated/` during a human review. It is compiler output, kept only for
100
+ validators and drift checks.
101
+
102
+ ## What ships here
103
+
104
+ | Path | Contents |
105
+ | ------------------------- | --------------------------------------------------------------------------- |
106
+ | `schema/` | Authored type, operation, and validation contract layers — edit these |
107
+ | `SPEC.md` | Normative meaning, operations, bindings, transport, and compatibility rules |
108
+ | `DESIGN.md` | Why the boundaries sit where they do — background, never normative |
109
+ | `generated/` | Compiler output: schemas, binding manifests, OpenAPI, and vectors |
110
+ | `examples/` | Canonical documents that must validate |
111
+ | `vectors/signatures.json` | Signature vectors every implementation must reproduce |
112
+ | `conformance/` | Portable conformance runner plus an IAPKit-free mock provider |
113
+ | `src/index.mjs` | Runtime access to the generated schemas and their derived constants |
114
+
115
+ The `schema/` layers govern wire structure. Their custom directives retain
116
+ patterns, bounds, maps, open objects, and conditional rules that standard SDL
117
+ cannot express. `bun run build` compiles that source into the JSON Schemas a Go,
118
+ Python, or other backend executes against incoming webhook bodies. `SPEC.md`
119
+ governs meaning and transport.
120
+
121
+ Do not add this SDL to `specs/client/schema-files.mjs`. `specs/client` owns the
122
+ client purchase API and the SDK types compiled from it; this file independently
123
+ owns the server-to-server commerce contract. Its Query and Mutation types are
124
+ the portable server operation surface — compiled into the REST and GraphQL
125
+ bindings, never into client SDK types — and it defines no Subscription root:
126
+ the operation surface is bounded request/response by rule.
127
+
128
+ ## Receiving events
129
+
130
+ An endpoint you register receives one JSON event per request. Verify the
131
+ signature — `SPEC.md` §9.4.2 states the rule and `vectors/signatures.json` pins
132
+ it — then handle the event; `SPEC.md` §9.5 walks a consumer end to end.
133
+
134
+ Three rules that are easy to get wrong, all specified in detail in `SPEC.md`:
135
+
136
+ - **Sign the bytes you received.** Re-serializing the JSON before verifying
137
+ changes key order and whitespace, and the signature will not match.
138
+ - **Read `subscription.active`, not `state`.** A canceled subscription keeps
139
+ access until its paid period ends — `subscription.canceled` means auto-renew
140
+ was turned off, not that access was revoked.
141
+ - **A missing amount means unknown.** It never means zero.
142
+
143
+ ## Calling a provider
144
+
145
+ Start with the provider's capability descriptor. Every conforming provider
146
+ supports discovery; its declared profiles determine which purchase, status,
147
+ entitlement, binding, and erasure operations it supports. Check those profiles
148
+ before calling an operation. REST and GraphQL bindings share one error-code
149
+ space. `SPEC.md` §4–§8 define the surface and authorization rules.
150
+
151
+ ## Certifying a provider
152
+
153
+ ```js
154
+ import Ajv from "ajv/dist/2020.js";
155
+ import {
156
+ createRestAdapter,
157
+ createGraphqlAdapter,
158
+ runConformance,
159
+ } from "@hyodotdev/openiap-commerce-protocol/conformance";
160
+
161
+ const report = await runConformance({
162
+ adapters: [
163
+ createRestAdapter({ baseUrl, fetch, credentials }),
164
+ createGraphqlAdapter({ url: graphqlUrl, fetch, credentials }),
165
+ ],
166
+ Ajv,
167
+ // The same role-to-credential map the adapters use — required, so the
168
+ // runner can reject an error message that echoes a credential.
169
+ credentials,
170
+ // Required when your capability descriptor declares the events profile:
171
+ // your outbound webhook implementation, driven through SPEC.md §9's
172
+ // signing, verification, delivery, response, entitlement, and emission
173
+ // vectors.
174
+ eventsAdapter,
175
+ });
176
+ ```
177
+
178
+ The runner is offline, needs no hosted service, and imports no implementation;
179
+ supply the Ajv 2020 class yourself, since the published runtime carries zero
180
+ dependencies. It certifies the transport contract — never real store receipt
181
+ validity (`SPEC.md` §11.3). A provider that declares the `events` profile must
182
+ also pass an `eventsAdapter` covering the full `EventsAdapter` surface
183
+ (`conformance/index.d.ts`); a signing-only adapter fails.
184
+
185
+ ## Validating
186
+
187
+ ```bash
188
+ bun install
189
+ bun run test
190
+ ```
191
+
192
+ The suite recompiles every schema and binding artifact, validates every
193
+ example, checks that each rejection case is actually rejected, reproduces
194
+ every signature vector using an implementation written only from `SPEC.md`,
195
+ and certifies an independent mock provider on both bindings.
196
+
197
+ ## Relationship to the rest of OpenIAP
198
+
199
+ ```
200
+ OpenIAP Commerce Protocol ← this package: the server-side contract
201
+
202
+ ┌──────────────┼──────────────┐
203
+ │ │ │
204
+ IAPKit vendor backend custom backend
205
+ (reference)
206
+ │ │ │
207
+ └──────────────┼──────────────┘
208
+
209
+ normalized commerce events
210
+
211
+ ┌──────────────┼──────────────┐
212
+ │ │ │
213
+ SaaS analytics enterprise
214
+ ```
215
+
216
+ No box in that diagram is required to be operated by the OpenIAP project. An
217
+ adopter may self-host IAPKit, use a hosted conforming provider, or implement the
218
+ contract in the backend they already have — and a consumer supports _the
219
+ specification_, so any of the three can feed it.
220
+
221
+ ## Status
222
+
223
+ Implements protocol version 1.0. The event vocabulary,
224
+ envelope, webhook contract, operation surface, REST and GraphQL bindings, and
225
+ portable conformance runner are implemented and tested. `SPEC.md` §14 lists
226
+ what is deliberately not in this version.
227
+
228
+ ## License
229
+
230
+ MIT