04 — Registry Pin / Ghim Pack (Branch C)
title: 04 — Registry Pin / Ghim Pack (Branch C) date: 2026-05-31 status: rehearsed GREEN; NEW table; COMMIT DEFERRED (RG6)
04 — Registry Pin / Ghim Pack (Branch C)
Goal: PG-backed pinning — not localStorage, not frontend-only state.
Re-scan for reuse (live)
Table scan ~* 'pin|ghim|favorit|watch|bookmark|star|monitor|saved' → 0 rows.
No favourite/watchlist/pin artifact exists. registry_pin is genuinely NEW
(REGISTRY_MISSING) → propose-only, classify NEW (not REUSE/EXTEND).
Rehearsal (live BEGIN..ROLLBACK, GREEN)
CREATE TABLE registry_pin (
id serial PRIMARY KEY,
object_ref text NOT NULL, -- CAT code / pivot code / substrate key
object_kind text, -- 'registry' | 'pivot' | 'list' | 'node'
surface_ref text NOT NULL, -- route/surface the pin shows on
pinned_by text NOT NULL,
scope text NOT NULL DEFAULT 'user',
scope_ref text, -- user/role/team id when scope <> global
reason text,
priority int NOT NULL DEFAULT 0,
active boolean NOT NULL DEFAULT true, -- soft-retire only (Đ0 Atom: never hard-delete)
created_at timestamptz NOT NULL DEFAULT now(),
CONSTRAINT registry_pin_scope_ck CHECK (scope IN ('global','user','role','team'))
);
Result: table created, 2 pilot rows inserted (CAT-023 global, PIV-007 user), CHECK
def confirmed scope = ANY (ARRAY['global','user','role','team']); ROLLBACK →
registry_pin gone, idle_in_transaction = 0.
Required properties — all satisfied
| requirement | mechanism |
|---|---|
| not localStorage / frontend-only | PG table, read via Directus/API |
| scope global/user/role/team | scope CHECK + scope_ref |
| reason | reason |
| priority | priority (sort key) |
| active | active (soft-retire, Đ0 Atom) |
| audit fields | pinned_by, created_at |
| governance owner | scope + future governance_owner (Đ37; via scope_ref=role/team) |
| pivot-countable | PIV-321 (pins by scope, grouped-count) activates on commit |
API contract (read)
GET /api/registries-pivot/pins?scope=&surface= →
[{object_ref, object_kind, surface_ref, scope, scope_ref, pinned_by, reason, priority, active}],
ordered by priority, created_at. Write path (pin/unpin) is a separate gated macro
(needs write API + Đ32 per-action approval); this macro exposes read only.
UI contract
A pin column / 📌 affordance on each row; pinned rows float to top within scope; the pin list itself is a living list (PIV-321 countable). No hierarchy/state in the frontend — order and membership come from PG.
No-hardcode tests
- No
localStoragefor pins (confirmed absent in Nuxt source scan, doc 09/12). - Pin membership/order from PG only; no hardcoded pinned codes in
.vue. - Pin count traces to PIV-321 or
count(registry_pin), never a frontend array length.
Commit-ready SQL (RG6 — DEFERRED)
CREATE TABLE registry_pin … above; additive/reversible (DROP TABLE registry_pin).
No persistent creation performed — no RG6 approval exists.
Verdict
Pin pack COMPLETE. NEW table, rehearsed GREEN, PG-backed, scoped, pivot-countable; commit deferred to RG6.