Skip to content

auth: internal mint-project-id endpoint (prerequisite for #1485)#1489

Merged
jonastemplestein merged 1 commit into
mainfrom
auth-mint-project-id
Jun 11, 2026
Merged

auth: internal mint-project-id endpoint (prerequisite for #1485)#1489
jonastemplestein merged 1 commit into
mainfrom
auth-mint-project-id

Conversation

@jonastemplestein

@jonastemplestein jonastemplestein commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

What

Adds POST /internal/project/mint-project-id (service middleware) to the auth worker + contract: mints a canonical prj_ id without creating an auth-side project record.

Why

#1485 makes auth the ONLY minter of the prj_ id space — OS's operator/recovery create path round-trips through this endpoint instead of minting locally. Previews point at production auth, so this must deploy from main BEFORE #1485 can pass preview e2e (its preview run currently 404s on this route).

Purely additive — extracted verbatim from #1485; nothing calls it until that PR lands.

Testing

🤖 Generated with Claude Code


Note

Low Risk
Additive internal route behind existing service auth; no DB writes and no production callers until a dependent PR lands.

Overview
Adds a service-only internal API so auth can hand out canonical prj_* ids without creating an auth project row—intended for OS operator/recovery creates that have no owning organization.

The auth-contract defines POST /internal/project/mint-project-id (no input; { id: string } output). The auth worker implements it behind serviceMiddleware, returning generateId("prj") and registers mintProjectId on the internal project router. Nothing in this PR calls the route yet; follow-up work will route OS minting through auth instead of local id generation.

Reviewed by Cursor Bugbot for commit 211c08a. 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: 211c08a
Preview: https://os.iterate-preview-2.com
Summary: Preview app released.
Workflow run
Updated: 2026-06-11T06:33:02.060Z

…y minting)

Adds POST /internal/project/mint-project-id (service-authed): mints a
canonical prj_ id without creating an auth-side project, for OS
operator/recovery creates with no owning organization. Purely additive —
extracted from #1485 so auth deploys ahead of OS consuming it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jonastemplestein jonastemplestein merged commit 17218a3 into main Jun 11, 2026
8 checks passed
@jonastemplestein jonastemplestein deleted the auth-mint-project-id branch June 11, 2026 06:31
jonastemplestein added a commit that referenced this pull request Jun 11, 2026
…tercept dies, kernel shrinks, auth mints, legacy afterAppend deleted (#1485)

## What

The remaining grand-cleanup workstreams in one deliberately breaking PR
(prd gets redeployed). DECISIONS **D23** is the canonical record. Three
main-side PRs landed mid-flight and overlap this work — all adopted
wholesale in the merges: **#1482** (repos/workspace/worker as platform
defaults with origin-carrying delegation), **#1487** (`fetch` is a
shadowable cap, `define` absorbs `provide`, shared registry host), and
**#1490** (intercept tunnel deleted, streams is a cap, best-effort
`onRpcBroken`). This PR contributes the layers below on top of them.

### §9 finished: the egress pipe is stateless
- #1487/#1490 made `fetch` a shadowable platform:project cap and deleted
the tunnel, but kept the DEFAULT pipe inside the Project DO
(`ProjectEgress.call` → `egressFetch`). This PR replaces that terminal
with the stateless **`EgressPipe`** loopback. The Project DO still
supervises every dispatch (live shadows resolve in its registry), but
egress secrets are D1 rows scoped by the registry-injected `projectId`,
so substitution + the real outbound fetch run in a plain isolate and
**secret material never enters the DO**.
- **The Project DO has no fetch surface at all** — no `fetch`, no
`ingressFetch`, no `egressFetch`.

### Worker-loading unification
- `itx/isolate.ts` is the ONE place the platform's trust posture (Law 4
ITERATE scoping, Law 5 egress outbound) is wired into loaded isolates;
the registry's source caps and the project worker both use it. (The
Workers-RPC-safe `onRpcBroken` guard this PR carried shipped
independently in #1490 — main's version adopted.)

### `ProjectCapability` dissolved
The hand-wired forwarder entrypoint is deleted; nothing called it.

### Auth is the ONLY project-id minter
New auth internal route `POST /internal/project/mint-project-id`
(service-authed); OS operator/recovery creates (project directory +
`itx.projects.create`) round-trip through it. `mintProjectId` is deleted
from OS — the `prj_` id space has exactly one source.

### Legacy afterAppend/runner-state deleted
The agent, slack-agent, slack-integration, and repo DOs lose their
`afterAppend` RPCs and fake runner shapes (delivery has been on the host
model for a while). Agent runtime state is now the honest `{ agentPath,
processors: { [slug]: snapshot } }`; slack `ensureReady` returns a plain
snapshot; the agent-stream benchmark updated.

## Deferred to main's posture (from the original plan)
- `project` stays a hardwired built-in (per #1482's kernel choice)
rather than a durable-object default; `DIALABLE_DURABLE_OBJECTS` stays
empty by default (config-gated).
- The egress cap is named `fetch` (per #1487), not `egress`.

## ⚠️ Merge order
**#1489 must merge (and auth deploy) first** — this PR's create paths
round-trip id minting through auth's new
`/internal/project/mint-project-id`, and previews point at production
auth. The preview e2e here 404s until that endpoint is live.

## Breaking changes (intended)
- Agent `runtimeState` shape changed (consumers were shape-agnostic or
updated).
- `egressFetch` is gone from every surface; use `itx.fetch` / the
`egress` cap.

## Testing
- Full repo gates green (typecheck, lint, 35/35 apps/os test files).
- Workers suites: project-ingress 6/6 (incl. live-shadow +
revoke-restores-default), itx-stream-subscribe 13/13.
- `project-mcp-server-connection` fails 2/3 **identically on the branch
base** (verified in a clean worktree) — pre-existing.
- Preview e2e exercises: the egress capability over capnweb (explicit +
implicit doors), the new live-shadow helper, and auth-routed minting.

## Out of scope
- Egress policy-as-data / hold-for-approval (the §9 follow-on).
- Stream processors taking a synchronous SQL client (jam).

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **High Risk**
> Breaking egress and secret-handling semantics (DO no longer
substitutes secrets; interceptors see raw placeholders), new auth
dependency for id minting, and changed agent runtimeState shape affect
security-sensitive paths and deploy ordering.
> 
> **Overview**
> Completes **itx D23**: project egress is a shadowable **`fetch`**
capability whose default terminal is the stateless **`EgressPipe`**
(secret substitution + outbound fetch in a plain isolate), while the
Project DO only supervises registry dispatch. **`fetch` / `egressFetch`
are removed** from the Project DO; **`ProjectCapability`** is deleted.
> 
> Adds **`itx/isolate.ts`** so project workers, source caps, and the run
harness share one **ITERATE + `ProjectEgress` globalOutbound** wiring
path.
> 
> **Auth is the sole `prj_` minter**: OS drops local
**`mintProjectId`**; operator/admin and **`itx.projects.create`** call
auth’s **`mintProjectId`** internal route.
> 
> Removes legacy **`afterAppend`** / runner-shaped RPCs on agent, slack,
and repo DOs; agent **`runtimeState`** is **`{ agentPath, processors
}`** (benchmark updated). Docs mark §8/§9 shipped; live **`fetch`**
shadows see **raw** `getSecret(...)` placeholders (withheld-text mode
removed).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
df5965b. 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-11T10:23:48.699Z",
      "headSha": "df5965b9948016c979fa5a71ae3b991f66e8c42c",
      "message": null,
      "publicUrl": "https://os.iterate-preview-6.com",
"runUrl": "https://github.com/iterate/iterate/actions/runs/27340067055",
      "shortSha": "df5965b"
    }
  },
  "environmentConfigLease": {
    "dopplerConfig": "preview_6",
    "leasedUntil": 1781176786363,
    "leaseId": "9c50031d-b4ce-4f00-a8fe-66a3ff9f9df5",
    "slug": "preview-6",
    "type": "environment-config-lease"
  }
}
-->
<!-- /CLOUDFLARE_PREVIEW_STATE -->
Lease: `preview-6`
Doppler config: `preview_6`
Type: `environment-config-lease`
Leased until: 2026-06-11T11:19:46.363Z

### OS
Status: deployed
Commit: `df5965b`
Preview: https://os.iterate-preview-6.com
[Workflow
run](https://github.com/iterate/iterate/actions/runs/27340067055)
Updated: 2026-06-11T10:23:48.699Z
<!-- /CLOUDFLARE_PREVIEW -->

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.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