Power stone

Worker

Acts, never remains. The stone that carries the blow is also the stone most tightly chained: created by a Directive, killed by its boundary, gone.

hard kill <= 30 min persistence: none ships in v0.1: signed artifact only

The discipline

Worker is not a fifth product. It is an ephemeral execution role: a Directive creates it, its boundary kills it. It never persists, never loops, and never schedules itself.

Watch is cheap, thought is rare, and action is final. Final things get fences. The gauntlet grants the Worker no memory of its own, no clock of its own, and no permission to exist past its job. When the boundary hits, the hard kill lands within 30 minutes and nothing of the Worker stays behind.

This is why v0.1 stops where it stops: the chain ends at a signed directive sitting in the Outbox. A signed directive is a promise recorded, not an action performed, and this page will never pretend otherwise.

Action is final, so action is fenced

An observer can be wrong and a council can be talked out of it. An actor cannot be un-acted. That asymmetry is the whole reason the Worker gets the shortest leash of any stone.

A Directive

The Directive is the Worker's entire world: its creation order, its leash, and its death certificate in one document.

Field
Meaning
job
The single task the Worker exists to do.
scope
The boundary the job may not leave.
stop_condition
The condition that ends the Worker's existence.
return_expectation
What the Worker owes back when it finishes.

A Directive must not grant persistence, looping, or scheduling. Identity and recall writes never touch the disk directly; they route through Librarian approval.

The allowed verbs come from ALLOWED_ACTIONS: read, report, notify, review, escalate. Everything else is refused: delete, write, the wildcard *, and even whitespace-padded verbs are rejected by the shared fence corpora.

Proposals travel under the schema irin.directive.proposal.v1 with authority recommend and verdicts Act or Dismiss. A verdict of Act pins scope.tenant to the expected tenant, so a directive cannot drift across tenant lines.

The Outbox lifecycle

Signed directives wait in the Outbox. Everything below is the lifecycle of that artifact: staged, claimed, heartbeated, acknowledged, or returned.

Endpoint
Contract
GET /watch/outbox/{tenant}
List staged directives. Requires admin plus canary. Returns the canonical envelope with signature. List limit 1..200, base64 cursor created_at:id.
GET /watch/outbox/{tenant}/{id}
Fetch one directive by id. Same admin plus canary gate, same canonical envelope and signature.
POST /watch/outbox/claim
Claim work. Requires admin, the X-Tenant-Scope header, and canary. claim_limit is 1..200, lease is 1000-300000 ms.
POST /watch/outbox/{id}/heartbeat
Extend a lease through the opaque_handle. Extension window: 1s to 300s.
POST /watch/outbox/{id}/ack
Acknowledge a row. Returns 204 on success, or 409 with not_actionable when the row cannot be acted on.
POST /watch/outbox/{id}/worker_ack
Complete with a WorkerProvenanceGuard. The route is always mounted, but the built-in worker loop is default-off and not operator-ready.
POST /watch/outbox/{id}/nack
Return a row to staged for retry.

Signing

Every Outbox entry passes the same three-step sealing: Canonicalize (RFC 8785) then Sign (Ed25519) then Chain (an append-only, hash-chained outbox where pruning is forbidden). The result is non-repudiation plus tamper-evidence: the artifact cannot be quietly edited, and it cannot be quietly denied.

Provenance guards

When something claims a Worker did it, the system states exactly how much of that claim is proven. No rounding up.

Guard
What it proves, and what it does not
WorkerProvenanceStatus
One of opaque_handle_only, verified_exact, or unavailable, each paired with an explicit fabrication_guard.
GatewayProvenance
Header-captured correlation. It is not cryptographic attestation, and it is never presented as such.

Who may act today

Power answers to gates, claims, and ceilings. All of them fail closed.

The three gates

  • Sentinel loaded.
  • Dispatcher enabled.
  • Producer armed.

There is also a boot triple-gate: WATCH_PRODUCER_ENABLED plus EXECUTION_MODE=LIVE plus WATCH_DISPATCHER_GATEWAY_KEY. Passing it starts the producer for recovery and testing, but it never writes active_arm. Spend reserves fail closed without the hardware ceremony.

Writer claim

Exactly one live writer per watch.db. Heartbeat every 30s; a claim goes stale at 90s; a lost claim self-disarms.

Spend ceilings

Ceiling
Value
DAILY_SPEND_CAP_USD
Daily ceiling of $50 per UTC day. This variable may only lower the cap, never raise it.
WATCH_MAX_FANOUT_COST_USD
Fanout reserve of $5.
signed arm window
Default 24h.
max loss
min(daily_ceiling, charge_unit*claims_per_tick + in_flight_at_disarm)

Fine print: read before you snap your fingers

  • v0.1 ends at the signed directive artifact. Never describe a signed directive as an action that happened.
  • A signature proves what was signed, not that the signer should have been trusted.
  • The built-in worker loop (WATCH_WORKER_ENABLED) is a default-off development path, not an operator-ready autonomous execution path.
  • WATCH_PRODUCER_ENABLED=true alone is not arming.
  • make runtime-status proves liveness only; make verify proves the isolated no-spend path only. Neither proves live provider calls, an armed producer, or Worker execution.