chore(schema): canonical remediation — chitty_id, P/L/T/E/A, entities registry, R2 ACL#34
Conversation
… registry, R2 ACL Greenfield canonical schema for Neon project steep-cloud-28172078. The DB was empty pre-migration; no production data to preserve. Stacked on Phase 1 Hono branch since canonical docs and Worker skeleton live there. Migrations (drizzle/): - 0001_init.sql — Drop-in canonical baseline. All entity tables get nullable chitty_id varchar UNIQUE, timestamptz created_at/updated_at, soft-delete deleted_at where applicable, GIN indexes on JSONB, and a shared set_updated_at trigger. Entity-type assignments annotated per table: users=P, assets=T, evidence=T, timeline_events=E, warranties=T, insurance_policies=T, legal_cases=E, ai_analysis_results=E. Borderline calls documented in COMMENT ON TABLE with canonical rationale. - 0002_entities_registry.sql — Canonical discovery/audit index with entity_type enum containing ALL FIVE P/L/T/E/A values (never omit A). Soft references only: per-service tables do NOT FK here. - 0003_r2_object_acl.sql — Replaces GCS objectStorage.ts ACL with a Neon-backed table. principal_chitty_id is a Person (P); evidence_id / asset_id scope grants to Thing (T) artifacts. docs/migrations/phase3-users-chittyid-migration.md — 5-step plan to promote users.chitty_id to PK once ChittyAuth-only cutover completes. Document only, not executed in this PR. shared/schema.ts — Rewritten to mirror DDL. All entity_type-bearing tables carry // @canon: chittycanon://gov/governance#core-types annotations. CANONICAL_ENTITY_TYPES tuple and CHITTY_ID_PATTERN regex include all five P/L/T/E/A; never omit A. Validated on Neon preview branch br-spring-star-aky6u1mc: - All 63 DDL statements executed cleanly via run_sql_transaction - Read-back confirms 11 tables, every entity table has chitty_id + created_at, entity_type enum = {P,L,T,E,A} - npm run check: zero shared/schema.ts errors (pre-existing errors in legacy server/* and client/* are unrelated) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7010f01fef
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| export const r2ObjectAcl = pgTable('r2_object_acl', { | ||
| id: varchar('id').primaryKey().default(sql`gen_random_uuid()`), | ||
| bucket: varchar('bucket').notNull(), | ||
| objectKey: text('object_key').notNull(), | ||
| /** Person (P) ChittyID — soft ref to users.chitty_id. */ | ||
| principalChittyId: varchar('principal_chitty_id').notNull(), | ||
| permission: r2AclPermissionEnum('permission').notNull(), | ||
| grantedByChittyId: varchar('granted_by_chitty_id'), | ||
| evidenceId: varchar('evidence_id').references(() => evidence.id), | ||
| assetId: varchar('asset_id').references(() => assets.id), | ||
| expiresAt: timestamp('expires_at', { withTimezone: true }), | ||
| createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), | ||
| revokedAt: timestamp('revoked_at', { withTimezone: true }), | ||
| }); |
There was a problem hiding this comment.
Mirror ACL uniqueness in Drizzle schema
The new r2_object_acl table is missing the composite uniqueness constraint that exists in drizzle/0003_r2_object_acl.sql (UNIQUE (bucket, object_key, principal_chitty_id, permission)). Because this repo’s normal workflow uses npm run db:push from shared/schema.ts, environments bootstrapped from schema (or reconciled by push) can end up without that guard and accept duplicate grants for the same principal/object/permission tuple, which can make permission resolution ambiguous and break idempotent grant logic.
Useful? React with 👍 / 👎.
| export const assets = pgTable('assets', { | ||
| id: varchar('id').primaryKey().default(sql`gen_random_uuid()`), | ||
| /** Canonical Thing ChittyID. Format VV-G-LLL-SSSS-T-YM-C-X. */ | ||
| chittyId: varchar('chitty_id').unique(), | ||
| chittyIdV2: varchar('chitty_id_v2').unique(), | ||
| userId: varchar('user_id').notNull().references(() => users.id), | ||
| name: text('name').notNull(), |
There was a problem hiding this comment.
Define assets user_id index in schema source of truth
drizzle/0001_init.sql adds idx_assets_user_id, but shared/schema.ts does not define an index for assets.user_id; since this project deploys schema changes via drizzle-kit push (from shared/schema.ts), that index will not be created (or can be removed on reconciliation), causing user-scoped asset reads (getAsset, getUserAssets, getAssetStats) to degrade into increasingly expensive scans as asset volume grows.
Useful? React with 👍 / 👎.
| export const evidence = pgTable('evidence', { | ||
| id: varchar('id').primaryKey().default(sql`gen_random_uuid()`), | ||
| chittyId: varchar('chitty_id').unique(), | ||
| assetId: varchar('asset_id').notNull().references(() => assets.id), | ||
| userId: varchar('user_id').notNull().references(() => users.id), |
There was a problem hiding this comment.
Preserve evidence lookup indexes in Drizzle schema
The SQL migration creates idx_evidence_asset_id and idx_evidence_user_id, but shared/schema.ts does not declare either index for evidence; with drizzle-kit push using the schema file as source of truth, environments can miss these indexes and turn /api/assets/:assetId/evidence and per-user evidence reads into table scans as evidence volume increases.
Useful? React with 👍 / 👎.
Summary
Greenfield canonical schema for Neon project
steep-cloud-28172078. The database was empty pre-migration (confirmed viaget_database_tables→[]), so no production data preservation needed. Stacked onfeat/hono-migration-phase-1since canonical docs (CHARTER/CHITTY/register.json) and the Worker skeleton live there — merging tomaindirect would conflict.drizzle/establishing the canonical baseline: chitty_id varchar UNIQUE on every entity table, timestamptz created_at/updated_at with sharedset_updated_attrigger, soft-deletedeleted_at, GIN indexes on JSONB, and theentitiesregistry withentity_typeenum containing ALL FIVE P/L/T/E/A values.shared/schema.tsrewritten to mirror DDL with// @canon: chittycanon://gov/governance#core-typesannotations on every entity_type-bearing table.docs/migrations/phase3-users-chittyid-migration.md) — 5-step backward-compatible promotion ofusers.chitty_idto PK. Not executed in this PR.Entity-type assignments (annotated per table)
usersassetsevidencetimeline_eventswarrantiesinsurance_policieslegal_casesai_analysis_resultssessions(legacy Replit Auth) andr2_object_acl(operational metadata) are not canonical entities and correctly lackchitty_id.Soft references
Per-service tables do NOT FK to the
entitiesregistry. The registry is populated by app-layer triggers / batch reconciliation. Schema authority remains per-table.Validation evidence (Neon preview branch
br-spring-star-aky6u1mc)All 63 DDL statements executed cleanly via
run_sql_transaction. Read-back queries on the preview branch confirm:ai_analysis_results, assets, entities, evidence, insurance_policies, legal_cases, r2_object_acl, sessions, timeline_events, users, warrantieschitty_idUNIQUE +created_attimestamptzentity_typeenum values ={P, L, T, E, A}— all five canonical types, A not omittednpm run check: zero errors inshared/schema.ts(pre-existing errors in legacyserver/chittyCore.ts,server/chittyEcosystem.ts,client/__tests__/*are unrelated to this PR)Test plan
npm run db:pushagainst preview DATABASE_URL to confirm Drizzle reconciliation against DDL is a no-opentity_typeenum on preview is{P,L,T,E,A}exactlyshared/schema.tserrors innpm run checkfeat/hono-migration-phase-1→ main, re-target this PR to main if neededOut of scope
docs/migrations/phase3-users-chittyid-migration.md)server/chittyCore.tsetc.🤖 Generated with Claude Code