Repository navigation
Machine publishing via central auth client_credentials tokens - #291
Conversation
Registers the extensions API as an RFC 8707 resource: publisher clients authenticate with resource-bound JWTs from the central auth service (verified locally through Better Auth's resource-server API), scoped to extensions:push and extensions:publish. Moderators bind clients to developer profiles via /m2m/clients; can_publish clients may approve their own developer's pending revisions, stamped "[auto publisher=<client_id>]" in the review note. Machine principals are rejected on all other routes; write pacing is keyed per client.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
Security findingsAdvisory findings (1)ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Dependency ReviewThe following issues were found:
|
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
api | 356a074 | Nov 01 2026, 06:46 PM |
There was a problem hiding this comment.
🛡️ Codex Security Review · Automatically triggered
Here are some automated security review suggestions for this pull request.
Reviewed commit: d076889460
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
There was a problem hiding this comment.
All reported issues were addressed across 29 files
Reply with feedback, questions, or to request a fix.
Turn on auto-fix | Re-trigger cubic
…eview fixes - m2m_publisher_clients gains ownership_epoch, set from the developer's epoch at registration. Ownership transfers go stale: getActiveRef reports it, middleware rejects with a re-register hint, and the propose/create/approve claim statements re-assert the epoch match, so a former owner's client cannot publish under a recipient. - Registration rebinds to the new epoch (also the un-revoke path). - Deletion batches now clear publisher mappings on profile deletion and account deletion, in guard, so the developers delete can pass. - Verifier chain runs m2m first (typ-filtered, no wasted assertion failures), rate-limits its failure warning, and jose is dropped from devDependencies. - Route docs record the 403s on account routes and the widened approve 403; m2m client registration distinguishes load errors from 404. - Tests: wrong issuer, expired token, ownership-transfer staleness and rebind recovery; key generation memoized in the test helper.
|
CI note: dependency-review fails on |
There was a problem hiding this comment.
All reported issues were addressed across 21 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
Turn on auto-fix | Re-trigger cubic
There was a problem hiding this comment.
0 issues found across 2 files (changes from recent commits).
Requires human review: Auto-approval blocked by 1 unresolved issue from previous reviews.
Turn on auto-fix | Re-trigger cubic
drizzle-kit 0.31 loads its config through @esbuild-kit/esm-loader, whose core-utils dep pins esbuild ~0.18.20 (GHSA-67mh-4wv8-2f99, moderate, fixed in 0.25). Scoped npm override lifts it to the 0.25 already used elsewhere in the tree; drizzle-kit check passes against both configs.
There was a problem hiding this comment.
0 issues found across 2 files (changes from recent commits).
Requires human review: Adds a new machine-to-machine publishing path: M2M bearer verification, a new D1 migration/table, and client-scoped write/approve authorization. This changes auth policy and operational configuration, so it needs human sign-off.
Turn on auto-fix | Re-trigger cubic
|
Fixed by 356a074: a scoped npm override lifts the |
Adds the extensions API as an RFC 8707 resource server for the
FOSSBilling/modulesCI publisher, using tokens from the central auth service (FOSSBilling/auth#74 already registershttps://api.fossbilling.netand theextensions:push/extensions:publishscopes).Auth layer (
src/lib/auth/)AuthPrincipalgains anm2mvariant:{ clientId, scopes, userId }whereuserIdis the client's syntheticusersprojection row (m2m:<client_id>) anchoring revision foreign keys and write budgets.verifyBearerTokenfrombetter-auth/oauth2(local JWKS verification with caching/kid-miss cooldown), gated ontyp: at+jwt, exactiss/aud, andsub === client_id. Scope enforcement stays at route level so insufficient scope answers 403 while bad tokens answer 401.M2M_ISSUER,M2M_JWKS_URL,M2M_AUDIENCE(defaults inwrangler.jsonc).Extensions v2
requireContentWrite():POST /extensionsandPUT /extensions/{id}accept an active human or a mapped client withextensions:push;requireApproveAccess(): approve accepts a moderator or acan_publishclient withextensions:publish(the first-party carve-out).[auto publisher=<client_id>]inreview_note; the mapping and publish flag are re-asserted inside the claim statement, so a concurrent revoke cannot publish.approve()'s ownership claim now matches the developer'sownership_epochonly — matchingowner_user_id = submitted_bymade machine submissions unapprovable by anyone (transfers bump the epoch, which is the actual staleness guard). Human submissions are unaffected.requireActiveAuth,requireModerator,requireUser, and role-aware reads fall back to anonymous).0028+m2m_publisher_clientstable; moderator-gatedPUT/DELETE/GET /m2m/clientsfor bindings. Write pacing keys machine traffic asclient:<client_id>; per-developer budgets unchanged.