What ships (verifiable without live DB, 64 new tests): - db/migrations/0000_initial_schema.sql (Drizzle-generated, 7 tables) + .down.sql + registry entry - db/migrations/rehearse.ts: forward-then-rollback round-trip with row-count hash check (DoD 2.2) - infra/docker-compose.yml: postgres 17 + redis 7 + openobserve for local dev (5433/6380/5080) - packages/schema/src/rate-limit.ts: pluggable store; 4 tests including 21st-of-20 reject (DoD 2.4) - packages/schema/src/csrf.ts: HMAC double-submit token; 8 tests covering forgery + tamper + malformed - packages/schema/src/authz.ts: 3-role Cerbos-equivalent rules (operator/approver/viewer); 6 tests - packages/schema/src/api-contracts.ts: Zod schemas for /api/content, /api/approvals, /api/publications, /api/feature-flags + idempotencyKeyOf; 11 tests What defers to live-DB session: - 2.3 admin route handlers integration tests (401/403/200/422 contract suite) - 2.2 actual rehearsal execution against staging DB Total: 79/79 tests pass across 9 files in 4 packages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
629 lines
16 KiB
JSON
629 lines
16 KiB
JSON
{
|
|
"id": "1fb12519-6c3a-4a98-ad43-864eb773898c",
|
|
"prevId": "00000000-0000-0000-0000-000000000000",
|
|
"version": "7",
|
|
"dialect": "postgresql",
|
|
"tables": {
|
|
"public.approvals": {
|
|
"name": "approvals",
|
|
"schema": "",
|
|
"columns": {
|
|
"id": {
|
|
"name": "id",
|
|
"type": "serial",
|
|
"primaryKey": true,
|
|
"notNull": true
|
|
},
|
|
"content_id": {
|
|
"name": "content_id",
|
|
"type": "integer",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"outlet": {
|
|
"name": "outlet",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"approved_by": {
|
|
"name": "approved_by",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"approved_at": {
|
|
"name": "approved_at",
|
|
"type": "timestamp with time zone",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"default": "now()"
|
|
},
|
|
"notes": {
|
|
"name": "notes",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false
|
|
}
|
|
},
|
|
"indexes": {},
|
|
"foreignKeys": {
|
|
"approvals_content_id_content_id_fk": {
|
|
"name": "approvals_content_id_content_id_fk",
|
|
"tableFrom": "approvals",
|
|
"tableTo": "content",
|
|
"columnsFrom": [
|
|
"content_id"
|
|
],
|
|
"columnsTo": [
|
|
"id"
|
|
],
|
|
"onDelete": "no action",
|
|
"onUpdate": "no action"
|
|
}
|
|
},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {},
|
|
"policies": {},
|
|
"checkConstraints": {},
|
|
"isRLSEnabled": false
|
|
},
|
|
"public.audit": {
|
|
"name": "audit",
|
|
"schema": "",
|
|
"columns": {
|
|
"id": {
|
|
"name": "id",
|
|
"type": "serial",
|
|
"primaryKey": true,
|
|
"notNull": true
|
|
},
|
|
"ts": {
|
|
"name": "ts",
|
|
"type": "timestamp with time zone",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"default": "now()"
|
|
},
|
|
"actor": {
|
|
"name": "actor",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"action": {
|
|
"name": "action",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"subject_type": {
|
|
"name": "subject_type",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"subject_id": {
|
|
"name": "subject_id",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"correlation_id": {
|
|
"name": "correlation_id",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"payload_jsonb": {
|
|
"name": "payload_jsonb",
|
|
"type": "jsonb",
|
|
"primaryKey": false,
|
|
"notNull": false
|
|
}
|
|
},
|
|
"indexes": {
|
|
"audit_ts_idx": {
|
|
"name": "audit_ts_idx",
|
|
"columns": [
|
|
{
|
|
"expression": "ts",
|
|
"isExpression": false,
|
|
"asc": true,
|
|
"nulls": "last"
|
|
}
|
|
],
|
|
"isUnique": false,
|
|
"concurrently": false,
|
|
"method": "btree",
|
|
"with": {}
|
|
},
|
|
"audit_correlation_idx": {
|
|
"name": "audit_correlation_idx",
|
|
"columns": [
|
|
{
|
|
"expression": "correlation_id",
|
|
"isExpression": false,
|
|
"asc": true,
|
|
"nulls": "last"
|
|
}
|
|
],
|
|
"isUnique": false,
|
|
"concurrently": false,
|
|
"method": "btree",
|
|
"with": {}
|
|
}
|
|
},
|
|
"foreignKeys": {},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {},
|
|
"policies": {},
|
|
"checkConstraints": {},
|
|
"isRLSEnabled": false
|
|
},
|
|
"public.content": {
|
|
"name": "content",
|
|
"schema": "",
|
|
"columns": {
|
|
"id": {
|
|
"name": "id",
|
|
"type": "serial",
|
|
"primaryKey": true,
|
|
"notNull": true
|
|
},
|
|
"vault_path": {
|
|
"name": "vault_path",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"slug": {
|
|
"name": "slug",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"title": {
|
|
"name": "title",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"body_sanitized": {
|
|
"name": "body_sanitized",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"frontmatter_jsonb": {
|
|
"name": "frontmatter_jsonb",
|
|
"type": "jsonb",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"content_hash": {
|
|
"name": "content_hash",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"version": {
|
|
"name": "version",
|
|
"type": "integer",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"default": 1
|
|
},
|
|
"created_at": {
|
|
"name": "created_at",
|
|
"type": "timestamp with time zone",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"default": "now()"
|
|
},
|
|
"updated_at": {
|
|
"name": "updated_at",
|
|
"type": "timestamp with time zone",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"default": "now()"
|
|
}
|
|
},
|
|
"indexes": {
|
|
"content_slug_idx": {
|
|
"name": "content_slug_idx",
|
|
"columns": [
|
|
{
|
|
"expression": "slug",
|
|
"isExpression": false,
|
|
"asc": true,
|
|
"nulls": "last"
|
|
}
|
|
],
|
|
"isUnique": false,
|
|
"concurrently": false,
|
|
"method": "btree",
|
|
"with": {}
|
|
}
|
|
},
|
|
"foreignKeys": {},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {
|
|
"content_vault_path_unique": {
|
|
"name": "content_vault_path_unique",
|
|
"nullsNotDistinct": false,
|
|
"columns": [
|
|
"vault_path"
|
|
]
|
|
}
|
|
},
|
|
"policies": {},
|
|
"checkConstraints": {},
|
|
"isRLSEnabled": false
|
|
},
|
|
"public.linkedin_tokens": {
|
|
"name": "linkedin_tokens",
|
|
"schema": "",
|
|
"columns": {
|
|
"id": {
|
|
"name": "id",
|
|
"type": "serial",
|
|
"primaryKey": true,
|
|
"notNull": true
|
|
},
|
|
"subject_type": {
|
|
"name": "subject_type",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"subject_urn": {
|
|
"name": "subject_urn",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"access_token_ct": {
|
|
"name": "access_token_ct",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"refresh_token_ct": {
|
|
"name": "refresh_token_ct",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false
|
|
},
|
|
"access_expires_at": {
|
|
"name": "access_expires_at",
|
|
"type": "timestamp with time zone",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"refresh_expires_at": {
|
|
"name": "refresh_expires_at",
|
|
"type": "timestamp with time zone",
|
|
"primaryKey": false,
|
|
"notNull": false
|
|
},
|
|
"scopes": {
|
|
"name": "scopes",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"created_at": {
|
|
"name": "created_at",
|
|
"type": "timestamp with time zone",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"default": "now()"
|
|
},
|
|
"updated_at": {
|
|
"name": "updated_at",
|
|
"type": "timestamp with time zone",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"default": "now()"
|
|
}
|
|
},
|
|
"indexes": {
|
|
"linkedin_tokens_subject_idx": {
|
|
"name": "linkedin_tokens_subject_idx",
|
|
"columns": [
|
|
{
|
|
"expression": "subject_urn",
|
|
"isExpression": false,
|
|
"asc": true,
|
|
"nulls": "last"
|
|
}
|
|
],
|
|
"isUnique": true,
|
|
"concurrently": false,
|
|
"method": "btree",
|
|
"with": {}
|
|
}
|
|
},
|
|
"foreignKeys": {},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {},
|
|
"policies": {},
|
|
"checkConstraints": {},
|
|
"isRLSEnabled": false
|
|
},
|
|
"public.metrics": {
|
|
"name": "metrics",
|
|
"schema": "",
|
|
"columns": {
|
|
"id": {
|
|
"name": "id",
|
|
"type": "serial",
|
|
"primaryKey": true,
|
|
"notNull": true
|
|
},
|
|
"publication_id": {
|
|
"name": "publication_id",
|
|
"type": "integer",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"collected_at": {
|
|
"name": "collected_at",
|
|
"type": "timestamp with time zone",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"default": "now()"
|
|
},
|
|
"impressions": {
|
|
"name": "impressions",
|
|
"type": "integer",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"default": 0
|
|
},
|
|
"reactions": {
|
|
"name": "reactions",
|
|
"type": "integer",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"default": 0
|
|
},
|
|
"comments": {
|
|
"name": "comments",
|
|
"type": "integer",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"default": 0
|
|
},
|
|
"shares": {
|
|
"name": "shares",
|
|
"type": "integer",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"default": 0
|
|
},
|
|
"clicks": {
|
|
"name": "clicks",
|
|
"type": "integer",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"default": 0
|
|
},
|
|
"raw_jsonb": {
|
|
"name": "raw_jsonb",
|
|
"type": "jsonb",
|
|
"primaryKey": false,
|
|
"notNull": false
|
|
}
|
|
},
|
|
"indexes": {},
|
|
"foreignKeys": {
|
|
"metrics_publication_id_publications_id_fk": {
|
|
"name": "metrics_publication_id_publications_id_fk",
|
|
"tableFrom": "metrics",
|
|
"tableTo": "publications",
|
|
"columnsFrom": [
|
|
"publication_id"
|
|
],
|
|
"columnsTo": [
|
|
"id"
|
|
],
|
|
"onDelete": "no action",
|
|
"onUpdate": "no action"
|
|
}
|
|
},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {},
|
|
"policies": {},
|
|
"checkConstraints": {},
|
|
"isRLSEnabled": false
|
|
},
|
|
"public.outlet_feature_flags": {
|
|
"name": "outlet_feature_flags",
|
|
"schema": "",
|
|
"columns": {
|
|
"outlet": {
|
|
"name": "outlet",
|
|
"type": "text",
|
|
"primaryKey": true,
|
|
"notNull": true
|
|
},
|
|
"enabled": {
|
|
"name": "enabled",
|
|
"type": "boolean",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"default": true
|
|
},
|
|
"reason": {
|
|
"name": "reason",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false
|
|
},
|
|
"updated_at": {
|
|
"name": "updated_at",
|
|
"type": "timestamp with time zone",
|
|
"primaryKey": false,
|
|
"notNull": true,
|
|
"default": "now()"
|
|
},
|
|
"updated_by": {
|
|
"name": "updated_by",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
}
|
|
},
|
|
"indexes": {},
|
|
"foreignKeys": {},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {},
|
|
"policies": {},
|
|
"checkConstraints": {},
|
|
"isRLSEnabled": false
|
|
},
|
|
"public.publications": {
|
|
"name": "publications",
|
|
"schema": "",
|
|
"columns": {
|
|
"id": {
|
|
"name": "id",
|
|
"type": "serial",
|
|
"primaryKey": true,
|
|
"notNull": true
|
|
},
|
|
"content_id": {
|
|
"name": "content_id",
|
|
"type": "integer",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"outlet": {
|
|
"name": "outlet",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"status": {
|
|
"name": "status",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"scheduled_at": {
|
|
"name": "scheduled_at",
|
|
"type": "timestamp with time zone",
|
|
"primaryKey": false,
|
|
"notNull": false
|
|
},
|
|
"published_at": {
|
|
"name": "published_at",
|
|
"type": "timestamp with time zone",
|
|
"primaryKey": false,
|
|
"notNull": false
|
|
},
|
|
"external_id": {
|
|
"name": "external_id",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false
|
|
},
|
|
"external_url": {
|
|
"name": "external_url",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false
|
|
},
|
|
"idempotency_key": {
|
|
"name": "idempotency_key",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": true
|
|
},
|
|
"error": {
|
|
"name": "error",
|
|
"type": "text",
|
|
"primaryKey": false,
|
|
"notNull": false
|
|
},
|
|
"metadata_jsonb": {
|
|
"name": "metadata_jsonb",
|
|
"type": "jsonb",
|
|
"primaryKey": false,
|
|
"notNull": false
|
|
}
|
|
},
|
|
"indexes": {
|
|
"publications_idempotency_key_idx": {
|
|
"name": "publications_idempotency_key_idx",
|
|
"columns": [
|
|
{
|
|
"expression": "idempotency_key",
|
|
"isExpression": false,
|
|
"asc": true,
|
|
"nulls": "last"
|
|
}
|
|
],
|
|
"isUnique": true,
|
|
"concurrently": false,
|
|
"method": "btree",
|
|
"with": {}
|
|
},
|
|
"publications_content_outlet_idx": {
|
|
"name": "publications_content_outlet_idx",
|
|
"columns": [
|
|
{
|
|
"expression": "content_id",
|
|
"isExpression": false,
|
|
"asc": true,
|
|
"nulls": "last"
|
|
},
|
|
{
|
|
"expression": "outlet",
|
|
"isExpression": false,
|
|
"asc": true,
|
|
"nulls": "last"
|
|
}
|
|
],
|
|
"isUnique": false,
|
|
"concurrently": false,
|
|
"method": "btree",
|
|
"with": {}
|
|
}
|
|
},
|
|
"foreignKeys": {
|
|
"publications_content_id_content_id_fk": {
|
|
"name": "publications_content_id_content_id_fk",
|
|
"tableFrom": "publications",
|
|
"tableTo": "content",
|
|
"columnsFrom": [
|
|
"content_id"
|
|
],
|
|
"columnsTo": [
|
|
"id"
|
|
],
|
|
"onDelete": "no action",
|
|
"onUpdate": "no action"
|
|
}
|
|
},
|
|
"compositePrimaryKeys": {},
|
|
"uniqueConstraints": {},
|
|
"policies": {},
|
|
"checkConstraints": {},
|
|
"isRLSEnabled": false
|
|
}
|
|
},
|
|
"enums": {},
|
|
"schemas": {},
|
|
"sequences": {},
|
|
"roles": {},
|
|
"policies": {},
|
|
"views": {},
|
|
"_meta": {
|
|
"columns": {},
|
|
"schemas": {},
|
|
"tables": {}
|
|
}
|
|
} |