Skip to content

prime-time: service-auth-adapters (WorkOS + better-auth)#83

Merged
rickylabs merged 10 commits into
feat/framework-prime-timefrom
feat/prime-time/service-auth-adapters
Jun 20, 2026
Merged

prime-time: service-auth-adapters (WorkOS + better-auth)#83
rickylabs merged 10 commits into
feat/framework-prime-timefrom
feat/prime-time/service-auth-adapters

Conversation

@rickylabs

Copy link
Copy Markdown
Owner

Track-2 — service-auth-adapters (prime-time slice)

Real auth provider adapters for @netscript/service (consumes the #77 AuthenticatorPort/AuthorizerPort/Principal seam). Additive only.

Packages

  • @netscript/auth-workoscreateWorkosAuthenticator (sealed-session loadSealedSession().authenticate() -> Principal, rotated-session cookie emission) and createWorkosAccessTokenAuthenticator (real jose JWKS JWT verification, audience-bound).
  • @netscript/auth-better-authcreateNetscriptBetterAuth (wraps better-auth's first-party prismaAdapter over a consumer-owned Prisma client; no @netscript/database dep per PLAN-EVAL layering fix), createBetterAuthAuthenticator (auth.api.getSession + Set-Cookie capture), mountBetterAuthHandler, and .llm/tools/auth/gen-better-auth-prisma.ts schema-gen wrapper.

Catalog law

  • Added better-auth ^1.6.20 + @workos-inc/node ^10.4.0 to the catalog; referenced only in the new packages via catalog:. @prisma/client/jose unchanged. No de-catalog, no version-pin edits.

Gates (selected; NOT an e2e-cli-gate slice)

  • check / lint / fmt / doc-lint / test (auth-workos 6, auth-better-auth 7) — PASS.
  • Node-compat smokes: @workos-inc/node@10.4.0 + better-auth@1.6.20 import & run under Deno 2.8.3.
  • deno publish --dry-run per package + root publish:dry-run — PASS (isolated declarations satisfied, no carve-out).
  • Consumer-import validation: both authenticators assign to upstream AuthenticatorPort with no type errors.

Deferred / drift

  • WorkOS webhook->DB user/org sync and CLI auth-provider scaffold prompts deferred by the approved plan.
  • Pre-existing repo-wide arch:check + deps:audit (undici/vite) findings are outside this slice and recorded in drift.

Run artifacts: .llm/tmp/run/feat-framework-prime-time--supervisor/slices/service-auth-adapters/.

Generator: WSL Codex daemon thread 019ee450-0594-75c1-8c59-2d61194916aa. Awaiting IMPL-EVAL (OpenHands qwen3.7-max, separate session) before merge into the umbrella.

@rickylabs

Copy link
Copy Markdown
Owner Author

@openhands-agent model=openrouter/qwen/qwen3.7-max output=pr-comment

Run IMPL-EVAL for the service-auth-adapters prime-time slice on THIS PR branch (checked out for you). You are a SEPARATE evaluator session from the WSL Codex generator — do not trust the worklog; independently verify.

Read first (in order):

  1. .llm/harness/evaluator/protocol.md and .llm/harness/evaluator/verdict-definitions.md.
  2. .llm/tmp/run/feat-framework-prime-time--supervisor/slices/service-auth-adapters/plan.md, plan-eval.md, worklog.md, context-pack.md, drift.md, commits.md.
  3. .llm/harness/gates/archetype-gate-matrix.md (these are ARCHETYPE-1 library packages with a SCOPE-service overlay).
  4. The diff vs the PR base, and the two new packages packages/auth-workos + packages/auth-better-auth and .llm/tools/auth/gen-better-auth-prisma.ts.

Production/enterprise bar to certify (NO stubs, NO no-ops):

  • WorkOS: createWorkosAuthenticator really calls loadSealedSession().authenticate() and maps a real Principal; rotated session emits cookies via AuthnResult.setCookies. createWorkosAccessTokenAuthenticator performs REAL jose JWKS signature verification with audience binding (not a decode-only shim).
  • better-auth: createNetscriptBetterAuth WRAPS better-auth's own prismaAdapter over a consumer-owned Prisma client and does NOT import @netscript/database (PLAN-EVAL layering fix). createBetterAuthAuthenticator calls auth.api.getSession and captures Set-Cookie. mountBetterAuthHandler mounts the Fetch handler.
  • ADDITIVE ONLY: the upstream [prime-time] Service auth seam #77 AuthenticatorPort/AuthorizerPort/Principal/AuthnRequest/AuthnResult contract from @netscript/service/auth is consumed, NOT redefined or modified.
  • CATALOG LAW: better-auth ^1.6.20 + @workos-inc/node ^10.4.0 are referenced via catalog: ONLY inside the new packages; no de-catalog; @prisma/client/jose pins, packages/aspire/src/public/mod.ts, and scaffold-versions.ts untouched.

Independently RE-RUN the selected gates (this is NOT an e2e-cli-gate slice — do NOT run deno task e2e:cli):

  • deno run --allow-read --allow-run .llm/tools/run-deno-check.ts --root packages/auth-workos --root packages/auth-better-auth --ext ts,tsx
  • deno run --allow-read --allow-run .llm/tools/run-deno-lint.ts --root packages/auth-workos --root packages/auth-better-auth --ext ts,tsx
  • deno run --allow-read --allow-run .llm/tools/run-deno-fmt.ts --root packages/auth-workos --root packages/auth-better-auth --root .llm/tools/auth --ext ts,tsx --ignore-line-endings
  • deno test --allow-net packages/auth-workos/tests/ and deno test --allow-net --allow-env packages/auth-better-auth/tests/
  • deno run --allow-read --allow-run .llm/tools/run-deno-doc-lint.ts --root packages/auth-workos --pretty and same for auth-better-auth
  • deno task publish:dry-run (confirm isolated declarations satisfied, no carve-out)
  • Confirm the node-compat smokes for @workos-inc/node@10.4.0 and better-auth@1.6.20 genuinely import/run under Deno 2.8.

Allowed deferrals (do not fail the slice for these — confirm they are recorded in drift.md): WorkOS webhook->DB sync, CLI auth-provider scaffold prompts, and pre-existing repo-wide arch:check + deps:audit (undici/vite) findings outside the new packages.

Emit a verdict of exactly PASS, FAIL_FIX, FAIL_RESCOPE, or FAIL_DEBT with file:line evidence for any finding. Report the raw exit code of each gate. Preserve lock hygiene: do not commit deno.lock re-resolution or source churn unless an explicit reviewed fix requires it.

@rickylabs

rickylabs commented Jun 20, 2026

Copy link
Copy Markdown
Owner Author

OpenHands Agent — Completed

Model: openrouter/qwen/qwen3.7-max
Provider: OPENROUTER
Job status: success
Trace: .llm/tmp/run/openhands/pr-83/run-27867455720-1 (committed to the PR branch)
Artifact: openhands-agent-27867455720-1

IMPL-EVAL Summary — service-auth-adapters

Summary

Independent IMPL-EVAL completed for the service-auth-adapters prime-time slice (@netscript/auth-better-auth + @netscript/auth-workos) on PR #83 branch feat/prime-time/service-auth-adapters.

Verdict: PASS

All production/enterprise bar requirements verified with file:line evidence. All required gates passed (exit code 0). No stubs, no no-ops, no contract redefinition, no catalog violations.

Changes Evaluated

New packages

  • packages/auth-workos — WorkOS AuthKit authenticators (sealed-session + JWKS access-token)
  • packages/auth-better-auth — better-auth integration (Prisma adapter wrapper + authenticator + mount helper)
  • .llm/tools/auth/gen-better-auth-prisma.ts — Schema generation wrapper for better-auth Prisma models

Key implementation details

  • WorkOS sealed-session: createWorkosAuthenticator calls loadSealedSession().authenticate() (line 159-166), maps WorkOS session to Principal, refresh emits rotated session via AuthnResult.setCookies (line 267-274)
  • WorkOS access-token: createWorkosAccessTokenAuthenticator uses REAL jose JWKS signature verification with createRemoteJWKSet + jwtVerify(token, jwks, { audience: clientId }) (line 205-218) — NOT a decode-only shim
  • better-auth Prisma wrapper: createNetscriptBetterAuth wraps better-auth's own first-party prismaAdapter from better-auth/adapters/prisma (line 113-118)
  • better-auth authenticator: createBetterAuthAuthenticator calls auth.api.getSession({ headers, returnHeaders: true }) and captures Set-Cookie via headersFromBetterAuth (line 140-272)
  • better-auth mount: mountBetterAuthHandler mounts the Fetch handler on Hono app (line 177-186)
  • PLAN-EVAL layering fix honored: @netscript/auth-better-auth does NOT import @netscript/database (consumer brings Prisma client instance at boundary)

Additive-only contract consumption

  • Both packages CONSUME AuthenticatorPort/AuthnRequest/AuthnResult/Principal from @netscript/service/auth (not redefined)
  • Type re-exports in mod.ts are for consumer ergonomics (not redefinition)

Catalog law compliance

  • packages/auth-workos/package.json"@workos-inc/node": "catalog:", "jose": "catalog:"
  • packages/auth-better-auth/package.json"better-auth": "catalog:"
  • Workspace root deno.json:96-114 — catalog block contains better-auth: "^1.6.20", @workos-inc/node: "^10.4.0", jose: "^5.9.2"
  • No de-catalog; @prisma/client/jose pins, packages/aspire/src/public/mod.ts, and scaffold-versions.ts untouched

Validation (independently re-run gates)

Gate Command Exit code Result
Scoped type-check run-deno-check.ts --root packages/auth-workos --root packages/auth-better-auth --ext ts,tsx 0 0 occurrences
Scoped lint run-deno-lint.ts --root packages/auth-workos --root packages/auth-better-auth --ext ts,tsx 0 0 occurrences
Scoped fmt run-deno-fmt.ts --root packages/auth-workos --root packages/auth-better-auth --root .llm/tools/auth --ext ts,tsx --ignore-line-endings 0 11 files, 0 findings
WorkOS tests deno test --allow-net packages/auth-workos/tests/ 0 6 passed, 0 failed
better-auth tests deno test --allow-net --allow-env packages/auth-better-auth/tests/ 0 7 passed, 0 failed
WorkOS doc-lint run-deno-doc-lint.ts --root packages/auth-workos --pretty 0 0 missing JSDoc, 0 private-type-ref
better-auth doc-lint run-deno-doc-lint.ts --root packages/auth-better-auth --pretty 0 0 missing JSDoc, 0 private-type-ref
publish:dry-run deno task publish:dry-run 0 Isolated declarations satisfied, no carve-out

All gates passed with raw exit code 0.

Node-compat smoke verification

  • WorkOS: workos-node-compat_test.ts imports @workos-inc/node@10.4.0 and constructs new WorkOS(...).userManagement.loadSealedSession(...).authenticate() under Deno 2.8.3 node-compat → PASSED (16ms)
  • better-auth: better-auth-node-compat_test.ts imports better-auth@1.6.20 and constructs betterAuth({ secret, baseURL }) under Deno 2.8.3 → PASSED (20ms)

Both provider SDKs resolve and execute under Deno's node-compatibility layer.

Remaining Risks

Recorded deferrals (documented in drift.md, not gate failures)

  1. WorkOS webhook-to-database sync: User/org sync from WorkOS webhooks to database remains deferred (documented optional fast-follow per plan §1 out-of-scope)
  2. CLI scaffold prompts: Auth provider selection prompts for CLI scaffold remain deferred (not in slice scope)
  3. Pre-existing repo-wide findings: deno task arch:check + deps:audit still report pre-existing undici/vite advisories and repository-wide doctrine failures outside the new auth adapter packages (per drift.md lines 14-17)

Operational considerations

  • Consumer owns running better-auth Prisma migration (plan §1 out-of-scope + locked decision 9). Slice ships generation + wiring; migration step is NOT a runtime dep
  • Services must configure NetScript auth exemption/allowAnonymous policy for /api/auth/** when using mountBetterAuthHandler (per worklog slice 5)
  • Catalog pins better-auth ^1.6.20 + @workos-inc/node ^10.4.0 match npm dist-tags.latest as of evaluation (verified in plan-eval)

Next Steps

Branch feat/prime-time/service-auth-adapters is ready to merge to umbrella branch feat/framework-prime-time. All six implementation slices are complete, tested, documented, and gate-verified. The umbrella PR #83 can proceed with this slice plus the already-merged service-auth-seam (#77).


Evaluator session: Separate-session IMPL-EVAL, cycle 1, 2026-06-20
Evaluation artifacts: .llm/tmp/run/feat-framework-prime-time--supervisor/slices/service-auth-adapters/evaluate.md
Raw gate logs: /tmp/eval-{check,lint,fmt}.{log,txt} (local to evaluator session)

Run: https://github.com/rickylabs/netscript/actions/runs/27867455720

@rickylabs
rickylabs merged commit 2e543a7 into feat/framework-prime-time Jun 20, 2026
1 check passed
rickylabs added a commit that referenced this pull request Jun 20, 2026
…erges into umbrella

Both squash-merged into feat/framework-prime-time after separate-session
IMPL-EVAL PASS (qwen3.7-max, cycle 1). Track-4 auth-kv-oauth PLAN-EVAL is
in flight on #73.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018fq9V7ujx7e1rWXi57qkPG
rickylabs added a commit that referenced this pull request Jun 20, 2026
…oval)

Wrapping plan that rescopes auth from standalone adapters into the standard
core-package + plugin shape, per user pivot:

- NEW @netscript/plugin-auth-core (mirrors plugin-sagas-core): oRPC auth.contract
  v1, stream-event schema, AuthBackendPort + selection seam, config/presets.
- NEW plugins/auth (mirrors plugins/sagas): unified /auth/* oRPC service,
  real-time streams (v1), CLI, database/auth.prisma, scaffold + Aspire, e2e gates.
- Backends (@netscript/auth-{workos,better-auth,kv-oauth}) refactored to PURE
  AuthBackendPort: no mount, no schema-gen, no CLI. Reach-back refactor of the
  landed #83 contribution leak (gen-better-auth-prisma + per-adapter Hono mount).
- oRPC + streams are v1 (every peer plugin ships them), not deferred.
- 3-level stacked PR topology per netscript-pr skill: #73 prime-time umbrella
  -> feat/prime-time/auth (auth umbrella, sub-PR of #73) -> AS1..AS6 leaf sub-PRs.
  kv-oauth = paused AS2b, resumes by pulling umbrella once AS1 lands.
- Absorbs the Track-4 auth-kv-oauth PLAN-EVAL PASS as the AS2b backend (~70%).

DRAFT — no implementation, no PR open/rename before user approval + PLAN-EVAL PASS.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018fq9V7ujx7e1rWXi57qkPG
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants