Documentation
¶
Overview ¶
Package migration ports a legacy `hanzo_cloud` PostgreSQL database into per-(org, user) SQLite files served by the Hanzo cloud orchestrator (HIP-0106).
Why introspective (not schema-aware):
Status owns its schema (7 tables in tree). kms's audit_logs subset is documented upstream. cloud's hanzo_cloud DB was the deployed cloud-api Python service — its schema is not in this Go repo and has drifted over multiple Python/TS versions across env. The right thing is to discover tables at migration time from information_schema and copy each one verbatim, with per-row routing to the destination SQLite file based on the row's org column.
Per-(org, user) routing:
The destination layout is the canonical `/data/<org>/<user>/cloud.sqlite` for user-scoped rows, or `/data/<org>/_org/cloud.sqlite` for org-scoped rows that no single user owns. The migrator inspects each table for an org column (canonical name: "org_id", fallback: "owner") and a user column (canonical: "user_id", fallback: "user_email"). Routing matrix:
has user_id → /data/<org>/<user_id>/cloud.sqlite
has org_id only → /data/<org>/_org/cloud.sqlite
has neither → /data/_global/_org/cloud.sqlite (fail-loud — a row
without org context is a data-quality bug; we
materialise it under _global so the operator can
triage rather than silently dropping)
Schema fidelity:
Each destination SQLite file gets the same DDL for every source table the migrator visits, lifted from information_schema.columns. PG-specific column types are mapped conservatively:
int*, bigint, serial → INTEGER bool, boolean → INTEGER (0/1) text, varchar, char → TEXT timestamp, timestamptz → TEXT (RFC3339Nano UTC) jsonb, json → TEXT bytea → BLOB numeric, decimal, real, double precision → REAL uuid → TEXT (other) → TEXT
This is the same conservative shape hanzoai/base uses for its generated DDL — see HIP-0302 §3. Hand-rolling per-type translation is the only correct choice across heterogeneous legacy schemas.
See ~/work/hanzo/CLAUDE_PG_TO_SQLITE_MIGRATION.md (service #4 — cloud).
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ColumnInfo ¶
ColumnInfo describes one PG column for SQLite DDL synthesis.
type Options ¶
type Options struct {
// SrcDSN is the legacy hanzo_cloud Postgres DSN.
SrcDSN string
// DstRoot is the data root under which per-(org, user) SQLite
// files are created. Conventionally /data per
// CLAUDE_PG_TO_SQLITE_MIGRATION.md.
DstRoot string
// IncludeSchemas, if non-empty, restricts the migration to tables
// from this set of PG schemas. Default ["public"].
IncludeSchemas []string
// ExcludeTables, if non-empty, skips matching tables (basename match
// only — schema-qualified names are not matched).
ExcludeTables []string
// BatchSize bounds memory use. Default 500.
BatchSize int
}
Options configures the migration.
type TableInfo ¶
type TableInfo struct {
Schema string
Name string
Columns []ColumnInfo
// OrgCol / UserCol are the resolved (org, user) routing columns;
// empty when no recognised column exists.
OrgCol string
UserCol string
}
TableInfo is the discovered metadata for one PG table.
func (TableInfo) QualifiedName ¶
QualifiedName returns schema.name with quoting that PG accepts. For schemaless sources (SQLite test fixtures) it returns the bare quoted table name. The SQL the migrator emits uses this same form, which is what allows the SQLite-as-source test path to drive the same copyTable code as production PG.