The sprint 1 prototype only includes the current ministry, current
- portfolio mapping, and department-backed portfolio relationships.
+ office mapping, and department-backed office relationships.
;
};
+function SearchSectionHeading({
+ eyebrow,
+ title,
+}: {
+ eyebrow: string;
+ title: string;
+}) {
+ return (
+
+
+ {eyebrow}
+
+
+ {title}
+
+
+ );
+}
+
+function EmptySearchState({ body }: { body: string }) {
+ return (
+
+
+ No matches yet
+
+
+ {body}
+
+
+ );
+}
+
+function GeneralOrderSearchCard({
+ result,
+}: {
+ result: GeneralOrderSearchResult;
+}) {
+ if (result.kind === "office") {
+ return (
+
+
+ General Order office
+ {result.actEntryCount} Acts
+ {result.ruleCount} rules
+ {result.sharedRuleCount > 0 ? (
+ {result.sharedRuleCount} shared
+ ) : null}
+ {result.partialRuleCount > 0 ? (
+ {result.partialRuleCount} partial
+ ) : null}
+
+
+ {result.officeName}
+
+
+ Browse the Acts and carve-outs recorded for this office in the latest
+ imported General Order.
+
+
+ Match: {result.matchReason}
+
+
+ );
+ }
+
+ return (
+
+
+ General Order Act
+ {result.ruleCount} rules
+ {result.sharedRuleCount > 0 ? {result.sharedRuleCount} shared : null}
+ {result.partialRuleCount > 0 ? (
+ {result.partialRuleCount} partial
+ ) : null}
+
+
+ {result.actName}
+
+
+ Under {result.officeName}
+
+
+ {result.previewText}
+
+
+ Match: {result.matchReason}
+
+
+ );
+}
+
export default async function HomePage({ searchParams }: HomePageProps) {
const { q } = await searchParams;
const query = firstQueryValue(q)?.trim();
- const catalog = await loadGovernmentCatalog();
+ const [catalog, generalOrderSearch] = await Promise.all([
+ loadGovernmentCatalog(),
+ query ? loadGeneralOrderSearch(query) : Promise.resolve({ status: "empty" as const }),
+ ]);
const results = query ? searchGovernmentCatalog(catalog, query, 12) : [];
+ const generalOrderResults =
+ generalOrderSearch.status === "ready" ? generalOrderSearch.results : [];
+ const totalSearchMatches = results.length + generalOrderResults.length;
const featuredNodes = [
...catalog.nodes.filter((node) => node.nodeType === "budget_document").slice(0, 2),
...catalog.nodes.filter((node) => node.nodeType === "public_entity").slice(0, 2),
...catalog.nodes.filter((node) => node.nodeType === "department").slice(0, 2),
- ...catalog.nodes.filter((node) => node.nodeType === "person").slice(0, 2),
+ ...catalog.nodes.filter((node) => node.nodeType === "ministerial_office").slice(0, 1),
+ ...catalog.nodes.filter((node) => node.nodeType === "person").slice(0, 1),
].slice(0, 8);
const implementedConnectors = sourceRegistry.filter(
(entry) => entry.implementationStatus === "implemented",
@@ -46,10 +153,10 @@ export default async function HomePage({ searchParams }: HomePageProps) {
Victorian Government Map
- Search the Victorian Government across structure, entities, and budget papers.
+ Search the Victorian Government across offices, entities, and budget papers.
- The graph now combines the current ministry and portfolio map
+ The graph now combines the current ministry and office map
with the VPSC employers directory and the Victorian Budget paper
index, plus structured budget outputs and performance measures,
so public entities and budget records sit beside the core
@@ -57,6 +164,14 @@ export default async function HomePage({ searchParams }: HomePageProps) {
@@ -68,7 +183,7 @@ export default async function HomePage({ searchParams }: HomePageProps) {
{catalog.summary.totalNodes}
- records across ministers, departments, public entities, outputs,
+ records across ministers, offices, departments, public entities, outputs,
measures, and budget documents.
@@ -122,14 +237,101 @@ export default async function HomePage({ searchParams }: HomePageProps) {
{query ? (
- {results.length} matches
+ {totalSearchMatches} matches
) : null}
- {(query ? results.map((result) => result.node) : featuredNodes).map(
- (node) => (
+ {query ? (
+ <>
+ {results.length > 0 ? (
+ <>
+
+ {results.map((result) => {
+ const node = result.node;
+
+ return (
+
+
+ {humanizeNodeType(node.nodeType)}
+
+
+ {node.canonicalName}
+
+
+ {node.description ??
+ "Current record in the live government graph snapshot."}
+
+
+ );
+ })}
+ >
+ ) : null}
+
+ {generalOrderSearch.status === "ready" &&
+ generalOrderResults.length > 0 ? (
+ <>
+
+ {generalOrderResults.map((result) => (
+
+ ))}
+ >
+ ) : null}
+
+ {generalOrderSearch.status === "empty" ? (
+
+
+ General Order records are not loaded yet
+
+
+ The main atlas search is working, but Act allocation matches
+ will only appear after the General Order import has been
+ loaded into Postgres.
+
+
+ ) : null}
+
+ {generalOrderSearch.status === "error" ? (
+
+
+ General Order search is unavailable right now
+
+
+ The rest of the atlas search still works, but the app could
+ not reach the imported General Order records. Error:{" "}
+ {generalOrderSearch.message}
+
+
+ ) : null}
+
+ {results.length === 0 &&
+ generalOrderResults.length === 0 &&
+ generalOrderSearch.status === "ready" ? (
+
+ ) : null}
+ >
+ ) : (
+ featuredNodes.map((node) => (
- ),
+ ))
)}
diff --git a/apps/web/package.json b/apps/web/package.json
index 437b028..9ca3270 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -10,6 +10,7 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
+ "@govgraph/db": "workspace:*",
"@govgraph/domain": "workspace:*",
"@govgraph/parsers": "workspace:*",
"@govgraph/ui": "workspace:*",
diff --git a/apps/worker/package.json b/apps/worker/package.json
index 7254a8a..2da9d47 100644
--- a/apps/worker/package.json
+++ b/apps/worker/package.json
@@ -9,6 +9,7 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
+ "@govgraph/db": "workspace:*",
"@govgraph/parsers": "workspace:*",
"@trigger.dev/sdk": "^4.0.0"
}
diff --git a/apps/worker/src/index.ts b/apps/worker/src/index.ts
index 0694eb7..95d94b9 100644
--- a/apps/worker/src/index.ts
+++ b/apps/worker/src/index.ts
@@ -1,5 +1,6 @@
export * from "./tasks/crawl-budget-index";
export * from "./tasks/sync-budget-performance-measures";
+export * from "./tasks/sync-general-order";
export * from "./tasks/sync-ministry";
export * from "./tasks/sync-vpsc-employers";
export * from "./tasks/sync-vpsc-portfolios";
diff --git a/apps/worker/src/tasks/sync-general-order.ts b/apps/worker/src/tasks/sync-general-order.ts
new file mode 100644
index 0000000..838966e
--- /dev/null
+++ b/apps/worker/src/tasks/sync-general-order.ts
@@ -0,0 +1,22 @@
+import { task } from "@trigger.dev/sdk";
+
+import {
+ closeDbClient,
+ createDbClient,
+ persistGeneralOrderDataset,
+} from "@govgraph/db";
+import { fetchVicGovGeneralOrder } from "@govgraph/parsers";
+
+export const syncGeneralOrder = task({
+ id: "sync-general-order",
+ run: async () => {
+ const snapshot = await fetchVicGovGeneralOrder({ kanonAssistance: true });
+ const client = createDbClient();
+
+ try {
+ return await persistGeneralOrderDataset(client.db, snapshot);
+ } finally {
+ await closeDbClient(client);
+ }
+ },
+});
diff --git a/apps/worker/src/tasks/sync-ministry.ts b/apps/worker/src/tasks/sync-ministry.ts
index 23c2c17..f303700 100644
--- a/apps/worker/src/tasks/sync-ministry.ts
+++ b/apps/worker/src/tasks/sync-ministry.ts
@@ -9,8 +9,8 @@ export const syncMinistry = task({
return {
members: snapshot.members.length,
- portfolioAssignments: snapshot.members.reduce(
- (total, member) => total + member.titles.length,
+ officeAssignments: snapshot.members.reduce(
+ (total, member) => total + member.officeTitles.length,
0,
),
};
diff --git a/apps/worker/src/tasks/sync-vpsc-portfolios.ts b/apps/worker/src/tasks/sync-vpsc-portfolios.ts
index 8767063..af60188 100644
--- a/apps/worker/src/tasks/sync-vpsc-portfolios.ts
+++ b/apps/worker/src/tasks/sync-vpsc-portfolios.ts
@@ -10,8 +10,8 @@ export const syncVpscPortfolios = task({
return {
effectiveDate: snapshot.asOfDate,
departments: snapshot.sections.length,
- portfolios: snapshot.sections.reduce(
- (total, section) => total + section.portfolioTitles.length,
+ ministerialOffices: snapshot.sections.reduce(
+ (total, section) => total + section.officeTitles.length,
0,
),
};
diff --git a/data_model.md b/data_model.md
index 826665f..6e77c86 100644
--- a/data_model.md
+++ b/data_model.md
@@ -8,7 +8,7 @@ The key design decision is to separate **identity**, **relationships**, **metric
type NodeType =
| 'person'
| 'ministry'
- | 'portfolio'
+ | 'ministerial_office'
| 'department'
| 'administrative_office'
| 'public_entity'
@@ -22,7 +22,7 @@ type NodeType =
```ts
type EdgeType =
- | 'HOLDS_PORTFOLIO'
+ | 'HOLDS_OFFICE'
| 'MEMBER_OF_MINISTRY'
| 'SUPPORTED_BY_DEPARTMENT'
| 'IN_PORTFOLIO'
diff --git a/packages/db/drizzle/0000_brown_serpent_society.sql b/packages/db/drizzle/0000_brown_serpent_society.sql
new file mode 100644
index 0000000..39791a4
--- /dev/null
+++ b/packages/db/drizzle/0000_brown_serpent_society.sql
@@ -0,0 +1,191 @@
+CREATE TYPE "public"."administration_mode" AS ENUM('sole', 'joint', 'joint_and_several', 'unknown');--> statement-breakpoint
+CREATE TYPE "public"."administration_scope" AS ENUM('whole_act', 'provision_list', 'residual');--> statement-breakpoint
+CREATE TYPE "public"."alias_type" AS ENUM('acronym', 'former_name', 'source_name', 'short_name');--> statement-breakpoint
+CREATE TYPE "public"."assertion_confidence" AS ENUM('high', 'medium', 'low');--> statement-breakpoint
+CREATE TYPE "public"."budget_phase" AS ENUM('budget', 'revised', 'actual');--> statement-breakpoint
+CREATE TYPE "public"."change_event_type" AS ENUM('created', 'abolished', 'renamed', 'transferred', 'portfolio_changed');--> statement-breakpoint
+CREATE TYPE "public"."edge_type" AS ENUM('HOLDS_OFFICE', 'MEMBER_OF_MINISTRY', 'SUPPORTED_BY_DEPARTMENT', 'IN_PORTFOLIO', 'REPORTS_TO', 'RESPONSIBLE_FOR', 'DELIVERS_OUTPUT', 'HAS_PERFORMANCE_MEASURE', 'HAS_CAPITAL_PROJECT', 'FUNDED_BY', 'SUCCEEDED_BY', 'RENAMED_TO', 'MOVED_TO_PORTFOLIO', 'HAS_SOURCE');--> statement-breakpoint
+CREATE TYPE "public"."general_order_heading_style" AS ENUM('plain', 'except', 'scoped_list');--> statement-breakpoint
+CREATE TYPE "public"."general_order_parse_status" AS ENUM('parsed', 'partial');--> statement-breakpoint
+CREATE TYPE "public"."general_order_rule_kind" AS ENUM('default', 'listed_scope', 'residual');--> statement-breakpoint
+CREATE TYPE "public"."node_type" AS ENUM('person', 'ministry', 'ministerial_office', 'department', 'administrative_office', 'public_entity', 'program_output', 'capital_project', 'performance_measure', 'budget_document', 'source_document', 'organisation_group');--> statement-breakpoint
+CREATE TYPE "public"."record_status" AS ENUM('active', 'ceased', 'superseded', 'draft');--> statement-breakpoint
+CREATE TYPE "public"."source_confidence" AS ENUM('high', 'medium', 'low');--> statement-breakpoint
+CREATE TYPE "public"."source_family" AS ENUM('budget', 'gazette', 'vpsc', 'vic_gov', 'parliament');--> statement-breakpoint
+CREATE TYPE "public"."source_type" AS ENUM('html', 'pdf', 'xlsx', 'csv', 'api');--> statement-breakpoint
+CREATE TABLE "act_administration_rules" (
+ "id" uuid PRIMARY KEY NOT NULL,
+ "source_document_id" uuid NOT NULL,
+ "effective_date" date,
+ "office_name" text NOT NULL,
+ "act_name" text NOT NULL,
+ "heading_text" text NOT NULL,
+ "heading_style" "general_order_heading_style" NOT NULL,
+ "rule_kind" "general_order_rule_kind" NOT NULL,
+ "scope" "administration_scope" NOT NULL,
+ "raw_text" text NOT NULL,
+ "scope_text" text,
+ "administration_mode" "administration_mode" NOT NULL,
+ "administering_office_names" jsonb NOT NULL,
+ "provision_references" jsonb NOT NULL,
+ "nested_raw_texts" jsonb NOT NULL,
+ "parse_status" "general_order_parse_status" NOT NULL,
+ "unparsed_tail" text,
+ "kanon_assistance" jsonb,
+ "created_at" timestamp with time zone NOT NULL,
+ "updated_at" timestamp with time zone NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "change_events" (
+ "id" uuid PRIMARY KEY NOT NULL,
+ "event_type" "change_event_type" NOT NULL,
+ "affected_node_id" uuid,
+ "from_node_id" uuid,
+ "to_node_id" uuid,
+ "effective_date" date NOT NULL,
+ "source_document_id" uuid NOT NULL,
+ "summary" text NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "edge_source_documents" (
+ "edge_id" uuid NOT NULL,
+ "source_document_id" uuid NOT NULL,
+ CONSTRAINT "edge_source_documents_edge_id_source_document_id_pk" PRIMARY KEY("edge_id","source_document_id")
+);
+--> statement-breakpoint
+CREATE TABLE "edges" (
+ "id" uuid PRIMARY KEY NOT NULL,
+ "edge_type" "edge_type" NOT NULL,
+ "from_node_id" uuid NOT NULL,
+ "to_node_id" uuid NOT NULL,
+ "valid_from" date,
+ "valid_to" date,
+ "status" "record_status" DEFAULT 'active' NOT NULL,
+ "notes" text
+);
+--> statement-breakpoint
+CREATE TABLE "budget_metrics" (
+ "id" uuid PRIMARY KEY NOT NULL,
+ "node_id" uuid NOT NULL,
+ "metric_family" text NOT NULL,
+ "metric_name" text NOT NULL,
+ "amount" numeric,
+ "currency" text DEFAULT 'AUD' NOT NULL,
+ "fiscal_year" text NOT NULL,
+ "budget_phase" "budget_phase" DEFAULT 'budget' NOT NULL,
+ "source_document_id" uuid NOT NULL,
+ "notes" text
+);
+--> statement-breakpoint
+CREATE TABLE "capital_projects" (
+ "id" uuid PRIMARY KEY NOT NULL,
+ "node_id" uuid,
+ "project_name" text NOT NULL,
+ "category" text,
+ "project_type" text,
+ "location_text" text,
+ "investment_amount" numeric,
+ "fiscal_year" text,
+ "source_document_id" uuid NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "performance_measures" (
+ "id" uuid PRIMARY KEY NOT NULL,
+ "node_id" uuid NOT NULL,
+ "measure_name" text NOT NULL,
+ "measure_unit" text,
+ "target_value" text,
+ "actual_value" text,
+ "period_label" text NOT NULL,
+ "source_document_id" uuid NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "workforce_metrics" (
+ "id" uuid PRIMARY KEY NOT NULL,
+ "node_id" uuid NOT NULL,
+ "metric_name" text NOT NULL,
+ "metric_value" numeric NOT NULL,
+ "as_at_date" date NOT NULL,
+ "source_document_id" uuid NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "node_aliases" (
+ "id" uuid PRIMARY KEY NOT NULL,
+ "node_id" uuid NOT NULL,
+ "alias" text NOT NULL,
+ "alias_type" "alias_type" NOT NULL,
+ "source_document_id" uuid,
+ "valid_from" date,
+ "valid_to" date
+);
+--> statement-breakpoint
+CREATE TABLE "nodes" (
+ "id" uuid PRIMARY KEY NOT NULL,
+ "node_type" "node_type" NOT NULL,
+ "canonical_name" text NOT NULL,
+ "slug" text NOT NULL,
+ "status" "record_status" DEFAULT 'active' NOT NULL,
+ "description" text,
+ "website_url" text,
+ "source_confidence" "source_confidence" DEFAULT 'high' NOT NULL,
+ "created_at" timestamp with time zone NOT NULL,
+ "updated_at" timestamp with time zone NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "source_assertions" (
+ "id" uuid PRIMARY KEY NOT NULL,
+ "source_document_id" uuid NOT NULL,
+ "subject_text" text NOT NULL,
+ "predicate" text NOT NULL,
+ "object_text" text,
+ "value_json" jsonb,
+ "page_ref" text,
+ "row_ref" text,
+ "extracted_at" timestamp with time zone NOT NULL,
+ "confidence" "assertion_confidence" NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "source_documents" (
+ "id" uuid PRIMARY KEY NOT NULL,
+ "source_type" "source_type" NOT NULL,
+ "source_family" "source_family" NOT NULL,
+ "title" text NOT NULL,
+ "source_url" text NOT NULL,
+ "publisher" text NOT NULL,
+ "publication_date" date,
+ "effective_date" date,
+ "retrieved_at" timestamp with time zone NOT NULL,
+ "checksum" text,
+ "parser_version" text NOT NULL,
+ "licence" text,
+ "raw_storage_path" text NOT NULL
+);
+--> statement-breakpoint
+ALTER TABLE "act_administration_rules" ADD CONSTRAINT "act_administration_rules_source_document_id_source_documents_id_fk" FOREIGN KEY ("source_document_id") REFERENCES "public"."source_documents"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "change_events" ADD CONSTRAINT "change_events_affected_node_id_nodes_id_fk" FOREIGN KEY ("affected_node_id") REFERENCES "public"."nodes"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "change_events" ADD CONSTRAINT "change_events_from_node_id_nodes_id_fk" FOREIGN KEY ("from_node_id") REFERENCES "public"."nodes"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "change_events" ADD CONSTRAINT "change_events_to_node_id_nodes_id_fk" FOREIGN KEY ("to_node_id") REFERENCES "public"."nodes"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "change_events" ADD CONSTRAINT "change_events_source_document_id_source_documents_id_fk" FOREIGN KEY ("source_document_id") REFERENCES "public"."source_documents"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "edge_source_documents" ADD CONSTRAINT "edge_source_documents_edge_id_edges_id_fk" FOREIGN KEY ("edge_id") REFERENCES "public"."edges"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "edge_source_documents" ADD CONSTRAINT "edge_source_documents_source_document_id_source_documents_id_fk" FOREIGN KEY ("source_document_id") REFERENCES "public"."source_documents"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "edges" ADD CONSTRAINT "edges_from_node_id_nodes_id_fk" FOREIGN KEY ("from_node_id") REFERENCES "public"."nodes"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "edges" ADD CONSTRAINT "edges_to_node_id_nodes_id_fk" FOREIGN KEY ("to_node_id") REFERENCES "public"."nodes"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "budget_metrics" ADD CONSTRAINT "budget_metrics_node_id_nodes_id_fk" FOREIGN KEY ("node_id") REFERENCES "public"."nodes"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "budget_metrics" ADD CONSTRAINT "budget_metrics_source_document_id_source_documents_id_fk" FOREIGN KEY ("source_document_id") REFERENCES "public"."source_documents"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "capital_projects" ADD CONSTRAINT "capital_projects_node_id_nodes_id_fk" FOREIGN KEY ("node_id") REFERENCES "public"."nodes"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "capital_projects" ADD CONSTRAINT "capital_projects_source_document_id_source_documents_id_fk" FOREIGN KEY ("source_document_id") REFERENCES "public"."source_documents"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "performance_measures" ADD CONSTRAINT "performance_measures_node_id_nodes_id_fk" FOREIGN KEY ("node_id") REFERENCES "public"."nodes"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "performance_measures" ADD CONSTRAINT "performance_measures_source_document_id_source_documents_id_fk" FOREIGN KEY ("source_document_id") REFERENCES "public"."source_documents"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "workforce_metrics" ADD CONSTRAINT "workforce_metrics_node_id_nodes_id_fk" FOREIGN KEY ("node_id") REFERENCES "public"."nodes"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "workforce_metrics" ADD CONSTRAINT "workforce_metrics_source_document_id_source_documents_id_fk" FOREIGN KEY ("source_document_id") REFERENCES "public"."source_documents"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "node_aliases" ADD CONSTRAINT "node_aliases_node_id_nodes_id_fk" FOREIGN KEY ("node_id") REFERENCES "public"."nodes"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "node_aliases" ADD CONSTRAINT "node_aliases_source_document_id_source_documents_id_fk" FOREIGN KEY ("source_document_id") REFERENCES "public"."source_documents"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "source_assertions" ADD CONSTRAINT "source_assertions_source_document_id_source_documents_id_fk" FOREIGN KEY ("source_document_id") REFERENCES "public"."source_documents"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
+CREATE INDEX "act_administration_rules_source_document_idx" ON "act_administration_rules" USING btree ("source_document_id");--> statement-breakpoint
+CREATE INDEX "act_administration_rules_office_lookup_idx" ON "act_administration_rules" USING btree ("office_name","act_name");--> statement-breakpoint
+CREATE INDEX "edge_source_documents_source_document_idx" ON "edge_source_documents" USING btree ("source_document_id");--> statement-breakpoint
+CREATE INDEX "edges_lookup_idx" ON "edges" USING btree ("edge_type","from_node_id","to_node_id");--> statement-breakpoint
+CREATE INDEX "node_aliases_node_alias_idx" ON "node_aliases" USING btree ("node_id","alias");--> statement-breakpoint
+CREATE UNIQUE INDEX "nodes_slug_idx" ON "nodes" USING btree ("slug");--> statement-breakpoint
+CREATE INDEX "nodes_type_name_idx" ON "nodes" USING btree ("node_type","canonical_name");--> statement-breakpoint
+CREATE UNIQUE INDEX "source_documents_source_url_idx" ON "source_documents" USING btree ("source_url");
diff --git a/packages/db/drizzle/meta/0000_snapshot.json b/packages/db/drizzle/meta/0000_snapshot.json
new file mode 100644
index 0000000..f022c6d
--- /dev/null
+++ b/packages/db/drizzle/meta/0000_snapshot.json
@@ -0,0 +1,1460 @@
+{
+ "id": "665ea40a-a5ca-46c2-a52d-0bece0c15f63",
+ "prevId": "00000000-0000-0000-0000-000000000000",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "public.act_administration_rules": {
+ "name": "act_administration_rules",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "source_document_id": {
+ "name": "source_document_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "effective_date": {
+ "name": "effective_date",
+ "type": "date",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "office_name": {
+ "name": "office_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "act_name": {
+ "name": "act_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "heading_text": {
+ "name": "heading_text",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "heading_style": {
+ "name": "heading_style",
+ "type": "general_order_heading_style",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "rule_kind": {
+ "name": "rule_kind",
+ "type": "general_order_rule_kind",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "scope": {
+ "name": "scope",
+ "type": "administration_scope",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "raw_text": {
+ "name": "raw_text",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "scope_text": {
+ "name": "scope_text",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "administration_mode": {
+ "name": "administration_mode",
+ "type": "administration_mode",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "administering_office_names": {
+ "name": "administering_office_names",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "provision_references": {
+ "name": "provision_references",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nested_raw_texts": {
+ "name": "nested_raw_texts",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "parse_status": {
+ "name": "parse_status",
+ "type": "general_order_parse_status",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "unparsed_tail": {
+ "name": "unparsed_tail",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "kanon_assistance": {
+ "name": "kanon_assistance",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "act_administration_rules_source_document_idx": {
+ "name": "act_administration_rules_source_document_idx",
+ "columns": [
+ {
+ "expression": "source_document_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "act_administration_rules_office_lookup_idx": {
+ "name": "act_administration_rules_office_lookup_idx",
+ "columns": [
+ {
+ "expression": "office_name",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "act_name",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "act_administration_rules_source_document_id_source_documents_id_fk": {
+ "name": "act_administration_rules_source_document_id_source_documents_id_fk",
+ "tableFrom": "act_administration_rules",
+ "tableTo": "source_documents",
+ "columnsFrom": [
+ "source_document_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.change_events": {
+ "name": "change_events",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "event_type": {
+ "name": "event_type",
+ "type": "change_event_type",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "affected_node_id": {
+ "name": "affected_node_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "from_node_id": {
+ "name": "from_node_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "to_node_id": {
+ "name": "to_node_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "effective_date": {
+ "name": "effective_date",
+ "type": "date",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "source_document_id": {
+ "name": "source_document_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "summary": {
+ "name": "summary",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "change_events_affected_node_id_nodes_id_fk": {
+ "name": "change_events_affected_node_id_nodes_id_fk",
+ "tableFrom": "change_events",
+ "tableTo": "nodes",
+ "columnsFrom": [
+ "affected_node_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "change_events_from_node_id_nodes_id_fk": {
+ "name": "change_events_from_node_id_nodes_id_fk",
+ "tableFrom": "change_events",
+ "tableTo": "nodes",
+ "columnsFrom": [
+ "from_node_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "change_events_to_node_id_nodes_id_fk": {
+ "name": "change_events_to_node_id_nodes_id_fk",
+ "tableFrom": "change_events",
+ "tableTo": "nodes",
+ "columnsFrom": [
+ "to_node_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "change_events_source_document_id_source_documents_id_fk": {
+ "name": "change_events_source_document_id_source_documents_id_fk",
+ "tableFrom": "change_events",
+ "tableTo": "source_documents",
+ "columnsFrom": [
+ "source_document_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.edge_source_documents": {
+ "name": "edge_source_documents",
+ "schema": "",
+ "columns": {
+ "edge_id": {
+ "name": "edge_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "source_document_id": {
+ "name": "source_document_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "edge_source_documents_source_document_idx": {
+ "name": "edge_source_documents_source_document_idx",
+ "columns": [
+ {
+ "expression": "source_document_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "edge_source_documents_edge_id_edges_id_fk": {
+ "name": "edge_source_documents_edge_id_edges_id_fk",
+ "tableFrom": "edge_source_documents",
+ "tableTo": "edges",
+ "columnsFrom": [
+ "edge_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "edge_source_documents_source_document_id_source_documents_id_fk": {
+ "name": "edge_source_documents_source_document_id_source_documents_id_fk",
+ "tableFrom": "edge_source_documents",
+ "tableTo": "source_documents",
+ "columnsFrom": [
+ "source_document_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "edge_source_documents_edge_id_source_document_id_pk": {
+ "name": "edge_source_documents_edge_id_source_document_id_pk",
+ "columns": [
+ "edge_id",
+ "source_document_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.edges": {
+ "name": "edges",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "edge_type": {
+ "name": "edge_type",
+ "type": "edge_type",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "from_node_id": {
+ "name": "from_node_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "to_node_id": {
+ "name": "to_node_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "valid_from": {
+ "name": "valid_from",
+ "type": "date",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "valid_to": {
+ "name": "valid_to",
+ "type": "date",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "status": {
+ "name": "status",
+ "type": "record_status",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'active'"
+ },
+ "notes": {
+ "name": "notes",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "edges_lookup_idx": {
+ "name": "edges_lookup_idx",
+ "columns": [
+ {
+ "expression": "edge_type",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "from_node_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "to_node_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "edges_from_node_id_nodes_id_fk": {
+ "name": "edges_from_node_id_nodes_id_fk",
+ "tableFrom": "edges",
+ "tableTo": "nodes",
+ "columnsFrom": [
+ "from_node_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "edges_to_node_id_nodes_id_fk": {
+ "name": "edges_to_node_id_nodes_id_fk",
+ "tableFrom": "edges",
+ "tableTo": "nodes",
+ "columnsFrom": [
+ "to_node_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.budget_metrics": {
+ "name": "budget_metrics",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "node_id": {
+ "name": "node_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "metric_family": {
+ "name": "metric_family",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "metric_name": {
+ "name": "metric_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "amount": {
+ "name": "amount",
+ "type": "numeric",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "currency": {
+ "name": "currency",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'AUD'"
+ },
+ "fiscal_year": {
+ "name": "fiscal_year",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "budget_phase": {
+ "name": "budget_phase",
+ "type": "budget_phase",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'budget'"
+ },
+ "source_document_id": {
+ "name": "source_document_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "notes": {
+ "name": "notes",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "budget_metrics_node_id_nodes_id_fk": {
+ "name": "budget_metrics_node_id_nodes_id_fk",
+ "tableFrom": "budget_metrics",
+ "tableTo": "nodes",
+ "columnsFrom": [
+ "node_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "budget_metrics_source_document_id_source_documents_id_fk": {
+ "name": "budget_metrics_source_document_id_source_documents_id_fk",
+ "tableFrom": "budget_metrics",
+ "tableTo": "source_documents",
+ "columnsFrom": [
+ "source_document_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.capital_projects": {
+ "name": "capital_projects",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "node_id": {
+ "name": "node_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "project_name": {
+ "name": "project_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "category": {
+ "name": "category",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "project_type": {
+ "name": "project_type",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "location_text": {
+ "name": "location_text",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "investment_amount": {
+ "name": "investment_amount",
+ "type": "numeric",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "fiscal_year": {
+ "name": "fiscal_year",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "source_document_id": {
+ "name": "source_document_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "capital_projects_node_id_nodes_id_fk": {
+ "name": "capital_projects_node_id_nodes_id_fk",
+ "tableFrom": "capital_projects",
+ "tableTo": "nodes",
+ "columnsFrom": [
+ "node_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "capital_projects_source_document_id_source_documents_id_fk": {
+ "name": "capital_projects_source_document_id_source_documents_id_fk",
+ "tableFrom": "capital_projects",
+ "tableTo": "source_documents",
+ "columnsFrom": [
+ "source_document_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.performance_measures": {
+ "name": "performance_measures",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "node_id": {
+ "name": "node_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "measure_name": {
+ "name": "measure_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "measure_unit": {
+ "name": "measure_unit",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "target_value": {
+ "name": "target_value",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "actual_value": {
+ "name": "actual_value",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "period_label": {
+ "name": "period_label",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "source_document_id": {
+ "name": "source_document_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "performance_measures_node_id_nodes_id_fk": {
+ "name": "performance_measures_node_id_nodes_id_fk",
+ "tableFrom": "performance_measures",
+ "tableTo": "nodes",
+ "columnsFrom": [
+ "node_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "performance_measures_source_document_id_source_documents_id_fk": {
+ "name": "performance_measures_source_document_id_source_documents_id_fk",
+ "tableFrom": "performance_measures",
+ "tableTo": "source_documents",
+ "columnsFrom": [
+ "source_document_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.workforce_metrics": {
+ "name": "workforce_metrics",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "node_id": {
+ "name": "node_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "metric_name": {
+ "name": "metric_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "metric_value": {
+ "name": "metric_value",
+ "type": "numeric",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "as_at_date": {
+ "name": "as_at_date",
+ "type": "date",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "source_document_id": {
+ "name": "source_document_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "workforce_metrics_node_id_nodes_id_fk": {
+ "name": "workforce_metrics_node_id_nodes_id_fk",
+ "tableFrom": "workforce_metrics",
+ "tableTo": "nodes",
+ "columnsFrom": [
+ "node_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "workforce_metrics_source_document_id_source_documents_id_fk": {
+ "name": "workforce_metrics_source_document_id_source_documents_id_fk",
+ "tableFrom": "workforce_metrics",
+ "tableTo": "source_documents",
+ "columnsFrom": [
+ "source_document_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.node_aliases": {
+ "name": "node_aliases",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "node_id": {
+ "name": "node_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "alias": {
+ "name": "alias",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "alias_type": {
+ "name": "alias_type",
+ "type": "alias_type",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "source_document_id": {
+ "name": "source_document_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "valid_from": {
+ "name": "valid_from",
+ "type": "date",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "valid_to": {
+ "name": "valid_to",
+ "type": "date",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "node_aliases_node_alias_idx": {
+ "name": "node_aliases_node_alias_idx",
+ "columns": [
+ {
+ "expression": "node_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "alias",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "node_aliases_node_id_nodes_id_fk": {
+ "name": "node_aliases_node_id_nodes_id_fk",
+ "tableFrom": "node_aliases",
+ "tableTo": "nodes",
+ "columnsFrom": [
+ "node_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "node_aliases_source_document_id_source_documents_id_fk": {
+ "name": "node_aliases_source_document_id_source_documents_id_fk",
+ "tableFrom": "node_aliases",
+ "tableTo": "source_documents",
+ "columnsFrom": [
+ "source_document_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.nodes": {
+ "name": "nodes",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "node_type": {
+ "name": "node_type",
+ "type": "node_type",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "canonical_name": {
+ "name": "canonical_name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "status": {
+ "name": "status",
+ "type": "record_status",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'active'"
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "website_url": {
+ "name": "website_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "source_confidence": {
+ "name": "source_confidence",
+ "type": "source_confidence",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'high'"
+ },
+ "created_at": {
+ "name": "created_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "updated_at": {
+ "name": "updated_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "nodes_slug_idx": {
+ "name": "nodes_slug_idx",
+ "columns": [
+ {
+ "expression": "slug",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "nodes_type_name_idx": {
+ "name": "nodes_type_name_idx",
+ "columns": [
+ {
+ "expression": "node_type",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "canonical_name",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.source_assertions": {
+ "name": "source_assertions",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "source_document_id": {
+ "name": "source_document_id",
+ "type": "uuid",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "subject_text": {
+ "name": "subject_text",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "predicate": {
+ "name": "predicate",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "object_text": {
+ "name": "object_text",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "value_json": {
+ "name": "value_json",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "page_ref": {
+ "name": "page_ref",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "row_ref": {
+ "name": "row_ref",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "extracted_at": {
+ "name": "extracted_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "confidence": {
+ "name": "confidence",
+ "type": "assertion_confidence",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "source_assertions_source_document_id_source_documents_id_fk": {
+ "name": "source_assertions_source_document_id_source_documents_id_fk",
+ "tableFrom": "source_assertions",
+ "tableTo": "source_documents",
+ "columnsFrom": [
+ "source_document_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.source_documents": {
+ "name": "source_documents",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "uuid",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "source_type": {
+ "name": "source_type",
+ "type": "source_type",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "source_family": {
+ "name": "source_family",
+ "type": "source_family",
+ "typeSchema": "public",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "title": {
+ "name": "title",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "source_url": {
+ "name": "source_url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "publisher": {
+ "name": "publisher",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "publication_date": {
+ "name": "publication_date",
+ "type": "date",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "effective_date": {
+ "name": "effective_date",
+ "type": "date",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "retrieved_at": {
+ "name": "retrieved_at",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "checksum": {
+ "name": "checksum",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "parser_version": {
+ "name": "parser_version",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "licence": {
+ "name": "licence",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "raw_storage_path": {
+ "name": "raw_storage_path",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "source_documents_source_url_idx": {
+ "name": "source_documents_source_url_idx",
+ "columns": [
+ {
+ "expression": "source_url",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ }
+ },
+ "enums": {
+ "public.administration_mode": {
+ "name": "administration_mode",
+ "schema": "public",
+ "values": [
+ "sole",
+ "joint",
+ "joint_and_several",
+ "unknown"
+ ]
+ },
+ "public.administration_scope": {
+ "name": "administration_scope",
+ "schema": "public",
+ "values": [
+ "whole_act",
+ "provision_list",
+ "residual"
+ ]
+ },
+ "public.alias_type": {
+ "name": "alias_type",
+ "schema": "public",
+ "values": [
+ "acronym",
+ "former_name",
+ "source_name",
+ "short_name"
+ ]
+ },
+ "public.assertion_confidence": {
+ "name": "assertion_confidence",
+ "schema": "public",
+ "values": [
+ "high",
+ "medium",
+ "low"
+ ]
+ },
+ "public.budget_phase": {
+ "name": "budget_phase",
+ "schema": "public",
+ "values": [
+ "budget",
+ "revised",
+ "actual"
+ ]
+ },
+ "public.change_event_type": {
+ "name": "change_event_type",
+ "schema": "public",
+ "values": [
+ "created",
+ "abolished",
+ "renamed",
+ "transferred",
+ "portfolio_changed"
+ ]
+ },
+ "public.edge_type": {
+ "name": "edge_type",
+ "schema": "public",
+ "values": [
+ "HOLDS_OFFICE",
+ "MEMBER_OF_MINISTRY",
+ "SUPPORTED_BY_DEPARTMENT",
+ "IN_PORTFOLIO",
+ "REPORTS_TO",
+ "RESPONSIBLE_FOR",
+ "DELIVERS_OUTPUT",
+ "HAS_PERFORMANCE_MEASURE",
+ "HAS_CAPITAL_PROJECT",
+ "FUNDED_BY",
+ "SUCCEEDED_BY",
+ "RENAMED_TO",
+ "MOVED_TO_PORTFOLIO",
+ "HAS_SOURCE"
+ ]
+ },
+ "public.general_order_heading_style": {
+ "name": "general_order_heading_style",
+ "schema": "public",
+ "values": [
+ "plain",
+ "except",
+ "scoped_list"
+ ]
+ },
+ "public.general_order_parse_status": {
+ "name": "general_order_parse_status",
+ "schema": "public",
+ "values": [
+ "parsed",
+ "partial"
+ ]
+ },
+ "public.general_order_rule_kind": {
+ "name": "general_order_rule_kind",
+ "schema": "public",
+ "values": [
+ "default",
+ "listed_scope",
+ "residual"
+ ]
+ },
+ "public.node_type": {
+ "name": "node_type",
+ "schema": "public",
+ "values": [
+ "person",
+ "ministry",
+ "ministerial_office",
+ "department",
+ "administrative_office",
+ "public_entity",
+ "program_output",
+ "capital_project",
+ "performance_measure",
+ "budget_document",
+ "source_document",
+ "organisation_group"
+ ]
+ },
+ "public.record_status": {
+ "name": "record_status",
+ "schema": "public",
+ "values": [
+ "active",
+ "ceased",
+ "superseded",
+ "draft"
+ ]
+ },
+ "public.source_confidence": {
+ "name": "source_confidence",
+ "schema": "public",
+ "values": [
+ "high",
+ "medium",
+ "low"
+ ]
+ },
+ "public.source_family": {
+ "name": "source_family",
+ "schema": "public",
+ "values": [
+ "budget",
+ "gazette",
+ "vpsc",
+ "vic_gov",
+ "parliament"
+ ]
+ },
+ "public.source_type": {
+ "name": "source_type",
+ "schema": "public",
+ "values": [
+ "html",
+ "pdf",
+ "xlsx",
+ "csv",
+ "api"
+ ]
+ }
+ },
+ "schemas": {},
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
diff --git a/packages/db/drizzle/meta/_journal.json b/packages/db/drizzle/meta/_journal.json
new file mode 100644
index 0000000..5d1c1ec
--- /dev/null
+++ b/packages/db/drizzle/meta/_journal.json
@@ -0,0 +1,13 @@
+{
+ "version": "7",
+ "dialect": "postgresql",
+ "entries": [
+ {
+ "idx": 0,
+ "version": "7",
+ "when": 1775551509841,
+ "tag": "0000_brown_serpent_society",
+ "breakpoints": true
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/db/package.json b/packages/db/package.json
index 97e8b85..7d478b5 100644
--- a/packages/db/package.json
+++ b/packages/db/package.json
@@ -9,9 +9,15 @@
"types": "./src/index.ts",
"scripts": {
"build": "tsc --noEmit",
- "typecheck": "tsc --noEmit"
+ "typecheck": "tsc --noEmit",
+ "test": "vitest run"
},
"dependencies": {
- "drizzle-orm": "^0.44.6"
+ "@govgraph/domain": "workspace:*",
+ "drizzle-orm": "^0.44.6",
+ "pg": "^8.16.3"
+ },
+ "devDependencies": {
+ "@types/pg": "^8.20.0"
}
}
diff --git a/packages/db/src/client.ts b/packages/db/src/client.ts
new file mode 100644
index 0000000..09e8928
--- /dev/null
+++ b/packages/db/src/client.ts
@@ -0,0 +1,28 @@
+import { drizzle, type NodePgDatabase } from "drizzle-orm/node-postgres";
+import { Pool } from "pg";
+
+import * as schema from "./schema";
+
+const DEFAULT_DATABASE_URL = "postgresql://postgres:postgres@localhost:5432/govgraph";
+
+export type GovgraphDb = NodePgDatabase