Worker: revocations, install counts, Play verification; client publish() - #229
Conversation
- Moderators yank a version from /moderation or the admin API. It lands on /revocations, leaves listings, shows yanked in detail, and its download 404s. - Full downloads carry azphalt-report-token. POST /installs counts installs and uninstalls against tokens and receipts. Free downloads are streamed from the git catalog so the token can ride along. - POST /entitlements/play verifies one-time purchases with the Android Publisher API (service-account JWT, RS256 over WebCrypto) and issues the store-signed entitlement. It answers 501 until configured. - @azphalt/repository-client gains publish(). - Privacy policy, terms header and Worker README updated to match. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QwYWVPse8spRrfMMcuTJPv
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Reviewer's GuideThe PR closes the Worker’s remaining repository API gaps by adding durable revocation and moderation workflows, anonymous install-count reporting, and Google Play purchase verification, while changing free downloads to Worker streaming so report tokens reach clients. It also adds typed client publish() support, expands integration coverage, and updates documentation and release metadata. Sequence diagram for streamed downloads and install reportingsequenceDiagram
participant Client
participant Worker
participant GitCatalog
participant DurableObject
Client->>Worker: GET package download
Worker->>DurableObject: POST /report-token
DurableObject-->>Worker: 32-byte token
Worker->>GitCatalog: Fetch package bytes
GitCatalog-->>Worker: 200 or 206 response
Worker-->>Client: Stream bytes with azphalt-report-token on 200
Client->>Worker: POST /installs
Worker->>DurableObject: Redeem token or receipt
DurableObject-->>Worker: accepted or rejected
Worker-->>Client: Install report result
Sequence diagram for moderator revocation workflowsequenceDiagram
actor Moderator
participant Storefront
participant Worker
participant DurableObject
participant RepositoryClient
Moderator->>Storefront: Yank report
Storefront->>Worker: POST /api/reports/{id}/resolve
Worker->>DurableObject: PUT /report/{id}/resolution
DurableObject-->>Worker: Report version
Worker->>DurableObject: PUT /revocation/{packageId}/{version}
DurableObject-->>Worker: Revocation
Worker-->>Storefront: Resolved report and revocation
RepositoryClient->>Worker: GET /revocations?since=
Worker->>DurableObject: GET /revocations
DurableObject-->>Worker: Yanked versions
Worker-->>RepositoryClient: Revocation feed
Sequence diagram for Google Play purchase verificationsequenceDiagram
participant App
participant Worker
participant GoogleOAuth
participant GooglePlay
participant DurableObject
App->>Worker: POST /entitlements/play
Worker->>GoogleOAuth: JWT assertion signed with RS256
GoogleOAuth-->>Worker: OAuth access token
Worker->>GooglePlay: Verify product purchase token
GooglePlay-->>Worker: Purchase state and order identity
opt Unacknowledged purchase
Worker->>GooglePlay: Acknowledge purchase
end
Worker->>DurableObject: issueEntitlement
DurableObject-->>Worker: Store-signed entitlement
Worker-->>App: Entitlement or 402/502/501
Sequence diagram for client package publishingsequenceDiagram
participant Publisher
participant RepositoryClient
participant Repository
Publisher->>RepositoryClient: publish(azp)
RepositoryClient->>Repository: POST /packages
alt 201 Created
Repository-->>RepositoryClient: Live package
RepositoryClient-->>Publisher: PublishLive
else 202 Accepted
Repository-->>RepositoryClient: Pending review
RepositoryClient-->>Publisher: PublishPending
else Refused
Repository-->>RepositoryClient: Error envelope
RepositoryClient-->>Publisher: PublishError
end
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Nothing in the repository runs it, so no code change can fix it. It stops once Copilot's code review / security agent is turned off in the repo settings. The OpenCode Generated by Claude Code |
There was a problem hiding this comment.
Sorry @HereLiesAz, you've used your own review budget of 250,000 diff characters for the last 7 days.
You can request another review in 2 days and 21 hours by commenting @sourcery-ai review. Upgrade to get a review now.
This fills the Worker's remaining Repository API gaps and adds
publish()to the client.Revocations (§ 5)
/moderation(Dismiss / Yank on each report), or throughPOST /api/admin/revocationsandDELETE /api/admin/revocations/{id}/{version}.POST /api/reports/{id}/resolverecords the decision. A yank uses the report's version, or the version served now if the report named none./revocations(supports?since=);/packagesand/api/packages;yanked: truein its detail;404 not_foundon download.Install counts (§ 8)
200download, free or paid, carriesazphalt-report-token: 32 random bytes, stored with only the package and version, and deleted after 30 days if unspent.206responses carry none.POST /installsspends tokens and receipts per spec. Rejections are counted, not fatal.installsanduninstallsappear on the package summaries.Play (§ 7)
src/play.tsimplements a real verifier:purchases.productsand acknowledges unacknowledged purchases.play-account:<obfuscatedExternalAccountId>, falling back toplay-order:<orderId>.playProductId, which defaults to the package id.402when Google does not recognise the purchase;502when Google cannot be reached or our credentials are refused;501for subscription listings;501untilPLAY_PACKAGE_NAME(var,store.azphalt.storefront) andPLAY_SERVICE_ACCOUNT_JSON(secret) are set.Client
RepositoryClient.publish(azp)returnsPublishPendingorPublishLive, and throwsPublishErrorwithstatus,codeanddetails.Docs
@azphalt/repository-clientminor (public); the Worker and React apps minor (private), in separate files so neither is a mixed changeset.Validation
node:sqliteand stub GitHub raw and Google. The OAuth assertion's RS256 signature is verified against the generated key.pnpm testandpnpm -r typecheckpass across the workspace.wrangler dev), the following worked end to end: feed, yank, detail, listing exclusion, report resolve, installs and Play 501. That run exercised theALTER TABLEmigration on DO SQLite.Needs from you for Play: a service account with View financial data and Manage orders on the store app, then
wrangler secret put PLAY_SERVICE_ACCOUNT_JSONand thePLAY_PACKAGE_NAMEvar.Not in this PR: the Worker has no
POST /updates(§ 6) yet, and store-app subscriptions via Play remain unsupported.🤖 Generated with Claude Code
https://claude.ai/code/session_01QwYWVPse8spRrfMMcuTJPv
Generated by Claude Code
Summary by Sourcery
Complete the Worker's remaining repository APIs and add client-side package publishing.
New Features:
RepositoryClient.publish()with pending-review and published results plus structured publish errors.Bug Fixes:
Enhancements:
Deployment:
Documentation:
Tests:
Chores: