Skip to content

feat(api): persist bound capability Run provenance#320

Merged
Yevanchen merged 2 commits into
langgenius:mainfrom
AsperforMias:feat/bound-capability-run-provenance
Jul 15, 2026
Merged

feat(api): persist bound capability Run provenance#320
Yevanchen merged 2 commits into
langgenius:mainfrom
AsperforMias:feat/bound-capability-run-provenance

Conversation

@AsperforMias

Copy link
Copy Markdown
Collaborator

Summary

Why

#317 makes the final Run insertion the authorization linearization point for a bound capability. Before this PR, a successfully accepted owner-billed Run did not retain the Deployment and binding that authorized it. Logs are not a durable billing/audit record: they may be sampled, expire, or be unavailable during an incident.

The provenance is a Run-level snapshot rather than Session metadata because one Session can contain multiple Runs. It contains no capability URL or signed bearer token.

Implementation

  • Adds six nullable session_run columns through generated migration 0001_bound-capability-run-provenance.sql; existing Runs remain readable with NULL provenance.
  • Propagates only verified capability claims from the bound-Agent path into the final guarded Run insertion. The Run and all six facts therefore commit together or not at all.
  • Adds boundCapabilityRunProvenance(appId, runId), guarded by existing App ownership checks. Legacy/non-bound Runs return null; malformed partial snapshots fail closed.
  • Documents the access and retention policy: the snapshot follows the Run lifecycle and is deleted with the Run.

Verification

  • Commands:
    • just db-reset-local
    • just test-file apps/api/tests/app-agent-bound-run-revocation.test.ts (4 pass, 0 fail)
    • just test-file apps/api/tests/app-agent-capability-revocation-http.test.ts (5 pass, 0 fail)
    • just test-package @mosoo/api (981 pass, 0 fail)
    • just tc-package @mosoo/api
    • just tc-package @mosoo/db
    • just graphql-codegen-check
    • just check
    • git diff --check
  • Local D1/Worker boundary injection:
    • Applied the baseline and 0001 migration to local Wrangler D1 and inspected the resulting session_run columns.
    • Exercised the actual guarded Run insertion with SQLite-backed D1 injection. Accepted calls persist all six fields in the same row.
    • Executed the GraphQL resolver with owner and non-owner contexts: the owner reads the full snapshot; the non-owner receives FORBIDDEN.
    • Injected deployment deletion immediately before the guarded Run insert. The statement rejected and session_run remained empty, so neither a Run nor provenance can be left behind.
    • Verified a normal non-bound Run remains readable and returns null provenance.
  • Not run:
    • No real Cloudflare account, remote Worker/D1 deployment, or billable CF resource was used. The D1/Worker and Cloudflare-boundary behavior was exercised locally with injection; this PR does not claim remote-production validation.

Impact

  • User/API changes:
    • Adds an owner-only GraphQL audit query. Existing public Thread/Run responses are unchanged.
    • Existing Runs and ordinary non-bound Runs retain their behavior; their provenance is null.
  • Database:
    • Forward-only, non-destructive migration with six nullable ADD COLUMN operations. The shipped 0000_baseline.sql is unchanged.
    • No raw capability URL or token is stored.
  • Consistency and rollback:
    • There is no separate provenance write or retry window: the accepted Run and audit facts share one D1 statement. Later Run status and driver-lease updates do not update the snapshot fields.
    • Rolling back the Worker is schema-safe because the added columns are nullable; it only stops writing/serving new provenance. Do not roll back fix(api): revoke bound deployment capabilities #317 independently, because that would restore its bound-capability authorization race.

Review

  • Please review after fix(api): revoke bound deployment capabilities #317, focusing on:
    • apps/api/src/modules/runtime/infrastructure/session-runs/session-run-write.repository.ts
    • apps/api/src/modules/public-api/bound-capability-run-provenance.service.ts
    • pkgs/db/drizzle/0001_bound-capability-run-provenance.sql
    • apps/api/tests/app-agent-bound-run-revocation.test.ts
  • Trade-off: the capability snapshot is immutable in Mosoo application paths. A principal with direct D1 administrative write access can alter any database row; that is outside the Worker authorization boundary and is not expanded by this PR.

@Yevanchen
Yevanchen force-pushed the feat/bound-capability-run-provenance branch from 32ddfb4 to 401f6eb Compare July 15, 2026 07:58
@Yevanchen
Yevanchen merged commit 70367dd into langgenius:main Jul 15, 2026
6 checks passed
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.

feat(api): persist bound capability provenance for accepted Runs

2 participants