Shadow discovery
Sooner or later, somebody points an agent at Quayside without telling the registry it exists. Quayside’s response is strict reject, but log the attempt.
What happens
- Caller hits the proxy with
x-api-key: qsk_<jwt>whoseclass_slugclaim iswat/rogue-bot. - The proxy decodes the JWT, gets the slug, asks the registry to resolve it.
- The registry doesn’t have a class with that slug → raises
NotFound. - The proxy catches the
NotFound, records a shadow attempt for(slug, principal_id), and re-raises so the caller still gets404.
The caller cannot tell from the response whether they’ve been logged. The operator can see exactly who tried what.
What’s in the shadow log
| Field | Notes |
|---|---|
id | UUID |
slug | The unknown class slug |
principal_id | Who tried |
tenant | Which tenant context they tried in |
first_seen_at | First attempt |
last_seen_at | Latest attempt (bumped on repeat) |
attempt_count | Bumped on (slug, principal_id) repeat |
The unique constraint is on (slug, principal_id) so the same person retrying the same slug just bumps the count.
What the operator does
Open /shadow in the dashboard. Each entry shows:
- the slug
- the principal who tried
- how many times they’ve tried
- when they last tried
Two actions per entry:
- Clear — the entry is dismissed. If the principal tries again, a new row is created.
- Register — open the registry’s register-class form pre-filled with the slug. After registration, future calls from that principal succeed.
Via HTTP
# Listcurl http://localhost:8000/api/v1/registry/shadow
# Clear onecurl -X DELETE http://localhost:8000/api/v1/registry/shadow/<entry_id>Why strict-reject
Two alternatives Quayside deliberately rejected:
- Auto-register on first sight — too lenient. An attacker can name a class whatever they want and it suddenly exists in your registry. Strict-reject means every new class goes through a human.
- 404 with no record — too thin. Without the log, you can’t see who is doing what, and the dashboard has nothing to surface.
The shadow log is the discovery queue — a queue of decisions waiting for a registrar.
What this isn’t
It isn’t an alert. It isn’t a block list. It’s an inbox for the person responsible for class registration. They get to decide.