@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/CONVENTION.md ADDED
@@ -0,0 +1,168 @@
1
+ # Commerce Protocol conventions
2
+
3
+ Rules for changing the OpenIAP Commerce Protocol. Read `SPEC.md` first; this
4
+ file covers how to modify it safely.
5
+
6
+ ## The GraphQL contract is the source of truth
7
+
8
+ Edit the layers under `schema/` — one file per logical surface, assembled in
9
+ filename order by `scripts/assemble-schema.mjs` into the generated single-file
10
+ `generated/commerce-protocol.graphql` (exported at the package path
11
+ `./commerce-protocol.graphql` for consumers), which is generated and never
12
+ edited. The custom
13
+ directives preserve the patterns, bounds, maps, open-object policy,
14
+ omission/nullability distinction, and conditional invariants that plain
15
+ GraphQL SDL cannot express.
16
+
17
+ `scripts/build-json-schemas.mjs` compiles the SDL into the modular files under
18
+ `generated/schemas/`; `scripts/build-bundle.mjs` then creates the offline
19
+ bundle. `scripts/build-lifecycle-vectors.mjs` writes only to
20
+ `generated/vectors/`, and `scripts/build-operations.mjs` compiles the Query and
21
+ Mutation surface into `generated/bindings/`, `generated/openapi/`, and
22
+ `generated/vectors/operations.json`. Every file under `generated/` is committed
23
+ for consumers that should not need GraphQL tooling, but is never edited
24
+ directly. `bun run test` byte-compares every generated artifact and rejects
25
+ drift.
26
+
27
+ `src/index.mjs` reads the generated runtime artifacts. Never restate a contract
28
+ value in code or prose that could drift from the SDL. If runtime code needs an
29
+ event-type list, read it from
30
+ `commerceEventSchema.properties.eventType.examples` — the space is open, so the
31
+ schema documents the known values rather than closing the set.
32
+ A second hand-maintained list is the defect this rule exists to prevent.
33
+
34
+ Do not add this SDL to `specs/client/schema-files.mjs` or generate client SDK
35
+ types from it. `specs/client` owns the client purchase API and its executable
36
+ Query, Mutation, and Subscription surface. This package independently owns the
37
+ server-to-server commerce contract; its own Query and Mutation types are
38
+ operation containers for the portable server surface, compiled into the REST
39
+ and GraphQL bindings and nothing else. A Subscription root stays forbidden —
40
+ the compiler rejects one — because the operation surface is bounded
41
+ request/response, never a stream a shipped app could hold open.
42
+
43
+ ## Never add a central dependency
44
+
45
+ This specification must stay implementable and verifiable with no request to
46
+ anything the OpenIAP project operates. That rules out: an issued identifier or
47
+ credential in any schema; a registry lookup; a hosted validation or conformance
48
+ service; telemetry of any kind; and a schema `$ref` that resolves off the local
49
+ document.
50
+
51
+ The last one is subtle and already bit us: a relative `$ref` resolves against
52
+ the absolute `$id`, so the modular schemas alone would have sent a validator to
53
+ `openiap.dev`. `generated/schemas/commerce-protocol.bundle.schema.json` exists
54
+ to close that and is generated from the canonical SDL. Edit the SDL, never the
55
+ bundle or modular outputs.
56
+
57
+ `test/decentralization.test.mjs` guards this section. Adding a rule here without
58
+ a test there means the rule is decoration.
59
+
60
+ ## This package specifies; it does not implement
61
+
62
+ Nothing here may import a backend, a database client, or IAPKit. The published
63
+ runtime has no dependencies and must keep none — the GraphQL parser is a
64
+ development-only compiler dependency. An implementation in Go or Rust gets the
65
+ same generated artifacts as a TypeScript one.
66
+
67
+ `src/index.mjs` is a convenience binding over the schemas. It is not privileged.
68
+
69
+ `conformance/` is verification tooling, not a backend: the runner drives any
70
+ provider through the generated vectors via an injected `fetch`, and the mock
71
+ provider exists to prove the runner needs no IAPKit code. Neither may import a
72
+ backend, and the runner takes its JSON Schema validator by injection so the
73
+ published runtime keeps zero dependencies.
74
+
75
+ ## Changing the contract
76
+
77
+ Every change answers one question first: **is this MAJOR or MINOR?** The table
78
+ in `SPEC.md` §12 decides it.
79
+
80
+ A MINOR change requires:
81
+
82
+ 1. The SDL edit, in the owning `schema/` layer.
83
+ 2. `bun run build` to regenerate JSON Schema artifacts.
84
+ 3. An example exercising it, added to `examples/`.
85
+ 4. A test in `test/schemas.test.mjs` proving both that the valid shape passes and
86
+ that the invalid shape fails. A rule with no rejection test is not enforced.
87
+ An operation or binding change proves itself in `test/operations.test.mjs`
88
+ instead, including a compiler rejection for a new @operation rule.
89
+ 5. The matching prose in `SPEC.md`. `test/operations.test.mjs` pins §3, §6.1,
90
+ and §8 to the generated manifest, so prose and contract cannot drift apart.
91
+
92
+ A MAJOR change additionally requires a migration note in `SPEC.md` stating what
93
+ breaks and what a consumer pinned to the previous major should do.
94
+
95
+ ## Do not specify what is not implemented
96
+
97
+ A capability may enter the specification only when a real implementation emits
98
+ it and a test proves it. `SPEC.md` §14 exists to hold the rest: an honestly
99
+ listed gap is useful, a specified-but-absent feature is a lie a consumer will
100
+ build against.
101
+
102
+ ## Public collaboration and implementation evidence
103
+
104
+ Open a public issue before changing shared behavior. Use the Commerce Protocol
105
+ proposal form and follow the project's [significant-decision review process](https://openiap.dev/docs/foundation/governance#significant-decisions).
106
+ Include the use case, affected roles and implementations, a runnable example
107
+ with an expected result and rejection case, and the MAJOR/MINOR impact.
108
+ Explain why an existing profile or extension cannot express the requirement.
109
+
110
+ Apply the same schema and behavioral checks to every implementation, including
111
+ IAPKit. A feature's presence in IAPKit is not sufficient evidence for acceptance.
112
+ Record relevant implementation affiliations, objections, their resolution, and
113
+ the decision rationale in the issue. Identify who actually reviewed or ran the
114
+ example; missing independent review stays an explicit gap, not an endorsement.
115
+ The current project lead retains the decision authority described by governance.
116
+
117
+ For interoperability reports, include source revisions or hashes, commands,
118
+ the compared configurations without credential values, changed adapter/client
119
+ files, results, and limits. Separate same-project fixtures, external implementer
120
+ reproductions, store sandbox runs, and production observations. Preserve failing
121
+ cases and disclose required client changes; two green schema checks alone do
122
+ not demonstrate interchangeable implementations.
123
+
124
+ ## The deployed wire format constrains us
125
+
126
+ Event schema version 1.0 is deployed and its payload shape is published. A
127
+ change to an existing member is a live break for receivers already decoding it,
128
+ including receivers this repository cannot see.
129
+
130
+ `SubscriptionState` is PascalCase while event types are lowercase-dotted. That
131
+ inconsistency is inherited, recorded here, and stays until a major
132
+ version. Do not "fix" it in place.
133
+
134
+ ## Keeping IAPKit honest
135
+
136
+ `packages/kit/convex/commerce/spec.conformance.test.ts` validates payloads that
137
+ IAPKit actually builds against the schemas published here, and compares the two
138
+ vocabularies directly. It fails when either side drifts.
139
+
140
+ That test belongs to kit, not to this package: the specification does not depend
141
+ on its implementation. When a spec change makes it fail, the correct fix is
142
+ usually in kit — unless the spec change was wrong.
143
+
144
+ ## DESIGN.md explains, SPEC.md decides
145
+
146
+ `DESIGN.md` is the reasoning behind the boundaries. It may not state a rule
147
+ `SPEC.md` does not, and where the two disagree `SPEC.md` is right and
148
+ `DESIGN.md` is the bug.
149
+
150
+ It ships in the npm tarball, so every link to something outside this package
151
+ is an absolute repository URL — a relative one dangles for anyone reading the
152
+ installed copy.
153
+
154
+ It is also the source of the published PDF. After editing it, rebuild with
155
+ `scripts/build-whitepaper.sh` and commit the PDF and the
156
+ `scripts/whitepaper.sha256` manifest it writes in the same change.
157
+ `bun audit:whitepaper` compares that manifest with the working tree, so a
158
+ source edit without a rebuild, or a rebuild that never reached the commit,
159
+ fails instead of publishing a stale document. Bump the version and date in its front matter when
160
+ the reasoning changes, not for a typo.
161
+
162
+ ## Verification
163
+
164
+ ```bash
165
+ bun run test # from specs/commerce-protocol
166
+ (cd ../.. && bun audit:whitepaper) # DESIGN.md matches the published PDF
167
+ (cd ../../packages/kit && npx vitest run convex/commerce/) # the conformance proof
168
+ ```