@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.
- package/CONVENTION.md +168 -0
- package/DESIGN.md +1056 -0
- package/README.md +227 -5
- package/SPEC.md +1471 -0
- package/conformance/index.d.ts +303 -0
- package/conformance/index.mjs +2126 -0
- package/conformance/mock-provider.mjs +491 -0
- package/examples/entitlement-granted-no-subscription.json +12 -0
- package/examples/entitlement-revoked.json +21 -0
- package/examples/provider-capabilities.json +209 -0
- package/examples/store-event-mapping.json +287 -0
- package/examples/subscription-canceled.json +22 -0
- package/examples/subscription-product-changed.json +30 -0
- package/examples/subscription-renewed.json +29 -0
- package/examples/verify-purchase-request.json +6 -0
- package/examples/verify-purchase-result.json +7 -0
- package/generated/bindings/graphql-operations.json +87 -0
- package/generated/bindings/http-binding.json +143 -0
- package/generated/bindings/introspection-signature.json +320 -0
- package/generated/bindings/operations-sdl.json +4 -0
- package/generated/bindings/operations.graphql +366 -0
- package/generated/commerce-protocol.graphql +1219 -0
- package/generated/openapi/commerce-protocol.openapi.json +1413 -0
- package/generated/schemas/commerce-event.schema.json +499 -0
- package/generated/schemas/commerce-protocol.bundle.schema.json +1576 -0
- package/generated/schemas/operations.schema.json +578 -0
- package/generated/schemas/primitives.schema.json +101 -0
- package/generated/schemas/provider-capabilities.schema.json +205 -0
- package/generated/schemas/store-event-mapping.schema.json +211 -0
- package/generated/vectors/lifecycle.json +908 -0
- package/generated/vectors/operations.json +1122 -0
- package/package.json +62 -12
- package/schema/01-primitives.graphql +102 -0
- package/schema/02-commerce-event.graphql +195 -0
- package/schema/03-provider-capabilities.graphql +139 -0
- package/schema/04-store-event-mapping.graphql +98 -0
- package/schema/05-operations.graphql +461 -0
- package/schema/06-compiler-vocabulary.graphql +139 -0
- package/schema/07-protocol-metadata.graphql +76 -0
- package/src/index.d.ts +63 -0
- package/src/index.mjs +121 -0
- 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
|
+
```
|