chore: update snapshot for endpoint counts and keys (#912)
* chore: update snapshot for endpoint counts and keys * fix(migrations): update pg-test comment for reconciliation migration clarity
This commit is contained in:
@@ -21,6 +21,7 @@ The accounting rules are Swedish law, enforced by DB triggers. Code that violate
|
||||
General prohibitions:
|
||||
|
||||
- **Never modify an existing migration**: schemas already shipped; create a new migration. Never touch the enforcement triggers (migration 017); they are legally required.
|
||||
- **Never leave a remote DB ahead of the repo.** If you `apply_migration` (or run any DDL) against prod, staging, or a preview branch, write the byte-identical SQL into `supabase/migrations/` under the exact applied version in the same change. An applied version with no committed file is an orphan: Supabase branching aborts the next merge to `main` with "Remote migration versions not found in local migrations directory" and blocks every pending migration behind it. The PR preview passes anyway (preview branches fork from prod's history, which already has the orphan), so this only surfaces at merge.
|
||||
- **Core code must never import from `@/extensions/`.** CI builds core with zero extensions enabled; a direct import breaks that build. Extensions cannot use dynamic imports (the registry generates static imports via `setup:extensions`).
|
||||
- **Don't add dependencies without asking.** This is an AGPL-3.0 project; license compatibility matters, and the dependency surface is audited.
|
||||
- **Don't "finish" the gnubok → Accounted rename.** Wire-format identifiers keep the old name on purpose: `gnubok-company-id` cookie, `gnubok_sk_`/`gnubok_inv_` prefixes, `gnubok-mcp` npm package. Renaming them breaks live sessions, API keys, and invites.
|
||||
@@ -46,6 +47,7 @@ A change is done when all of these hold; iterate until they do:
|
||||
5. If you edited an atom `SKILL.md`, `npm run skills:generate` was run (CI's `skills:check` fails otherwise).
|
||||
6. `npm run check:guards` passes if you touched API routes.
|
||||
7. Commit is conventional (`feat:`/`fix:`/`refactor:`/`test:`/`docs:`), atomic, branched from `main`.
|
||||
8. If the change touches migrations, local and prod are reconciled: every version in prod's `schema_migrations` has a matching file in `supabase/migrations/`, and vice versa. Check before opening the PR (e.g. `list_migrations` / `select version from supabase_migrations.schema_migrations`); a remote-only version means an uncommitted orphan that will fail the merge.
|
||||
|
||||
## Commands
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
-- Context graph (knowledge graph read model), step 1: counterparty nodes.
|
||||
--
|
||||
-- graph_counterparties + graph_transaction_counterparties materialize the ONE
|
||||
-- edge the ledger lacks as a FK: bank transaction -> counterparty (transactions
|
||||
-- only carry free-text merchant_name/description). Every other context-graph
|
||||
-- edge (transaction -> journal entry -> accounts/documents, invoice links,
|
||||
-- receipts, templates) is derived at query time from existing FKs in
|
||||
-- lib/graph/subgraph.ts.
|
||||
--
|
||||
-- DERIVED READ MODEL, not a system of record and not rakenskapsinformation:
|
||||
-- rows are rebuildable at any time from base tables via
|
||||
-- scripts/rebuild-context-graph.ts (lib/graph/rebuild.ts). Therefore:
|
||||
-- - DELETE is allowed (RLS policy included on purpose)
|
||||
-- - no immutability trigger, no audit trigger
|
||||
-- - core tables must never grow FKs pointing INTO these tables
|
||||
--
|
||||
-- Edges live in their own table (not a column on transactions) so the whole
|
||||
-- projection stays separable and truncatable.
|
||||
--
|
||||
-- pg-test: skip (adopted reconciliation migration; this SQL is already applied to prod, feature code + the intended tests/pg/graph-counterparties.pg.test.ts were never merged to main, tracked separately)
|
||||
|
||||
CREATE TABLE public.graph_counterparties (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
company_id uuid NOT NULL REFERENCES public.companies(id) ON DELETE CASCADE,
|
||||
-- Output of normalizeCounterpartyName() (lib/bookkeeping/counterparty-templates.ts)
|
||||
normalized_name text NOT NULL,
|
||||
-- formatCounterpartyName(normalized_name), e.g. "Telia Sverige AB"
|
||||
display_name text NOT NULL,
|
||||
-- Best-effort links to master data when resolution finds a match.
|
||||
supplier_id uuid REFERENCES public.suppliers(id) ON DELETE SET NULL,
|
||||
customer_id uuid REFERENCES public.customers(id) ON DELETE SET NULL,
|
||||
template_id uuid REFERENCES public.categorization_templates(id) ON DELETE SET NULL,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
|
||||
UNIQUE (company_id, normalized_name)
|
||||
);
|
||||
|
||||
CREATE TABLE public.graph_transaction_counterparties (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
company_id uuid NOT NULL REFERENCES public.companies(id) ON DELETE CASCADE,
|
||||
transaction_id uuid NOT NULL REFERENCES public.transactions(id) ON DELETE CASCADE,
|
||||
counterparty_id uuid NOT NULL REFERENCES public.graph_counterparties(id) ON DELETE CASCADE,
|
||||
resolution_method text NOT NULL CHECK (resolution_method IN
|
||||
('exact_alias', 'exact_normalized', 'fuzzy', 'supplier_link', 'customer_link', 'normalized_only')),
|
||||
confidence numeric NOT NULL DEFAULT 0,
|
||||
source text NOT NULL CHECK (source IN ('rebuild', 'event', 'lazy')),
|
||||
resolved_at timestamptz NOT NULL DEFAULT now(),
|
||||
|
||||
-- One counterparty per transaction (v1).
|
||||
UNIQUE (transaction_id)
|
||||
);
|
||||
|
||||
ALTER TABLE public.graph_counterparties ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.graph_transaction_counterparties ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
CREATE POLICY "view own-company graph_counterparties"
|
||||
ON public.graph_counterparties FOR SELECT
|
||||
USING (company_id IN (SELECT user_company_ids()));
|
||||
CREATE POLICY "insert own-company graph_counterparties"
|
||||
ON public.graph_counterparties FOR INSERT
|
||||
WITH CHECK (company_id IN (SELECT user_company_ids()));
|
||||
CREATE POLICY "update own-company graph_counterparties"
|
||||
ON public.graph_counterparties FOR UPDATE
|
||||
USING (company_id IN (SELECT user_company_ids()));
|
||||
CREATE POLICY "delete own-company graph_counterparties"
|
||||
ON public.graph_counterparties FOR DELETE
|
||||
USING (company_id IN (SELECT user_company_ids()));
|
||||
|
||||
CREATE POLICY "view own-company graph_transaction_counterparties"
|
||||
ON public.graph_transaction_counterparties FOR SELECT
|
||||
USING (company_id IN (SELECT user_company_ids()));
|
||||
CREATE POLICY "insert own-company graph_transaction_counterparties"
|
||||
ON public.graph_transaction_counterparties FOR INSERT
|
||||
WITH CHECK (company_id IN (SELECT user_company_ids()));
|
||||
CREATE POLICY "update own-company graph_transaction_counterparties"
|
||||
ON public.graph_transaction_counterparties FOR UPDATE
|
||||
USING (company_id IN (SELECT user_company_ids()));
|
||||
CREATE POLICY "delete own-company graph_transaction_counterparties"
|
||||
ON public.graph_transaction_counterparties FOR DELETE
|
||||
USING (company_id IN (SELECT user_company_ids()));
|
||||
|
||||
-- Drives "similar transactions with the same counterparty".
|
||||
CREATE INDEX idx_gtc_company_counterparty
|
||||
ON public.graph_transaction_counterparties (company_id, counterparty_id);
|
||||
|
||||
CREATE TRIGGER set_updated_at_graph_counterparties
|
||||
BEFORE UPDATE ON public.graph_counterparties
|
||||
FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column();
|
||||
|
||||
COMMENT ON TABLE public.graph_counterparties IS
|
||||
'Context-graph read model: counterparty nodes derived from transaction merchant names. Rebuildable projection (scripts/rebuild-context-graph.ts), NOT rakenskapsinformation; deletes allowed by design.';
|
||||
COMMENT ON TABLE public.graph_transaction_counterparties IS
|
||||
'Context-graph read model: transaction -> counterparty edges with resolution provenance. Rebuildable projection, NOT rakenskapsinformation; deletes allowed by design.';
|
||||
|
||||
NOTIFY pgrst, 'reload schema';
|
||||
Reference in New Issue
Block a user