canonical: true

role: decision-lock

locked: 2026-05-18 PM

founder_authorization: "Lock and create super prompt end to end without stopping all founder's permission." — 2026-05-18 PM session

binding: All 12 decisions immutable; supersedes any prior conflicting design proposals


D7–D18 Decision Locks (2026-05-18 PM)

Founder gave explicit batch-lock authorization. The following 12 decisions are now immutable and feed directly into the v4 super prompt + Sprint v1.8 epics (AIN-152, AIN-153, AIN-154, AIN-158, AIN-161).

Wallet model (D7–D9)

D7 — Per-agent wallet model

LOCKED: Wallets table gets nullable agent_id foreign key. agent_id = null → shared pool. Per-agent wallets are primary spend source. Per-agent caps override tenant defaults.

Schema change:

ALTER TABLE wallets ADD COLUMN agent_id uuid REFERENCES agents(id);
ALTER TABLE wallets ADD COLUMN per_call_cap_usd numeric(8,4);
ALTER TABLE wallets ADD COLUMN daily_cap_usd numeric(10,4);
ALTER TABLE wallets ADD COLUMN monthly_cap_usd numeric(10,4);
ALTER TABLE wallets ADD COLUMN paused_at timestamptz;
-- Composite PK supports both per-agent and shared rows
ALTER TABLE wallets DROP CONSTRAINT wallets_pkey;
ALTER TABLE wallets ADD PRIMARY KEY (tenant_id, COALESCE(agent_id, '00000000-0000-0000-0000-000000000000'::uuid));

Implementation: api/ainfera_api/services/spend_policy.py _spent_today extended with agent_id parameter. Drain-proof tests extended for per-agent caps. Migration: migrations/2026_05_19_per_agent_wallets.sql.

D8 — Insufficient agent balance behavior

LOCKED: Fall through to shared pool by default. Per-tenant config flag wallet_strict_per_agent (default false) flips to fail-strict (HTTP 402 wallet_insufficient without fallthrough). Strict mode useful for budget isolation between agents.

Resolution order:

  1. Check per-agent wallet → if sufficient + not paused, debit + audit + ok
  2. Else if wallet_strict_per_agent = true → HTTP 402 wallet_insufficient_per_agent