Skip to content

Fix 5-min logout, deploy-time JWKS, and stream append skeleton flash#1410

Merged
jonastemplestein merged 2 commits into
mainfrom
fix-token-refresh-stream-flash
Jun 10, 2026
Merged

Fix 5-min logout, deploy-time JWKS, and stream append skeleton flash#1410
jonastemplestein merged 2 commits into
mainfrom
fix-token-refresh-stream-flash

Conversation

@jonastemplestein

@jonastemplestein jonastemplestein commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #1408. Three reliability fixes on the OS/auth path, one branch.

1. ~5-minute logout (root cause from library source)

@better-auth/oauth-provider's refresh-token grant rotates the refresh token on every use and, on reuse of an already-rotated token, revokes the entire token family (handleRefreshTokenGrantcreateRefreshToken marks the old token revoked, and a later reuse deletes all of the user+client's refresh tokens). A normal OS page load fires several concurrent requests; once the 5-minute access token was within the 30s refresh skew, each request independently hit the token endpoint with the same cookie token — the first rotated it, the rest looked like theft and nuked the session → logout, repeating roughly every 5 minutes.

Fixes (apps/auth/src/lib/server.ts, the SDK OS bundles):

  • Single-flight refresh per refresh token — concurrent refreshes collapse to one token-endpoint call (createSingleFlight, extracted + unit-tested).
  • Never refresh on WebSocket upgrades — an upgrade response can't carry Set-Cookie, so refreshing there would rotate the token into a response the browser can't store and strand the session (this is also the REPL websocket failure: once the access token went stale, the capnweb upgrade tried to refresh, failed, and 401'd).
  • Tolerate a failed refresh while the access token is still valid — serve the request and let a later one retry, instead of dropping the session on any hiccup.
  • Access-token TTL 5m → 30m (auth-plugins.ts) so refresh is rare. Tradeoff: org/project claim changes propagate within ≤30m (mitigated for the creator by client cache seeding).

2. Deploy-time JWKS (apps/os/alchemy.run.ts)

#1408 verified JWTs locally from a static JWKS but relied on a hand-set Doppler secret. Now the alchemy script fetches <issuer>/jwks at deploy time into APP_CONFIG (typesafe), so key rotation only needs an OS redeploy. A loopback issuer (local dev auth, own keys) skips the static JWKS; a failed fetch falls back to runtime JWKS. Verified: preview-5 deploy log shows the JWKS baked into config and the worker healthy with zero auth-worker roundtrips.

3. Stream append skeleton flash (apps/os/.../project-stream-view.tsx)

On append the virtualized window shifted (the list grows and the view force-scrolled to the bottom), which re-created the visible-range SQL query. stream-browser-db.query() seeds a new range query as pending carrying a different range's rows, so rowsByIndex missed the visible indices and every visible row blanked to a grey bg-slate-100 skeleton for a frame — the "skeleton flash + all rows redraw". Fixes: retain the last committed rows across range re-queries (only genuinely-new indices fall back to a skeleton), and only auto-scroll to the bottom when already pinned there (don't yank a scrolled-up reader and trigger a full-window re-query).

Proof status (being precise)

  • Refresh single-flight: proven by apps/os/src/auth/iterate-auth-single-flight.test.ts (deterministic) + root cause read from the oauth-provider source. The end-to-end "wait 5 minutes in a browser" proof was not completed: production auth is Google-only (no headless sign-in) and doesn't honor service-token impersonation at the public oauth2/authorize, and the fixed local stack now issues 30m tokens. Worth a manual 5-min check after this deploys to prod auth.
  • Deploy-time JWKS: verified on a real preview-5 deploy.
  • Stream flash: fix is code-reasoned and safe (retain-last-rows + sticky-scroll); not pixel-verified — the local headless harness was too unstable (Chrome OOM, dev issuer drift) to capture the sub-second flash reliably. See apps/os/docs/headless-local-debugging.md.

Docs

apps/os/docs/headless-local-debugging.md — driving the full local OS+Auth stack headlessly (test OTP 424242, signup allowlist, orgs/projects, OAuth/consent quirks, reading local D1, MutationObserver over throttled timers).

pnpm typecheck && pnpm lint && pnpm test all green.

🤖 Generated with Claude Code


Note

High Risk
Changes authentication refresh semantics, WebSocket session behavior, and access-token lifetime—security-critical paths that affect all signed-in users and long-lived connections.

Overview
Addresses three reliability issues on the OS/auth path: periodic session logout, JWT verification at deploy, and stream UI flicker.

Auth session (~5‑minute logout): Adds exported createSingleFlight and wraps refresh-token grants so concurrent requests sharing one cookie collapse to a single token call—avoiding rotated-token reuse that revokes the whole family. Cookie middleware skips refresh on WebSocket upgrades (no Set-Cookie), tolerates refresh failures while the access token is still valid, and extends access-token TTL from 5m to 30m on the auth provider.

OS deploy: alchemy.run.ts fetches issuer JWKS at deploy time into static config (loopback dev skips production JWKS; fetch failure falls back to runtime JWKS).

Stream UI: project-stream-view keeps last committed SQLite rows during virtualizer range re-queries and only auto-scrolls when the user is pinned near the bottom, reducing skeleton flashes on append.

Adds headless-local-debugging.md, README link, and unit tests for createSingleFlight.

Reviewed by Cursor Bugbot for commit 10682c4. Bugbot is set up for automated code reviews on this repo. Configure here.

Environment Config Lease

No active environment config lease.

OS

Status: released
Commit: 10682c4
Preview: https://os.iterate-preview-2.com
Summary: Preview app released.
Workflow run
Updated: 2026-06-10T05:22:42.108Z

jonastemplestein and others added 2 commits June 9, 2026 23:49
Three related reliability fixes on the OS/auth path:

Token refresh / 5-minute logout (apps/auth):
- The oauth-provider rotates the refresh token on every use and treats reuse
  of a rotated token as theft, revoking the entire token family. A normal page
  load fires many concurrent requests; once the 5-minute access token is near
  expiry they all raced the token endpoint with the same cookie token — first
  rotated, the rest looked like reuse and nuked the family, logging the user
  out. Fixes: single-flight refresh per refresh token in the SDK; never refresh
  on WebSocket upgrade requests (they can't carry Set-Cookie back, so a refresh
  there would strand the rotated token); tolerate a failed refresh while the
  current access token is still valid; raise access-token TTL 5m -> 30m so
  refresh is rare.

Deploy-time JWKS (apps/os/alchemy.run.ts):
- Fetch the issuer JWKS at deploy time into APP_CONFIG so the worker verifies
  auth JWTs locally with no runtime roundtrip, including cold isolates. A
  loopback issuer (local dev auth, own signing keys) skips the static JWKS and
  falls back to runtime fetch; fetch failure also falls back gracefully.

Stream append flash (apps/os project-stream-view):
- On append the virtualized window shifted (list grows + forced scroll to
  bottom), recreating the visible-range SQL query, which briefly reported
  pending carrying a different range's rows and blanked every visible row to a
  grey skeleton. Now retain the last committed rows across range re-queries and
  only auto-scroll to the bottom when already pinned there.

Docs: apps/os/docs/headless-local-debugging.md — how to drive the full local
stack headlessly (test OTP, orgs/projects, OAuth, reading local D1).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pull the per-refresh-token single-flight out of the SDK's doRefresh into an
exported createSingleFlight helper and cover it with a deterministic test:
concurrent calls for one token collapse to a single token-endpoint hit (the
fix for the family-revoke logout), independent tokens run independently,
the entry clears on settle so the next rotated token refreshes cleanly, and
a rejected refresh propagates to all waiters and lets the next call retry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jonastemplestein jonastemplestein merged commit ad6da76 into main Jun 10, 2026
9 checks passed
@jonastemplestein jonastemplestein deleted the fix-token-refresh-stream-flash branch June 10, 2026 05:20
jonastemplestein added a commit that referenced this pull request Jun 10, 2026
- tasks/cf-prd-orphaned-resources-cleanup.md: completed — prd account is down to 14 worker scripts and 6 D1 databases per live 2026-06-10 Cloudflare API check (was 1026 at the 2026-05-18 sweep)
- tasks/complete/2026-05-22-os-captun-worker-test-tunnel.md: completed — shipped via merged PR #1361; all described artifacts exist on main and survived the golden-path rebuild (#1411)
- tasks/dead-code-and-docs-cleanup-audit.md: completed — all high-confidence items shipped; pnpm-workspace.yaml now uses apps/*/packages/* globs and no longer lists the dead packages
- tasks/github-oauth-use-repo-id.md: obsolete — all referenced code (linkExternalIdToGroups / repoId / repository.id) is gone repo-wide
- tasks/ignoreme-email-security.md: obsolete — every targeted code path was deleted with the legacy OS1 stack in commit 545854d (#1341)
- tasks/os-auth-spurious-logout-refresh.md: completed — commit ad6da76 (#1410, merged 2026-06-10) shipped exactly this work
- tasks/os-codemode-router.md: completed — task file was added in the very PR that implemented it (commit 98ee148, #1294)
- tasks/os-domain-capability-orpc-refactor-design.md: completed — every major pillar of the design (domains layout, capabilities, oRPC structure) exists on main
- tasks/os-domain-capability-orpc-refactor-prd.md: completed — shipped in PR #1305 "Make codemode function calls event-driven" (squash commit 284193e, merged 2026-05-08)
- tasks/os-stream-runtime-big-refactors.md: obsolete — os2-era brainstorm list largely superseded or done differently; item 2 shipped via PR #1394
- tasks/realtime-pusher-efficiency.md: obsolete — targets the legacy OS1 realtime pusher, which no longer exists
- tasks/semaphore-lease-renewal.md: completed — lease renewal exists on main as resources.renew in apps/semaphore
- tasks/signup-slug-uniqueness.md: completed — shipped with the auth worker (PR #1273); packages/shared/src/slug.ts implements resolveUniqueSlug/slugifyWithSuffix
- tasks/stream-processor-ergonomics.md: obsolete — targets the legacy hook-style processor API replaced by the class-based StreamProcessor model
- apps/os/tasks/codemode-session-night-plan.md: completed — planned outcomes verifiably shipped on main in evolved form (codemode session UI and friends)
- apps/os/tasks/codemode-session-vertical-slice.md: completed — all 11 ticked checklist items shipped via PRs #1294/#1305 and follow-ups
- apps/os/tasks/refactor-lifecycle-init-params-as-structured-name.md: completed — every acceptance criterion implemented in with-lifecycle-hooks.ts mixin on main
- apps/os/tasks/repos-vertical-slice.md: completed — frontmatter says state: done and the described slice exists on main
- apps/os/tasks/slack-google-auth-poc-implementation.md: historical log — explicitly an implementation log (state: done); work shipped in merged PR #1317
- apps/os/tasks/slack-processor-unwind.md: completed — all target-shape items exist on main (/integrations/slack stream path, no webhooks refs)
- apps/os/tasks/stream-processor-class-design-notes.md: historical log — design notes written alongside the class-based StreamProcessor migration, not a task
- apps/os/tasks/workspace-codemode-implementation-log.md: historical log — frontmatter state: done, all 9 checkpoints ticked, work verifiably shipped on main

Already deleted by earlier commits on this branch (skipped):
apps/os/tasks/project-egress-secrets-mvp.md,
apps/os/tasks/simplify-context-cloudflare-native.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jonastemplestein added a commit that referenced this pull request Jun 10, 2026
- tasks/cf-prd-orphaned-resources-cleanup.md: completed — prd account is down to 14 worker scripts and 6 D1 databases per live 2026-06-10 Cloudflare API check (was 1026 at the 2026-05-18 sweep)
- tasks/complete/2026-05-22-os-captun-worker-test-tunnel.md: completed — shipped via merged PR #1361; all described artifacts exist on main and survived the golden-path rebuild (#1411)
- tasks/dead-code-and-docs-cleanup-audit.md: completed — all high-confidence items shipped; pnpm-workspace.yaml now uses apps/*/packages/* globs and no longer lists the dead packages
- tasks/github-oauth-use-repo-id.md: obsolete — all referenced code (linkExternalIdToGroups / repoId / repository.id) is gone repo-wide
- tasks/ignoreme-email-security.md: obsolete — every targeted code path was deleted with the legacy OS1 stack in commit 545854d (#1341)
- tasks/os-auth-spurious-logout-refresh.md: completed — commit ad6da76 (#1410, merged 2026-06-10) shipped exactly this work
- tasks/os-codemode-router.md: completed — task file was added in the very PR that implemented it (commit 98ee148, #1294)
- tasks/os-domain-capability-orpc-refactor-design.md: completed — every major pillar of the design (domains layout, capabilities, oRPC structure) exists on main
- tasks/os-domain-capability-orpc-refactor-prd.md: completed — shipped in PR #1305 "Make codemode function calls event-driven" (squash commit 284193e, merged 2026-05-08)
- tasks/os-stream-runtime-big-refactors.md: obsolete — os2-era brainstorm list largely superseded or done differently; item 2 shipped via PR #1394
- tasks/realtime-pusher-efficiency.md: obsolete — targets the legacy OS1 realtime pusher, which no longer exists
- tasks/semaphore-lease-renewal.md: completed — lease renewal exists on main as resources.renew in apps/semaphore
- tasks/signup-slug-uniqueness.md: completed — shipped with the auth worker (PR #1273); packages/shared/src/slug.ts implements resolveUniqueSlug/slugifyWithSuffix
- tasks/stream-processor-ergonomics.md: obsolete — targets the legacy hook-style processor API replaced by the class-based StreamProcessor model
- apps/os/tasks/codemode-session-night-plan.md: completed — planned outcomes verifiably shipped on main in evolved form (codemode session UI and friends)
- apps/os/tasks/codemode-session-vertical-slice.md: completed — all 11 ticked checklist items shipped via PRs #1294/#1305 and follow-ups
- apps/os/tasks/refactor-lifecycle-init-params-as-structured-name.md: completed — every acceptance criterion implemented in with-lifecycle-hooks.ts mixin on main
- apps/os/tasks/repos-vertical-slice.md: completed — frontmatter says state: done and the described slice exists on main
- apps/os/tasks/slack-google-auth-poc-implementation.md: historical log — explicitly an implementation log (state: done); work shipped in merged PR #1317
- apps/os/tasks/slack-processor-unwind.md: completed — all target-shape items exist on main (/integrations/slack stream path, no webhooks refs)
- apps/os/tasks/stream-processor-class-design-notes.md: historical log — design notes written alongside the class-based StreamProcessor migration, not a task
- apps/os/tasks/workspace-codemode-implementation-log.md: historical log — frontmatter state: done, all 9 checkpoints ticked, work verifiably shipped on main

Already deleted by earlier commits on this branch (skipped):
apps/os/tasks/project-egress-secrets-mvp.md,
apps/os/tasks/simplify-context-cloudflare-native.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jonastemplestein added a commit that referenced this pull request Jun 10, 2026
…capnweb pointers, fix task states (#1432)

Documentation sweep over `apps/os`. Every statement written into a doc
was verified against the code on this branch.

## Changes

**`apps/os/README.md` (= `AGENTS.md`)**
- Important Files: `src/app.ts` / `src/entry.workerd.ts` do not exist —
replaced with `src/worker.ts` (Worker entrypoint) and `src/config.ts`
(`AppConfig` schema). All other listed files verified to exist.
- Real-worker tests: the documented vitest configs
(`src/capnweb/e2e/vitest.config.ts`,
`src/domains/capability-prototype/e2e.vitest.config.ts`) are gone —
replaced with the real lanes `pnpm e2e` (`e2e/vitest.config.ts`) and
`pnpm e2e:itx` (`src/itx/e2e/vitest.config.ts`), verified against
`apps/os/package.json`.
- `pnpm cf:deploy # production deploy` was wrong and dangerous:
`cf:deploy` deploys to whatever Doppler/Alchemy stage is ambient. Now
documents both `cf:deploy` (ambient stage) and `pnpm deploy` (the
`doppler --config prd` wrapper).
- Removed the nonexistent `/org/:organizationSlug` route; remaining
routes verified against `src/routes/`; added `/new-project`.

**`apps/os/CONTEXT.md`** — fixed the example-dialogue claim that
organization UI lives under `/org/:organizationSlug` (no such route;
orgs live in the auth worker).

**`apps/os/docs/architecture-and-operations.md`** — rewritten. The old
doc described the pre-migration world: Clerk auth (whole `## Clerk`
section, `sync-clerk-apps.ts`, `APP_CONFIG_CLERK__*`),
`/orgs/:organizationSlug` route maps, inbound MCP via
`ProjectMcpServerEntrypoint` (now a hardcoded 410 tombstone), wrong
redirect claims, and an unprefixed `/durable-objects/stream` debug
route. The new doc describes current reality: `src/worker.ts` dispatch
pipeline, Iterate Auth middleware, real route map and root-redirect
behavior (`/` → `/projects/$projectSlug` or `/projects`; project root
renders `ProjectHomePage`), canonical MCP endpoint from
`APP_CONFIG_MCP__BASE_URL` with Iterate Auth protected-resource
metadata, `/__durable-objects/<kind>/<name>/<path>` debug proxy (kinds
verified), itx endpoints, `scripts/sync-auth-clients.ts`, current
codemode default/example providers, and current smoke-test env vars
(verified in the e2e test files).

**`apps/os/docs/headless-local-debugging.md`** — `/projects/new` → the
real route `/new-project`.

**`apps/os/docs/iterate-context.md`, `iterate-context-learnings.md`** —
both pointed at the deleted `src/capnweb/` tree as "the current design";
now short tombstones pointing at the successor (`src/itx/` README +
DECISIONS, `docs/itx-spec.md`).

**`apps/os/docs/capability-system-research-and-design-notes.md`,
`rpc-target-constructor-shape-research.md`** — added status headers
marking them historical research notes superseded by itx; bodies
untouched.

**`apps/os/src/itx/README.md` + `src/itx/handle.ts`** — the "Typed caps"
`ProjectCaps` declaration-merging pattern does not exist in code (no
`ProjectCaps` interface anywhere). Rewrote the README section to the
thing that actually works: casting `itx.cap("name")` through the
exported `Stubify<T>` type. Also fixed the same false claim in the
`Stubify` doc comment in `handle.ts` (comment-only change).

**`apps/os/docs/itx-spec.md`** — status header said "IMPLEMENTED on the
`itx-implementation` branch"; PR #1407 is merged to main (verified in
git history). Marked the one known divergence honestly: the §6.3 client
reconnect loop was never built — `connectItx` (`src/itx/client.ts`) is
one-shot, and there is no `itx.cap.disconnected` event. Corrected §6.3
and the related §4 caveat.

**`apps/os/tasks/`**
- Deleted `simplify-context-cloudflare-native.md` (state: todo, but
shipped — `src/worker.ts` imports `env` from `cloudflare:workers`
directly, `RequestContext` is the narrow request-scoped shape the task
specified, auth lives in Start request middleware, the
manifest/`src/app.ts` is gone).
- Deleted `project-egress-secrets-mvp.md` (state: todo, but shipped —
`ProjectEgress` entrypoint, `ProjectDurableObject.egressFetch` with
`substituteProjectEgressSecretHeaders`, D1-backed
`SecretsCapability.getSecret`, and the `/api/itx/egress-echo` echo proof
covered by `src/itx/e2e/itx-egress.e2e.test.ts`).
- Grooming rules (`docs/tasks-grooming.md`) say "Delete when done", so
deletion rather than state edits.
- Added brief status notes (no rewrite) to
`codemode-session-vertical-slice.md` (checked-off "tiny worker" box
diverged: `CodemodeSession` lives in the main OS worker) and
`codemode-session-night-plan.md` (plan superseded by itx).

## Skipped
- Nothing skipped; all nine items verified and addressed.

## Flags for reviewers
- `src/itx/handle.ts` got a comment-only edit (the `Stubify` doc comment
made the same false declaration-merging claim as the README). No runtime
change; typecheck/lint/tests pass.
- The two deleted task files: please sanity-check the "shipped" verdicts
above if you have more context on intended remaining scope.
- Carve-outs respected: no changes to the streams type systems or to how
the os-streams worker is deployed.

## Checks
- `pnpm install`, `pnpm format` (oxfmt), `pnpm typecheck`, `pnpm lint`,
`pnpm test` — all pass.

## Task-file audit

A follow-up commit deletes 22 task files whose work was verified as
shipped, obsolete, or purely historical. (Two more from the audit —
`apps/os/tasks/project-egress-secrets-mvp.md` and
`apps/os/tasks/simplify-context-cloudflare-native.md` — were already
deleted by earlier commits on this branch, see above.)

### Deleted: completed

- `tasks/cf-prd-orphaned-resources-cleanup.md` — live Cloudflare API
check of the prd account (2026-06-10) shows 14 worker scripts (was 1026
at the task's 2026-05-18 sweep) and 6 D1 databases; cleanup is done.
- `tasks/complete/2026-05-22-os-captun-worker-test-tunnel.md` — shipped
via merged PR #1361 ("codemode++ e2e++"); all described artifacts exist
on main and survived the golden-path rebuild (#1411).
- `tasks/dead-code-and-docs-cleanup-audit.md` — high-confidence items
all shipped; `pnpm-workspace.yaml` no longer lists the dead packages and
now uses `apps/*`/`packages/*` globs.
- `tasks/os-auth-spurious-logout-refresh.md` — commit ad6da76 "Fix
5-min logout, deploy-time JWKS, and stream append skeleton flash
(#1410)" (merged 2026-06-10) shipped exactly this work.
- `tasks/os-codemode-router.md` — task file was added in the very PR
that implemented it (commit 98ee148, #1294).
- `tasks/os-domain-capability-orpc-refactor-design.md` — every major
pillar of the design (domains layout, capabilities, oRPC structure)
exists on main.
- `tasks/os-domain-capability-orpc-refactor-prd.md` — shipped in PR
#1305 "Make codemode function calls event-driven" (squash commit
284193e, merged 2026-05-08).
- `tasks/semaphore-lease-renewal.md` — the described lease-renewal
feature exists on main as `resources.renew` (named "renew" rather than
the proposed "extend") in `apps/semaphore`.
- `tasks/signup-slug-uniqueness.md` — shipped with the auth worker (PR
#1273); `packages/shared/src/slug.ts` implements
`resolveUniqueSlug`/`slugifyWithSuffix`.
- `apps/os/tasks/codemode-session-night-plan.md` — planned outcomes
verifiably shipped on main, in evolved form (codemode session browser UI
and follow-ons).
- `apps/os/tasks/codemode-session-vertical-slice.md` — all 11 ticked
checklist items shipped via PRs #1294/#1305 and follow-ups.
- `apps/os/tasks/refactor-lifecycle-init-params-as-structured-name.md` —
every acceptance criterion implemented in the `with-lifecycle-hooks.ts`
mixin on main.
- `apps/os/tasks/repos-vertical-slice.md` — frontmatter already says
`state: done` and the described slice verifiably exists on main.
- `apps/os/tasks/slack-processor-unwind.md` — all target-shape items
exist on main (`/integrations/slack` stream path; no
`/integrations/slack/webhooks` references).

### Deleted: obsolete / nonsense

- `tasks/github-oauth-use-repo-id.md` — all referenced code is gone:
`linkExternalIdToGroups` / `repoId` / `repository.id` return zero hits
repo-wide.
- `tasks/ignoreme-email-security.md` — every code path the task targets
was deleted with the legacy OS1 stack (commit 545854d, #1341).
- `tasks/os-stream-runtime-big-refactors.md` — os2-era brainstorm list
largely superseded or done differently; item 2 shipped via PR #1394.
- `tasks/realtime-pusher-efficiency.md` — targets the legacy OS1
realtime pusher, which no longer exists.
- `tasks/stream-processor-ergonomics.md` — targets the legacy hook-style
processor API, replaced by the class-based StreamProcessor model.

### Deleted: historical logs

- `apps/os/tasks/slack-google-auth-poc-implementation.md` — explicitly
an "Implementation Log" (`state: done`), not actionable work; shipped in
merged PR #1317.
- `apps/os/tasks/stream-processor-class-design-notes.md` — design notes
written alongside the class-based StreamProcessor migration, not a task.
- `apps/os/tasks/workspace-codemode-implementation-log.md` — `state:
done`, all 9 checkpoints ticked; the described work verifiably shipped
on main.

### Kept but flagged for maintainer judgment

- `tasks/cf-prd-orphaned-resources-cleanup.md`: Explicit not-in-scope
follow-ups (preview account 376ef7ed cleanup, Doppler os-legacy-backup
pruning) were never broken out into their own tasks; spin them out only
if still wanted.
- `tasks/codemode-capability-policy.md`: Still-unshipped, still-wanted
design work, but duplicates
`apps/os/tasks/codemode-capability-access-policy.md` and overlaps the
active itx capability-system design notes — maintainer should
consolidate into a single task.
- `tasks/complete/2026-05-22-os-captun-worker-test-tunnel.md`: apps/os
still depends on the unpublished pkg.pr.new/captun@14 build (the task's
stated stopgap); a published captun/worker release would be a separate
follow-up, not a reason to keep this file.
- `tasks/dead-code-and-docs-cleanup-audit.md`: Residual from this audit:
packages/iterate is still excluded from root build/typecheck/test
(`--filter '!iterate'`); if that CI gap matters, open a fresh small task
rather than keeping this stale inventory.
- `tasks/doppler-shared-and-os-secrets-audit.md`: Audit still unrun and
wanted, but needs a rewrite first: replace Clerk-key expectations with
iterateAuth, point AppConfig refs at `apps/os/src/config.ts` (`app.ts`
and `packages/shared/src/apps/config.ts` were deleted in PR #1411), and
refresh the 2026-05-18 baseline.
- `tasks/ignoreme-email-security.md`: If outbound email via Resend is
ever reintroduced in the rebuilt apps/os, recipient allowlisting should
be designed fresh against the itx/egress-secret-substitution layer, not
this OS1-era plan.
- `tasks/iterate-cli-distribution.md`: Live but ~90% of the file is
OpenCode architecture research notes, not actionable steps; npm
distribution already exists, so the remaining work (bun binary, brew,
install script) should be restated as concrete tasks or the research
trimmed.
- `tasks/os-auth-spurious-logout-refresh.md`: PR #1410 left one open
thread: a manual end-to-end "wait 5 minutes in prod" verification was
never done, and the claims-staleness force-refresh was consciously
skipped (≤30m propagation accepted) — file a new narrow task only if
either still matters.
- `tasks/os-deploy-time-jwks-fetch.md`: Code shipped in PR #1410; only
remaining action is deleting `ITERATE_AUTH_JWKS` from Doppler os
prd/preview (still present and shadowing the deploy-time fetch) — after
that, delete this task.
- `tasks/os-domain-capability-orpc-refactor-prd.md`: Sibling task
`os-domain-capability-orpc-refactor-design.md` (its dependsOn target) is
likely also completed and should be audited/deleted together.
- `tasks/os-project-do-projection-reconciliation.md`: Scope item "rename
IterateMcpServer to ProjectMcpServerConnection" is already done and
could be ticked off; the rest is unshipped and still relevant.
- `tasks/os-project-hostname-base-singular.md`: Scope file paths are
stale post-PR #1411 (`app.ts`→`src/config.ts`,
`sync-clerk-apps.ts`→`sync-auth-clients.ts`, `entry.workerd.ts` deleted,
routing files moved to `src/ingress/`); task itself is still valid.
- `tasks/os-project-route-authorization.md`: Still-wanted design work
(referenced by live project-ingress-architecture task), but needs
rewrite: Clerk OAuth and `ProjectMcpServerEntrypoint` references are
dead — MCP moved off project ingress (410 stub) and auth is now
apps/auth Principal-based.
- `tasks/os-stream-runtime-big-refactors.md`: Only surviving idea:
cosmetic no-compat rename of `events.iterate.com/...` event-type names
(events app is deleted); re-file as a small standalone task if still
wanted.
- `apps/os/tasks/codemode-capability-access-policy.md`: Live work, but
near-duplicates root-level `tasks/codemode-capability-policy.md` (same
PR #1294); keep this copy and consolidate/delete the root one.
- `apps/os/tasks/codemode-session-night-plan.md`: Open capability-scope
questions from this plan live on in
`codemode-capability-access-policy.md`; checkboxes are unticked but the
work shipped via PRs #1294/#1305/#1402.
- `apps/os/tasks/codemode-session-vertical-slice.md`: Last unchecked box
(generalize self-callable bindings) shipped as the loopback-binding
pattern used repo-wide; follow-on work lives in
`codemode-session-night-plan.md`.
- `apps/os/tasks/project-egress-and-secrets-architecture.md`: Design doc
whose first vertical slice shipped (egress + secret substitution MVP);
remaining secret-DO/policy/approval/OAuth design is still live but needs
grooming: drop completed PoC sections, update Clerk-scope terminology,
and reconcile with itx DECISIONS.md as the newer design-of-record for
egress wiring.
- `apps/os/tasks/project-egress-intercept-tunnel-latency.md`:
Still-relevant latency work, but file refs are stale (`entry.workerd.ts`
→ `src/worker.ts`; vendored `apps/os/src/lib/captun` removed for the
published captun package in #1361) and the benchmark numbers predate the
#1411 worker rebuild — re-benchmark before picking an option.
- `apps/os/tasks/project-ingress-architecture.md`: Live,
actively-maintained ingress reference (edited today in #1416), but needs
a refresh: Clerk auth sections, `Project.checkAccess`, and the
streams-upstream proxy model are superseded (auth worker, principal
claims, bundled project worker), and the 2026-05-05 status checklist is
partly outdated.
- `apps/os/tasks/stream-processor-class-migration-log.md`: Migration log
(merged today via #1402, which links to it as the canonical rationale) —
not an actionable task; contains unique I6-I8 forensics not in the PR
body, consider moving to docs/ alongside `tasks/migration-notes/` rather
than deleting.
- `apps/os/tasks/stream-subscriber-delivery-refactor.md`: Core design
shipped differently via the class-model cutover (#1401/#1402/#1394);
only live remainder is migrating `codemode.streamEvents`,
`StreamsCapability.stream()`, and project-mcp-server-connection off the
OS-internal NDJSON shim in `new-stream-runtime.ts` — consider replacing
this large draft with a small task for that.
- `apps/os/tasks/workspace-codemode-implementation-log.md`: Done
implementation log; only marginally unique note is the rationale that
plain method objects (not class instances) cross DO RPC, which is now
embodied in the shipped workspace DO code.
- `apps/os/tasks/migration-notes/`: Historical migration logs (not
tasks) committed with and cited by merged PR #1402 one day ago; contain
unique per-domain decisions plus the legacy-subscriber gap behind the
2026-06-10 prd Slack outage — maintainer should relocate to docs/ or
delete deliberately.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Documentation and task-file deletions only; no application runtime or
API behavior changes in the diff.
> 
> **Overview**
> **Aligns OS documentation with the current worker, auth, routing, and
itx reality**, and **removes a large set of completed or obsolete task
files** from `apps/os/tasks/` and `tasks/`.
> 
> The **README / AGENTS** and **`architecture-and-operations.md`**
rewrites drop Clerk-era and deleted-entrypoint references (`src/app.ts`,
`src/entry.workerd.ts`, `/org/:organizationSlug`) in favor of
**`src/worker.ts`**, **Iterate Auth**, **project-scoped routes**
(`/projects/...`, `/new-project`), **canonical MCP**
(`APP_CONFIG_MCP__BASE_URL`, auth-worker OAuth), **itx** endpoints, and
**`sync-auth-clients.ts`**. Deploy docs now distinguish ambient **`pnpm
cf:deploy`** from production **`pnpm deploy`**. E2E docs point at
**`pnpm e2e`** and **`pnpm e2e:itx`** instead of removed capnweb vitest
configs.
> 
> **Cap'n Web tombstones** in `iterate-context*.md` redirect readers to
**itx** (`src/itx/`, `itx-spec.md`). Research notes get **historical**
headers; **itx-spec** notes merged status on main and documents that
**`connectItx` is one-shot** (no §6.3 reconnect loop). **itx README /
`Stubify`** docs are corrected: typed caps use **`itx.cap("name") as
Stubify<...>`**, not declaration merging.
> 
> **CONTEXT.md** fixes the example that claimed org UI lived under
`/org/...`. **headless-local-debugging** uses **`/new-project`**.
> 
> **Task grooming** deletes many markdown tasks whose work is done,
superseded (itx, auth worker), or OS1-dead — including codemode
vertical-slice plans, domain oRPC refactor design, egress MVP, Slack
processor unwind, and similar inventory items.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
a4f093f. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- CLOUDFLARE_PREVIEW -->
## Environment Config Lease
<!-- CLOUDFLARE_PREVIEW_STATE -->
<!--
{
  "apps": {
    "os": {
      "appDisplayName": "OS",
      "appSlug": "os",
      "status": "deployed",
      "updatedAt": "2026-06-10T12:23:34.040Z",
      "headSha": "a4f093f29684fc65b851dbf53847ccd85ddf8ffc",
      "message": null,
      "publicUrl": "https://os.iterate-preview-5.com",
"runUrl": "https://github.com/iterate/iterate/actions/runs/27275677688",
      "shortSha": "a4f093f"
    }
  },
  "environmentConfigLease": {
    "dopplerConfig": "preview_5",
    "leasedUntil": 1781097591555,
    "leaseId": "36e57584-6cc7-4024-a027-103a3cb0b29b",
    "slug": "preview-5",
    "type": "environment-config-lease"
  }
}
-->
<!-- /CLOUDFLARE_PREVIEW_STATE -->
Lease: `preview-5`
Doppler config: `preview_5`
Type: `environment-config-lease`
Leased until: 2026-06-10T13:19:51.555Z

### OS
Status: deployed
Commit: `a4f093f`
Preview: https://os.iterate-preview-5.com
[Workflow
run](https://github.com/iterate/iterate/actions/runs/27275677688)
Updated: 2026-06-10T12:23:34.040Z
<!-- /CLOUDFLARE_PREVIEW -->

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
mmkal added a commit that referenced this pull request Jun 10, 2026
Replaces the `merge-to-main-slack` workflow (one Slack message per
merged PR — noisy on busy days) with a workflow that maintains **at most
one message per day** in `#ci`: a one-line PR dashboard summary, with
the full per-PR breakdown in a single threaded reply. Both are created
on the first PR event of the day and updated in place after that.

Channel message:

> **PR dashboard 10th June** — 51 merged · 9 closed without merging · 4
opened · 2 older still open (details in thread)

Threaded reply (rendered from real data):

> **Merged:**
> • [#1410 Fix 5-min logout, deploy-time JWKS, and stream append
skeleton flash](#1410) by jonas
(ad6da76)
> • [#1407 itx: contexts, capabilities, and the one true
handle](#1407) by jonas (f256768)
> …
> **Closed without merging:**
> • [#1440 Migrate captun to published npm
0.0.3](#1440) by misha
> …
> **Opened:**
> • [#1448 Replace per-merge Slack messages with a daily PR
dashboard](#1448) by misha
(draft)
> …
> Old: [#1349](#1349),
[#1355](#1355)

How it works:

- Content is refetched from the GitHub search API on every run (merged /
closed-unmerged / opened-and-still-open today, plus older open PRs), so
the message is self-healing — no incremental state to corrupt.
- The day's message timestamps live in a repo Actions variable
(`SLACK_PR_DASHBOARD_STATE`, `{date, channel, ts, details_ts}`), written
with the same `ITERATE_BOT_GITHUB_TOKEN` the nag workflow uses. No new
Slack scopes needed: `chat.update` uses the `chat:write` the bot already
exercises.
- Targets `#ci`, adopting #1452's decision to move merge announcements
out of `#building` (that PR edited the workflow this one deletes; the
conflict is resolved here by keeping the deletion).
- The threaded details go out as chunked mrkdwn section blocks rather
than one `text` param: on busy days a single text field hits
`chat.update`'s `msg_too_long` (`postMessage` truncates, `update`
rejects — found by e2e-testing against today's ~50 merges).
- Plain-text author names (no @-mentions) since the messages update many
times a day.
- Testable two ways: pushing any `*pr-dashboard*` branch runs it for
real against `#misha-test` with a separate state variable (create,
update-in-place, and threading paths all verified this way — e.g. runs
[27280068182](https://github.com/iterate/iterate/actions/runs/27280068182),
[27288814028](https://github.com/iterate/iterate/actions/runs/27288814028)),
and `node cli.ts github-script
pr-dashboard.update_dashboard.update_pr_dashboard --github-token ...`
does a local dry run that prints both messages.

Task file: `tasks/slack-daily-pr-dashboard.md`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant