Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
89b67e0
ci: skip native matrices for docs-only changes
hyochan Aug 19, 2026
217f142
docs(kit): reconcile the IAPKit surface with OpenIAP
hyochan Aug 19, 2026
f568614
feat(kit): sunset email sign-in on 2026-09-30
hyochan Aug 19, 2026
def1bbe
docs(agents): guard production data and keep agent surfaces in sync
hyochan Aug 19, 2026
11d60e5
docs: correct the alternative billing dialog migration target
hyochan Aug 19, 2026
1621426
fix: address CodeRabbit review on PR #363 and hide announcement thumb…
hyochan Aug 19, 2026
cc39276
fix(kit): bind the Apple verify response to the requesting JWS
hyochan Aug 19, 2026
3047861
test(kit): move email sign-in gates into pure, fully covered functions
hyochan Aug 19, 2026
d81929b
ci: cancel superseded PR runs of the main CI workflow
hyochan Aug 19, 2026
d4d6299
ci: route four mac lanes to a self-hosted runner behind a heartbeat gate
hyochan Aug 19, 2026
78c9aa4
ci: run the mac-runner gate from runner.temp
hyochan Aug 19, 2026
0bf24fb
ci: raise the pinned Xcode toolchain to 26.6 and gate mac routing to PRs
hyochan Aug 19, 2026
d816166
ci: move the react-native release lane to Xcode 26.6 as well
hyochan Aug 19, 2026
f9b4cdd
ci: let the Mac take the SPM-heavy CodeQL legs as a sixth slot
hyochan Aug 19, 2026
ba39e80
ci: restrict Mac routing to the owner's own pull requests
hyochan Aug 19, 2026
bb6afd7
test: teach the CodeQL runner guard the owner-gated Mac policy
hyochan Aug 19, 2026
45454ef
ci: keep the CodeQL Swift legs on hosted runners
hyochan Aug 19, 2026
2fe7b11
ci: run Swift CodeQL legs on the Mac by tracing builds, not tests
hyochan Aug 19, 2026
708faa9
ci: send every Swift CodeQL leg to the Mac when it is alive
hyochan Aug 19, 2026
6854111
ci: keep the Mac runner for CodeQL only
hyochan Aug 19, 2026
8ecd30f
ci: run the react-native CodeQL leg with the Mac's own Ruby
hyochan Aug 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions .claude/commands/audit-iapkit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
---
name: audit-iapkit
description: Audit the IAPKit product surface against OpenIAP as the source of truth, then fix the drift it finds. Use when the user asks to check whether IAPKit reflects OpenIAP updates, audit kit docs, or reconcile kit.openiap.dev with openiap.dev.
---

# Audit IAPKit Against OpenIAP

IAPKit is a deployable SaaS, not a library, so it sits outside the GQL type-sync
chain that keeps the SDKs aligned. Nothing regenerates its site copy when the
spec, the stores, or the SDKs move, so its documentation drifts silently. This
workflow finds that drift and fixes it.

Read `packages/kit/CONVENTION.md` before editing anything under `packages/kit`.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

## Direction of truth

```text
OpenIAP spec + packages/kit implementation → IAPKit site copy
(authoritative) (must follow)
```

Precedence when surfaces disagree: implementation > `packages/docs` >
`packages/kit` prose. `packages/docs` outranks kit prose only where the code
does not decide the question (product positioning, support claims). Never
"fix" the code to match a doc without saying so explicitly.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

## Workflow

```text
1. Establish what changed upstream
↓
2. Check every prose claim against the implementation
↓
3. Check kit against packages/docs for contradictions
↓
4. Apply mechanical fixes; escalate product calls
↓
5. Verify
```

## Steps

### 1. Establish what changed upstream

```bash
# Spec and SDK movement since the kit surface was last reviewed.
git log --oneline -20 -- packages/gql/src/type.graphql openiap-versions.json
# Least recently reviewed kit files first — that is where drift concentrates.
for f in $(git ls-files packages/kit/src/pages/docs/sections packages/kit/src/content); do
echo "$(git log -1 --format='%ad' --date=short -- "$f") $f"
done | sort
```

Also check upstream store documentation for anything the kit pages describe:
App Store Server API, Google Play Developer API, Amazon RVS, Meta Horizon, and
the Vega SDK release notes.

### 2. Check prose against the implementation

This is the highest-value pass. For every checkable claim on the kit site, find
the code that implements it and confirm the claim matches. Cite `file:line` for
both sides.

Highest-yield targets, in order:

- **Verification order and cryptography** — `packages/kit/convex/purchases/*.ts`.
A page saying IAPKit verifies something it does not verify is the worst class
of error.
- **Error codes** — confirm each documented code can actually reach a caller.
Codes raised internally and re-wrapped before the response must not be listed.
- **Endpoints, fields, and limits** — `packages/kit/server/api/v1/**`,
especially `route-input-schemas.ts` for which fields are required. A field the
server requires but the docs call optional makes every following example 400.
- **Negative verdicts that return 200** — outcomes that are not errors but are
documented as if they were, or not documented at all.
- **Numbers** — retry counts, rate limits, size caps, file sizes, retention
windows. These rot silently; recompute rather than trusting the page.

### 3. Check kit against `packages/docs`

The two sites describe one product. Find statements that contradict each other
and decide which side is right from the code, then fix the wrong side.

```bash
bun run audit:docs
```

### 4. Apply fixes, escalate decisions

Fix mechanically when the correct text is determined by the code: a wrong fact,
an unreachable error code, a stale number, a broken link, a naming violation.

Escalate to the user, do not guess, when the fix requires a product call:
what the product officially claims to support, support channels, pricing or
plan statements, legal document content, restructuring a page, or consolidating
pages that have published URLs.

Constraints that override any finding:

- **Production is read-only.** Never run a mutation or action against the
production Convex deployment, from the dashboard runner or anywhere else, and
never hand-edit production documents. Reads are fine when the user asks;
report aggregates, not customer emails. Full rule in the root `AGENTS.md`.
- **Webhook direction.** The only supported direction is store → IAPKit. Never
document an IAPKit → SDK/mobile webhook, SSE, WebSocket, push relay, or
long-poll feed. See the root `AGENTS.md`.
- **Brand.** `OpenIAP` and `IAPKit`, never `Open IAP`, `IAP Kit`, or bare `Kit`.
- **Reader-first standard.** `knowledge/internal/05-docs-patterns.md`. Remove
filler and state each fact once; do not restyle prose that is already clear.
- **Screenshots.** A figure that contradicts corrected text is worse than no
figure. Open the image before trusting its caption.

### 5. Verify

```bash
bun run --filter @hyodotdev/openiap-kit lint
bun run --filter @hyodotdev/openiap-kit test
bun run --filter @hyodotdev/openiap-kit smoke:server
bun run audit:kit-contract
bun run audit:docs
```

`packages/kit` changes also trigger the CI-equivalent gate in
`.husky/pre-commit`, which mirrors `deploy-kit.yml`.

## Report

Group findings as **fixed** (with file:line), **needs a decision** (with the
options and your recommendation), and **rejected** (with the reason). Say
plainly when a surface is in good shape rather than manufacturing work.
6 changes: 6 additions & 0 deletions .claude/commands/verify-all.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ bun run audit:parity
# Stable main / prerelease next branch contract.
bun run audit:release-state
node --test scripts/release-branch-policy.test.mjs

# Native build / Swift CodeQL path filters.
bun run audit:ci-paths
bun run audit:agents
```

This fails if a new non-Godot library, Expo example route/product ID, generated
Expand Down Expand Up @@ -318,6 +322,8 @@ set -euo pipefail
(cd scripts/agent && bun run compile:ai && bun test && bun run typecheck)
bun run audit:parity
bun run audit:release-state
bun run audit:ci-paths
bun run audit:agents
bun test \
--path-ignore-patterns='**/build/**' \
--path-ignore-patterns='**/.build/**' \
Expand Down
4 changes: 3 additions & 1 deletion .claude/skills/openiap-workflows/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: openiap-workflows
description: Use for OpenIAP monorepo work that should follow the repository's slash-command workflows when the user asks in natural language instead of typing a slash command, including review-pr, audit-code, compile-knowledge, verify-all, e2e-tests, stable or prerelease package releases, resolve-issue, commit/push/PR, generated type sync, package-specific checks, GitHub review threads, and project conventions from AGENTS.md.
description: Use for OpenIAP monorepo work that should follow the repository's slash-command workflows when the user asks in natural language instead of typing a slash command, including review-pr, audit-code, audit-security, audit-iapkit, compile-knowledge, verify-all, e2e-tests, stable or prerelease package releases, resolve-issue, commit/push/PR, generated type sync, package-specific checks, GitHub review threads, and project conventions from AGENTS.md.
---

# OpenIAP Workflows (Claude Code)
Expand All @@ -20,6 +20,8 @@ reading the command file (or invoke the slash command directly when available):
bots, and remove temporary CodeRabbit trigger and terminal
skip/unavailable top-level comments when the loop is clean
- Audit code against knowledge rules → `.claude/commands/audit-code.md` (`/audit-code`)
- Audit supply-chain security / SBOM → `.claude/commands/audit-security.md` (`/audit-security`)
- Reconcile IAPKit with OpenIAP → `.claude/commands/audit-iapkit.md` (`/audit-iapkit`)
- Compile knowledge / rebuild AI context → `.claude/commands/compile-knowledge.md` (`/compile-knowledge`)
- Resolve a GitHub issue → `.claude/commands/resolve-issue.md` (`/resolve-issue`)
- Verify all / monorepo health check → `.claude/commands/verify-all.md` (`/verify-all`)
Expand Down
4 changes: 3 additions & 1 deletion .codex/skills/openiap-workflows/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: openiap-workflows
description: Use for OpenIAP monorepo work that should follow the repository's shared agent workflows, including review-pr, audit-code, compile-knowledge, verify-all, e2e-tests, stable or prerelease package releases, resolve-issue, commit/push/PR, generated type sync, package-specific checks, GitHub review threads, and project conventions from AGENTS.md.
description: Use for OpenIAP monorepo work that should follow the repository's shared agent workflows, including review-pr, audit-code, audit-security, audit-iapkit, compile-knowledge, verify-all, e2e-tests, stable or prerelease package releases, resolve-issue, commit/push/PR, generated type sync, package-specific checks, GitHub review threads, and project conventions from AGENTS.md.
---

# OpenIAP Workflows
Expand Down Expand Up @@ -40,6 +40,8 @@ natural-language requests, execute the matching workflow:
`.claude/commands/audit-code.md`.
- Audit SBOM quality, release provenance, workflow permissions, or
supply-chain/security posture: read `.claude/commands/audit-security.md`.
- Reconcile the IAPKit site with OpenIAP, audit kit docs, or check whether
IAPKit reflects a spec/store update: read `.claude/commands/audit-iapkit.md`.
- Compile knowledge or rebuild AI context: read
`.claude/commands/compile-knowledge.md`.
- Resolve a GitHub issue: read `.claude/commands/resolve-issue.md`.
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/ci-expo-iap.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ on:
- "packages/apple/Sources/**"
- "packages/apple/Package.swift"
- "openiap-versions.json"
- "libraries-versions.jsonc"
- "codecov.yml"
- ".github/workflows/ci-expo-iap.yml"
- "!**/*.md"
push:
branches: [main, next]
paths:
Expand All @@ -19,8 +21,10 @@ on:
- "packages/apple/Sources/**"
- "packages/apple/Package.swift"
- "openiap-versions.json"
- "libraries-versions.jsonc"
- "codecov.yml"
- ".github/workflows/ci-expo-iap.yml"
- "!**/*.md"

permissions:
contents: read
Expand Down
10 changes: 7 additions & 3 deletions .github/workflows/ci-flutter-inapp-purchase.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ on:
- "packages/apple/Sources/**"
- "packages/apple/Package.swift"
- "openiap-versions.json"
- "libraries-versions.jsonc"
- "codecov.yml"
- ".github/workflows/ci-flutter-inapp-purchase.yml"
- ".github/workflows/release-flutter.yml"
- "!**/*.md"
push:
branches: [main, next]
paths:
Expand All @@ -20,9 +22,11 @@ on:
- "packages/apple/Sources/**"
- "packages/apple/Package.swift"
- "openiap-versions.json"
- "libraries-versions.jsonc"
- "codecov.yml"
- ".github/workflows/ci-flutter-inapp-purchase.yml"
- ".github/workflows/release-flutter.yml"
- "!**/*.md"

permissions:
contents: read
Expand Down Expand Up @@ -111,12 +115,12 @@ jobs:
run: bash scripts/verify-apple-swiftpm-consumer-build.sh

apple-cocoapods:
name: iOS CocoaPods consumer (Flutter 3.44 + Xcode 16.4)
name: iOS CocoaPods consumer (Flutter 3.44 + Xcode 26.6)
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
runs-on: macos-15
runs-on: macos-26
timeout-minutes: 60
env:
XCODE_VERSION: 16.4
XCODE_VERSION: 26.6
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/ci-godot-iap.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ on:
- "libraries/godot-iap/**"
- "packages/gql/codegen/plugins/gdscript.ts"
- "packages/gql/src/generated/types.gd"
- "openiap-versions.json"
- "!**/*.md"
push:
branches: [main, next]
paths:
Expand All @@ -19,6 +21,8 @@ on:
- "libraries/godot-iap/**"
- "packages/gql/codegen/plugins/gdscript.ts"
- "packages/gql/src/generated/types.gd"
- "openiap-versions.json"
- "!**/*.md"

permissions:
contents: read
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/ci-kmp-iap.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ on:
- "openiap-versions.json"
- "scripts/ci/retry-gradle.sh"
- ".github/workflows/ci-kmp-iap.yml"
- "!**/*.md"
push:
branches: [main, next]
paths:
Expand All @@ -17,6 +18,7 @@ on:
- "openiap-versions.json"
- "scripts/ci/retry-gradle.sh"
- ".github/workflows/ci-kmp-iap.yml"
- "!**/*.md"

permissions:
contents: read
Expand Down Expand Up @@ -66,7 +68,7 @@ jobs:

ios-compile-check:
name: iOS Compile Check
runs-on: macos-15
runs-on: macos-26
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/ci-maui-iap.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ on:
- "openiap-versions.json"
- "scripts/ci/retry-gradle.sh"
- ".github/workflows/ci-maui-iap.yml"
- "!**/*.md"
push:
branches: [main, next]
paths:
Expand All @@ -25,6 +26,7 @@ on:
- "openiap-versions.json"
- "scripts/ci/retry-gradle.sh"
- ".github/workflows/ci-maui-iap.yml"
- "!**/*.md"

permissions:
contents: read
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/ci-react-native-iap.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ on:
- "packages/apple/Sources/**"
- "packages/apple/Package.swift"
- "openiap-versions.json"
- "libraries-versions.jsonc"
- "codecov.yml"
- ".github/workflows/ci-react-native-iap.yml"
- "!**/*.md"
push:
branches: [main, next]
paths:
Expand All @@ -19,8 +21,10 @@ on:
- "packages/apple/Sources/**"
- "packages/apple/Package.swift"
- "openiap-versions.json"
- "libraries-versions.jsonc"
- "codecov.yml"
- ".github/workflows/ci-react-native-iap.yml"
- "!**/*.md"

permissions:
contents: read
Expand Down
20 changes: 18 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ on:
permissions:
contents: read

# Cancel the superseded run on every PR push; main pushes always run to completion.
concurrency:
group: ci-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
XCODE_VERSION: 16.4
XCODE_VERSION: 26.6

jobs:
audit-release-state:
Expand Down Expand Up @@ -153,6 +158,8 @@ jobs:
uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4
id: filter
with:
# Without this, '!' patterns are OR-ed positives that match nearly everything.
predicate-quantifier: some-with-excludes
filters: |
gql:
- 'packages/gql/**'
Expand All @@ -163,18 +170,21 @@ jobs:
- 'openiap-versions.json'
- '.github/workflows/ci.yml'
- 'libraries/maui-iap/src/OpenIap.Maui/Types.cs'
- '!**/*.md'
android:
- 'packages/google/**'
- 'packages/gql/**'
- 'scripts/**'
- 'openiap-versions.json'
- '.github/workflows/ci.yml'
- '!**/*.md'
ios:
- 'packages/apple/**'
- 'packages/gql/**'
- 'scripts/**'
- 'openiap-versions.json'
- '.github/workflows/ci.yml'
- '!**/*.md'
docs:
- 'packages/docs/**'
- 'packages/gql/src/generated/**'
Expand Down Expand Up @@ -291,6 +301,12 @@ jobs:
- name: Run IAPKit spec contract audit
run: node scripts/audit-kit-spec-contract.mjs

- name: Audit CI path filters
run: npm run audit:ci-paths

- name: Audit agent surfaces
run: npm run audit:agents

test-gql:
name: Test GQL Types
runs-on: ubuntu-latest
Expand Down Expand Up @@ -388,9 +404,9 @@ jobs:

test-ios:
name: Test iOS
runs-on: macos-15
needs: changes
if: needs.changes.outputs.ios == 'true'
runs-on: macos-26
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
Expand Down
Loading
Loading