Implements docs/requirements/hierarchy-schema.md sections 2-4 and the
schema-layer half of section 6:
- Five class tables (companies, estates, platform_projects, workspaces,
hierarchy_grants) with the section 2.7 exhaustive column sets: child
node tables carry no timestamps (renames are audited via events), no
owner_id anywhere (section 4.4 - ownership is computed from grants).
- Grant constraints per section 3: exactly-one-subject and
exactly-one-target num_nonnulls CHECKs, six-column UNIQUE NULLS NOT
DISTINCT, target FKs CASCADE / principal FKs RESTRICT, six btree
indexes.
- Migration 0018 generated by drizzle-kit; SQL verified against the
contract text and applied on PGlite.
- hierarchy-schema.witness.test.ts: dual-leg witness suite (PGlite
always; real PostgreSQL under DATABASE_URL, the section 6.8 binding
leg in CI). Covers parent-FK integrity + catalog assertion, slug
scoping, column allowlist (6.2), all six grant subject/target forms,
CHECK refusals, NULLS NOT DISTINCT duplicates, NOT NULL refusals, and
deletion semantics (6.6): fail-closed parent delete, leaf cascade of
exactly its grants, principal RESTRICT.
- hierarchy-writer-coverage.test.ts: section 6.3(b) three-prong static
assertion (alias-aware symbol writes, class-table names in SQL
literals, raw-execution primitives) with empty writer allowlist,
closed infrastructure register, and closed importer enumerations for
the migration runner and migrate-tier. All prongs proven able to fire
via a planted-violation control.
Command family, audit events, and route inventory land in M4-1b.