Scheduling: a pool id equal to a window id corrupts the supply anchor table

Open
#1,242 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
52/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
rust, sql
Domain
backend, databases

Research direction

Read the scheduling_supply definition in crates/registry-scheduling/migrations/0001_scheduling.sql, then trace the pool anchor insert, facts-replacement deletion and window anchor insert in crates/registry-scheduling/src/store.rs. Follow lock_supply and the existing StoreError::Corrupt path before choosing the schema and authoring approach. Done means collision refusal works in both directions, anchor conflict handling is consistent, and tests cover both publish orders and the resulting diagnostic.

Written by the indexing model from the issue text.

Description

bug criticality:p2 triage:needs-implementation

What

scheduling_supply is a single flat table keyed by supply_id, with a kind
column discriminating pool from window:

CREATE TABLE IF NOT EXISTS scheduling_supply (
    supply_id text PRIMARY KEY,
    kind text NOT NULL CHECK (kind IN ('pool','window'))
);

Two independent publish paths write it, and nothing refuses an id used by both.
Pool ids come from the policy package; window ids come from the environment
records. The two namespaces are authored separately and there is no check that
they are disjoint.

The two writes are also asymmetric. The pool anchor inserts with
ON CONFLICT(supply_id) DO NOTHING, while the window anchor inserts with no
conflict clause, after the facts replacement deletes every row with
kind='window'.

Two failures

Publish a window whose id matches a live pool. The window anchor insert
hits the primary key and aborts the whole facts-replacement transaction. The
operator gets an opaque failure rather than a named refusal naming the
collision.

Publish a pool whose id matches a live window. ON CONFLICT DO NOTHING
silently skips the anchor, so no pool row is created and the existing row keeps
kind='window'. Commitments still serialize, because lock_supply matches on
supply_id and finds the row. Then the next facts replacement runs
DELETE FROM scheduling_supply WHERE kind='window' and removes the anchor the
pool also depended on. From that point lock_supply returns fewer rows than it
asked for and raises StoreError::Corrupt, so every commitment against that
pool answers 503 until the policy is republished.

The second is the worse one: a silent, self-inflicted, persistent outage on one
pool, with no refusal at authoring time and no signal at publish time.

Where

  • crates/registry-scheduling/migrations/0001_scheduling.sql, the
    scheduling_supply definition
  • crates/registry-scheduling/src/store.rs, the pool anchor insert, the
    DELETE ... WHERE kind='window' and window anchor insert in the facts
    replacement, and lock_supply

Why it is filed rather than fixed

It needs an operator id collision to trigger, and #1092 is an MVP with no
adopters. The fix is small but it is a schema and authoring question rather
than a one-line guard, so it wants its own change.

Done when

  • Authoring refuses a pool id that collides with a window id, and the reverse,
    with a named diagnostic rather than a database error.
  • The two anchor writes agree on conflict handling.
  • StoreError::Corrupt from lock_supply is distinguishable from a genuine
    ledger inconsistency, or cannot be reached this way at all.
  • A test publishes a colliding id both ways and asserts the refusal.
Dominant language
Rust
Stars
2
Forks
0
Avg merge
3h 45m
Merged PRs (30d)
134

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from registrystack/registry-stack

All issues in registrystack/registry-stack

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.