Repository navigation
feat: send submission and budget events to quilt - #4
Merged
Adambomb210 merged 7 commits intoOct 11, 2026
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Quilt now has a patch API (patchworklabsorg/quilt#8). Krater is the app of the Ganymede patch. Quilt must know about each submission and about the budget that Krater approves, releases and spends. Weave adds the
quiltscope in patchworklabsorg/weave#176.What changed
quilt_outbox. The row id is the event id. A service writes the rows in the same transaction as the change, so a rollback removes both.krater.services.quilt_events.sync_projectcompares a project with its outbox rows and adds only the difference. The project services and the SkyPilot spend reconciler call it. The budget events followBudgetEntryrows one to one.WeaveClient.quilt_token()gets aclient_credentialstoken with thequiltscope. The live client caches tokens by scope, with the existing cache code. The stub returns a fixed fake token.krater.quiltholds the HTTP client and the sender. It is the only code that knows Quilt's URLs. The worker runsquilt_deliverevery minute. A web action that commits also defersquilt_deliver_now(with a queueing lock).SELECT ... FOR UPDATE SKIP LOCKED. Backoff starts at 30 s and doubles up to 1 hour./adminhas a "Delivery to Quilt" section. It shows waiting rows and rows that Quilt refused, with Retry and Dismiss. Both need a reason and write anAuditEvent.uv run python scripts/quilt_backfill.pyadds events for existing projects. Event ids are uuid5 values from the source rows, so a second run adds nothing.KRATER_QUILT_URL(blank = do not send yet),KRATER_QUILT_TIMEOUT_SECONDS,KRATER_QUILT_BATCH_SIZE. In production the URL must be blank orhttps://.docs/quilt-integration.md.CLAUDE.mdanddocs/SPEC.mdlink to it. The Weave e2e provisioning script gives the e2e Krater app thequiltscope.Sequence
Mapping
external_idis the KraterProject.id.statusis Krater's project status.submission.createdapplicant_sub,title,status,requested_cents,url({KRATER_BASE_URL}/projects/{id}),submitted_atsubmission.updatedBudgetEntry> 0 (initial approval, amendment up, admin adjustment up)budget.committedamount_cents,actor_subBudgetEntry< 0 (amendment down, admin adjustment down, reclaim on withdrawal, completion or by an admin)budget.releasedamount_centscapped at Quilt's remaining commitment,actor_subBudgetEntry= 0skippedSpendSnapshotwith a different totalspend.recordedspent_cents_totalunknown_submission, 5xx, no answerid_conflict/submission_exists, 413, 422/adminSetup
quiltscope on the Krater app.introspectscope on the Quilt app.KRATER_WEAVE_CLIENT_ID.KRATER_QUILT_URLon the portal and the worker.uv run python scripts/quilt_backfill.pyonce.While
KRATER_QUILT_URLis blank, the services still write the outbox rows. The sender does nothing and logs once. When the URL is set, the worker sends the backlog in order.Tests
710 tests pass (88 new). They cover each mapping, the same-transaction rollback, the release cap, idempotent sync and backfill, each response class, the order for each submission,
SKIP LOCKEDwith two real connections, the token scope and cache, the worker wiring, the production setting check, and the admin page with authz and CSRF.ruff check,ruff format --checkandalembic checkpass. The migration has one head.Closes #3