/** * Baseline for the module-business barrier gate * (openspec/changes/module-business-barrier/inventory.md section 5). * * **This file is a debt ledger, not a configuration knob.** Every entry is a * place where celilo core holds knowledge that belongs to a provider module. * The gate enforces *monotonic improvement*: an entry may shrink or disappear * freely, and may only grow with a justification a reviewer sees in the diff. * * Seeded from the 48 open rows of the audit. Row ids (`T1`, `S8`, `L12`, `X3`…) * refer to that document's sections 1-4 — read the row before changing a line * here. * * **Every debt entry names the issue tracking its removal.** The audit is a * ruling; the issues are the work. If you are here because the gate went red, * the issue in the entry's `why` is where the fix belongs: * * #937 the hardcoded well-known registry + its duplicate zone table * #938 the loader's capName branches, CAPABILITY_MODULE_MAP, isFirewallModule * #939 the four provider-domain tables * #940 the Caddyfile generator + interface classification in the shared package * #941 core shelling iptables-save * #943 the three capability-named CLI verbs * #944 core shelling wg pubkey * #945 three core primitives gated on one capability (generalise, don't move) * * Two kinds of entry live here and they must not be confused: * * - **Debt** — the default. It is here because it is wrong and not yet fixed. * - **Permanent** — marked `PERMANENT` in `why`. Not debt, and no one should * try to pay it down. `notification` is both a capability name and an * ordinary English word the alerting subsystem uses constantly, so its rows * never go away. */ import { allDeclaredTables } from '@celilo/capabilities'; /** * Tables tagged `@owner capability:*` in `db/schema.ts`, and the capability * each belongs to. Scan A asserts the tagged set EQUALS this map — not that it * is empty. * * DERIVED from the capability declarations, not hand-written * (openspec/changes/capability-owned-tables task 2.7). It used to be a literal, * which made `@owner capability:public_web` a comment checked against another * comment. Now the tag is checked against the thing that actually governs the * table, so a declared table that nobody tagged and a tagged table nobody * declared BOTH fail, and the map cannot drift from the declarations because it * no longer exists apart from them. These four exist today (audit T1, T2, T3, T6) and Phase 1 migrates * nothing; an assertion that core holds none would be red the day it landed. * * Tracked by #939. Migrating them keeps the ownership CLAIM in core — dropping * it is the mistake that made `dns_registration_consumers` necessary (#626). */ export const CAPABILITY_OWNED_TABLES: Readonly> = Object.fromEntries( allDeclaredTables().map(({ capability, declaration }) => [declaration.table, capability]), ); /** One `{file, capability}` pair and how many times core names it. */ export interface CapabilityNameRow { /** Repo-relative path, POSIX separators. */ readonly file: string; readonly capability: string; /** * Exact occurrence count. The count is the mechanism: `capability-loader.ts` * already carried 21 `firewall` hits, so at file-granularity a 22nd would be * invisible — and the 22nd is `baf2c70d` (row L12), the commit this whole * change exists because of. */ readonly count: number; readonly why: string; } /** Scan C: a file under `services/**` whose NAME carries a capability name. */ export interface ServiceFilenameRow { readonly file: string; readonly capability: string; readonly why: string; } /** Scan D: a provider-implementation literal appearing in core's code. */ export interface ProviderLiteralRow { readonly file: string; readonly literal: string; readonly count: number; readonly why: string; } export const CAPABILITY_NAME_BASELINE: readonly CapabilityNameRow[] = [ { file: 'apps/celilo/src/hooks/capability-loader.ts', capability: 'web_routes', count: 2, why: 'PERMANENT — a provider VIEW, not a module-provided capability. The name was registered so it stops being invisible to audits (celilo#1007); these references predate that and are framework plumbing, not core branching on a provider', }, { file: 'apps/celilo/src/hooks/capability-loader.ts', capability: 'firewall_registry', count: 4, why: 'PERMANENT — a provider VIEW, not a module-provided capability. The name was registered so it stops being invisible to audits (celilo#1007); these references predate that and are framework plumbing, not core branching on a provider', }, { file: 'apps/celilo/src/hooks/capability-loader.ts', capability: 'provider_converge', count: 2, why: 'PERMANENT — a provider VIEW, not a module-provided capability. Core injects the generic converge every provider renders through; naming it is framework plumbing, not core branching on a provider (providers-converge-declared-state)', }, { file: 'apps/celilo/src/db/schema.ts', capability: 'web_routes', count: 1, why: 'PERMANENT — the TABLE named web_routes, which predates the capability name entirely; the collision is nominal', }, { file: 'packages/capabilities/src/public-web.ts', capability: 'web_routes', count: 1, why: 'PERMANENT — the public_web implementation naming its own table; the capability package doing its job', }, { file: 'packages/capabilities/src/capability-contract.ts', capability: 'control_plane_api', count: 1, why: 'PERMANENT — a contract declaration with no implementation; this is the package doing its job', }, { file: 'packages/capabilities/src/capability-contract.ts', capability: 'web_routes', count: 1, why: 'PERMANENT — a contract declaration with no implementation; this is the package doing its job', }, { file: 'packages/capabilities/src/capability-contract.ts', capability: 'firewall_registry', count: 1, why: 'PERMANENT — a contract declaration with no implementation; this is the package doing its job', }, { file: 'packages/capabilities/src/capability-contract.ts', capability: 'provider_converge', count: 1, why: 'PERMANENT — a contract declaration with no implementation; this is the package doing its job', }, { file: 'apps/celilo/src/capabilities/well-known.ts', capability: 'dhcp_server', count: 1, why: 'X1 — hardcoded canonical hostnames, required zones and literal ports; Phase 2 (#937)', }, { file: 'apps/celilo/src/capabilities/well-known.ts', capability: 'dns_internal', count: 1, why: 'X1 — hardcoded canonical hostnames, required zones and literal ports; Phase 2 (#937)', }, { file: 'apps/celilo/src/capabilities/well-known.ts', capability: 'dns_registrar', count: 1, why: 'X1 — hardcoded canonical hostnames, required zones and literal ports; Phase 2 (#937)', }, { file: 'apps/celilo/src/capabilities/well-known.ts', capability: 'public_web', count: 1, why: 'X1 — hardcoded canonical hostnames, required zones and literal ports; Phase 2 (#937)', }, { file: 'apps/celilo/src/cli/commands/notify-config.ts', capability: 'notification', count: 2, why: "PERMANENT — 'notification' here is the English word, not the capability; celilo's own alerting surface", }, { file: 'apps/celilo/src/cli/commands/token.ts', capability: 'idp', count: 1, why: 'X7 — a top-level CLI verb backed by the idp capability; Phase 5 (#943)', }, { file: 'apps/celilo/src/cli/completion.ts', capability: 'firewall', count: 3, why: 'X6 — tab completion for the capability-named CLI verbs; falls out with X6 (#943)', }, { file: 'apps/celilo/src/cli/index.ts', capability: 'firewall', count: 2, why: 'X5/X6/X7 — the command tree wiring the capability-named CLI verbs; Phase 5 (#943)', }, { file: 'apps/celilo/src/hooks/capability-loader.ts', capability: 'control_plane_vpn', count: 1, why: 'L1-L12 — core branches on the capability NAME; becomes a provider declaration in Phase 3 (#938)', }, { file: 'apps/celilo/src/hooks/capability-loader.ts', capability: 'dhcp_server', count: 1, why: 'L1-L12 — core branches on the capability NAME; becomes a provider declaration in Phase 3 (#938)', }, { file: 'apps/celilo/src/hooks/capability-loader.ts', capability: 'dns_internal', count: 3, why: 'L1-L12 — core branches on the capability NAME; becomes a provider declaration in Phase 3 (#938)', }, { file: 'apps/celilo/src/hooks/capability-loader.ts', capability: 'dns_registrar', count: 4, why: 'L1-L12 — core branches on the capability NAME; becomes a provider declaration in Phase 3 (#938)', }, { file: 'apps/celilo/src/hooks/capability-loader.ts', capability: 'external_web', count: 1, why: 'L1-L12 — core branches on the capability NAME; becomes a provider declaration in Phase 3 (#938)', }, { file: 'apps/celilo/src/hooks/capability-loader.ts', capability: 'firewall', count: 12, why: 'L1-L12 — core branches on the capability NAME; becomes a provider declaration in Phase 3 (#938)', }, { file: 'apps/celilo/src/hooks/capability-loader.ts', capability: 'idp', count: 1, why: 'L1-L12 — core branches on the capability NAME; becomes a provider declaration in Phase 3 (#938)', }, { file: 'apps/celilo/src/hooks/capability-loader.ts', capability: 'notification', count: 1, why: 'L1-L12 — core branches on the capability NAME; becomes a provider declaration in Phase 3 (#938)', }, { file: 'apps/celilo/src/hooks/capability-loader.ts', capability: 'private_web', count: 1, why: 'L1-L12 — core branches on the capability NAME; becomes a provider declaration in Phase 3 (#938)', }, { file: 'apps/celilo/src/hooks/capability-loader.ts', capability: 'public_web', count: 8, why: 'L1-L12 — core branches on the capability NAME; becomes a provider declaration in Phase 3 (#938)', }, { file: 'apps/celilo/src/hooks/capability-loader.ts', capability: 'registry_publish', count: 1, why: 'L1-L12 — core branches on the capability NAME; becomes a provider declaration in Phase 3 (#938)', }, { file: 'apps/celilo/src/hooks/capability-loader.ts', capability: 'source_forge', count: 1, why: 'L1-L12 — core branches on the capability NAME; becomes a provider declaration in Phase 3 (#938)', }, { file: 'apps/celilo/src/manifest/validate.ts', capability: 'cross_module_read', count: 1, why: "PERMANENT — validating a manifest's declared capability names against the registry is core's job", }, { file: 'apps/celilo/src/manifest/validate.ts', capability: 'control_plane_api', count: 1, why: 'PERMANENT — framework-granted, so celilo satisfies it and no module provides it; the resolver has to be told that by name (web-ui-console D7b)', }, { file: 'apps/celilo/src/hooks/capability-loader.ts', capability: 'control_plane_api', count: 4, why: "PERMANENT — framework-granted like web_routes above; core builds the method table because enrolment writes celilo's own api_principals row, which no module script can reach (web-ui-console D7b)", }, { file: 'apps/celilo/src/services/alerting/inbound-poller.ts', capability: 'notification', count: 1, why: "PERMANENT — celilo's own alerting subsystem; 'notification' is the English word", }, { file: 'apps/celilo/src/services/alerting/transport-loader.ts', capability: 'notification', count: 1, why: "PERMANENT — celilo's own alerting subsystem; 'notification' is the English word", }, { file: 'apps/celilo/src/services/cross-module-read.ts', capability: 'cross_module_read', count: 1, why: 'PERMANENT — cross_module_read is a framework-granted privilege, not a module-provided capability (X10)', }, { file: 'apps/celilo/src/services/dns-provider-backfill.ts', capability: 'dns_internal', count: 2, why: 'S3 — the generic event-replay half is core; the dns_internal gate is not (#945)', }, { file: 'apps/celilo/src/services/firewall-reach.ts', capability: 'firewall', count: 1, why: 'S8 — core shells iptables-save at a remote box and parses the output (#941)', }, { file: 'apps/celilo/src/services/infrastructure-selector.ts', capability: 'firewall', count: 1, why: 'S15 — isFirewallModule hardcodes a placement rule the manifest should declare (#938)', }, { file: 'apps/celilo/src/services/module-deploy.ts', capability: 'firewall', count: 2, why: "S16 — two more copies of S15's decision; fixing S15 removes all three (#938)", }, { file: 'apps/celilo/src/services/module-deploy.ts', capability: 'public_web', count: 1, why: "D10 (capability-owned-tables stage 4): the public_web PROVIDER's own deploy writes the static-content release set into its generated inventory, so a rebuilt host recovers with no consumer involvement. The branch checks the deploying module's manifest `provides`, not a module name; the capability-loader callback is the other half of the same seam.", }, { file: 'apps/celilo/src/services/zone-policy.ts', capability: 'public_web', count: 1, why: 'S13 — ZONE_REQUIREMENTS, a second hand-maintained copy of well-known.ts; Phase 2 (#937)', }, { file: 'apps/celilo/src/templates/generator.ts', capability: 'dns_internal', count: 1, why: 'X4 — declaration-driven and the model for the rest; only the error string names the capability (#945)', }, { file: 'apps/celilo/src/variables/context.ts', capability: 'dns_internal', count: 1, why: 'X3 — reaches capabilitiesMap.dns_internal by name; should read a declared field (X4 is the model) (#945)', }, { file: 'packages/capabilities/src/declared-tables.ts', capability: 'dns_internal', count: 1, why: 'PERMANENT — the name-keyed aggregate of capability TABLE declarations, same shape and same justification as capability-contract.ts: a declaration with no implementation. Naming the capability IS the mapping; core reads it to avoid naming any (openspec/changes/capability-owned-tables D2)', }, { file: 'packages/capabilities/src/declared-tables.ts', capability: 'firewall', count: 1, why: 'PERMANENT — the name-keyed aggregate of capability TABLE declarations, same shape and same justification as capability-contract.ts: a declaration with no implementation. Naming the capability IS the mapping; core reads it to avoid naming any (openspec/changes/capability-owned-tables D2)', }, { file: 'packages/capabilities/src/declared-tables.ts', capability: 'public_web', count: 1, why: 'PERMANENT — the name-keyed aggregate of capability TABLE declarations, same shape and same justification as capability-contract.ts: a declaration with no implementation. Naming the capability IS the mapping; core reads it to avoid naming any (openspec/changes/capability-owned-tables D2)', }, { file: 'packages/capabilities/src/capability-contract.ts', capability: 'celilo_module_deploy_worker', count: 1, why: 'PERMANENT — X10, a contract declaration with no implementation; this is the package doing its job', }, { file: 'packages/capabilities/src/capability-contract.ts', capability: 'control_plane_vpn', count: 1, why: 'PERMANENT — X10, a contract declaration with no implementation; this is the package doing its job', }, { file: 'packages/capabilities/src/capability-contract.ts', capability: 'cross_module_read', count: 1, why: 'PERMANENT — X10, a contract declaration with no implementation; this is the package doing its job', }, { file: 'packages/capabilities/src/capability-contract.ts', capability: 'dhcp_server', count: 1, why: 'PERMANENT — X10, a contract declaration with no implementation; this is the package doing its job', }, { file: 'packages/capabilities/src/capability-contract.ts', capability: 'dns_internal', count: 1, why: 'PERMANENT — X10, a contract declaration with no implementation; this is the package doing its job', }, { file: 'packages/capabilities/src/capability-contract.ts', capability: 'dns_registrar', count: 1, why: 'PERMANENT — X10, a contract declaration with no implementation; this is the package doing its job', }, { file: 'packages/capabilities/src/capability-contract.ts', capability: 'external_web', count: 1, why: 'PERMANENT — X10, a contract declaration with no implementation; this is the package doing its job', }, { file: 'packages/capabilities/src/capability-contract.ts', capability: 'firewall', count: 1, why: 'PERMANENT — X10, a contract declaration with no implementation; this is the package doing its job', }, { file: 'packages/capabilities/src/capability-contract.ts', capability: 'idp', count: 1, why: 'PERMANENT — X10, a contract declaration with no implementation; this is the package doing its job', }, { file: 'packages/capabilities/src/capability-contract.ts', capability: 'notification', count: 1, why: 'PERMANENT — X10, a contract declaration with no implementation; this is the package doing its job', }, { file: 'packages/capabilities/src/capability-contract.ts', capability: 'private_web', count: 1, why: 'PERMANENT — X10, a contract declaration with no implementation; this is the package doing its job', }, { file: 'packages/capabilities/src/capability-contract.ts', capability: 'public_web', count: 1, why: 'PERMANENT — X10, a contract declaration with no implementation; this is the package doing its job', }, { file: 'packages/capabilities/src/capability-contract.ts', capability: 'registry_publish', count: 1, why: 'PERMANENT — X10, a contract declaration with no implementation; this is the package doing its job', }, { file: 'packages/capabilities/src/capability-contract.ts', capability: 'source_forge', count: 1, why: 'PERMANENT — X10, a contract declaration with no implementation; this is the package doing its job', }, { file: 'packages/capabilities/src/firewall.ts', capability: 'firewall', count: 3, why: 'PERMANENT — X10, the firewall capability contract. The third is FIREWALL_CAPABILITY_NAME, exported so core queries the provider registry without spelling the literal; it moved a name OUT of apps/celilo/src/console/projection.ts rather than adding one', }, { file: 'packages/capabilities/src/public-web.ts', capability: 'public_web', count: 1, why: "X8 — generateCaddyfile renders caddy's complete config from the shared package; Phase 5 (#940)", }, { file: 'packages/capabilities/src/utils.ts', capability: 'public_web', count: 3, why: 'X8 — shared helpers that name the capability they serve; moves with X8 in Phase 5 (#940)', }, ]; export const SERVICE_FILENAME_BASELINE: readonly ServiceFilenameRow[] = [ { file: 'apps/celilo/src/services/alerting/notification-responder.ts', capability: 'notification', why: "PERMANENT — false positive; celilo's own alerting responder, unrelated to the notification capability", }, { file: 'apps/celilo/src/services/cross-module-read.ts', capability: 'cross_module_read', why: 'PERMANENT — cross_module_read is a framework privilege, not a module capability', }, { file: 'apps/celilo/src/services/provider-converge.ts', capability: 'provider_converge', why: 'PERMANENT — provider_converge is a framework-granted view, not a module capability, and this service IS the generic mechanism it grants: it carries what a provider rendered and runs that provider own role. Naming it for one provider is what the scan exists to catch; naming it for the mechanism is the fix the scan asks for (providers-converge-declared-state)', }, { file: 'apps/celilo/src/services/dns-internal-records.ts', capability: 'dns_internal', why: 'S5 — the store for T6; moves with the table in Phase 4 (#939)', }, { file: 'apps/celilo/src/services/firewall-reach.ts', capability: 'firewall', why: 'S8 — core reaching into one provider implementation (#941)', }, ]; export const PROVIDER_LITERAL_BASELINE: readonly ProviderLiteralRow[] = [ { file: 'apps/celilo/src/secrets/generators.ts', literal: 'wg pubkey', count: 1, why: 'X11 — core shells `wg pubkey` to derive a key, and tells the operator to brew install wireguard-tools (#944)', }, { file: 'apps/celilo/src/services/firewall-reach.ts', literal: 'iptables-save', count: 1, why: "S8 — core parses a firewall's live ruleset; implementation-specific, not merely capability-specific (#941)", }, { file: 'packages/capabilities/src/public-web.ts', literal: '/srv/www', count: 3, why: "X8 — the Caddyfile generator knows caddy's on-disk asset layout (#940)", }, ];