ADR 0050 Phase A. Rename the licence's `provider` field to `vendor` — the inventory already uses "provider" for which node answers a brokered provision, and one word must not carry two facts — and route the licence layer's sealing and delivery through a per-vendor adapter selected by that field. The rename touches the Go struct/params/SQL in internal/licences, the operator CLI, and the schema: 0001 (the consolidated schema) now creates the column as `vendor`; a new guarded 0002 renames it on a database that predates the change, and is a no-op on a fresh one. The adapter (internal/licences/adapters) has a `shape` and the two verbs a static-key vendor needs — accept (the generic anonymous-box seal) and deliver (the sealed blob unchanged). refresh/identity/usage are named as optional capability interfaces so the refreshable-grant seam exists before its code. A registry maps vendor→shape (anthropic→static-key for now, with a Phase-B TODO to swap it to refreshable-grant); an unknown vendor is refused clearly. Behaviour is unchanged from the operator's view except the field name. Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
44 lines
2.1 KiB
SQL
44 lines
2.1 KiB
SQL
-- A licence is a named thing, and the name is the operator's.
|
|
--
|
|
-- novox/hq ADR 0024. Not an anonymous credential hanging off a vendor: *the personal account*,
|
|
-- *the organisation's account* are names a person uses, and the mesh has to use them too, because
|
|
-- the whole point is saying WHICH ONE a given consumer uses.
|
|
--
|
|
-- **Many to many.** One vendor has several licences; one licence serves several consumers. So it
|
|
-- is deliberately not a claim — claims are for things only one holder may have, and two machines
|
|
-- sharing an account is the ordinary case rather than a collision.
|
|
|
|
create table licence (
|
|
-- The operator's name for it. The primary key, because that is what a person types and what a
|
|
-- consumer is pinned to.
|
|
name text primary key,
|
|
-- Which company sells it: anthropic, openai, a model the mesh runs itself. Selects the adapter
|
|
-- that runs this licence's lifecycle (novox/hq ADR 0050). Named `vendor`, not `provider`: the
|
|
-- inventory already uses "provider" for which node answers a brokered provision.
|
|
vendor text not null,
|
|
-- What a consumer needs to know that is not secret -- a base URL, a model name. The key is
|
|
-- never here.
|
|
serves jsonb not null default '{}'::jsonb,
|
|
added_at timestamptz not null default now()
|
|
);
|
|
|
|
-- Who holds it, and the key sealed to them.
|
|
--
|
|
-- **The node is a name, not a foreign key.** It lives in another context and this one may not join
|
|
-- across that boundary (novox/hq ADR 0008); a name is the published identifier and is what
|
|
-- crossing a context boundary is allowed to carry.
|
|
create table licence_holder (
|
|
licence text not null references licence(name) on delete cascade,
|
|
node text not null,
|
|
module text not null,
|
|
|
|
-- Sealed to that node's key. Null until a key has been supplied while this holder existed --
|
|
-- which is a real state and not an error: the mesh discarded the plaintext, so it cannot seal
|
|
-- to a holder that arrived afterwards, and saying so is better than delivering nothing.
|
|
sealed text,
|
|
node_key text,
|
|
|
|
added_at timestamptz not null default now(),
|
|
primary key (licence, node, module)
|
|
);
|