Skip to main content

Crate cratefield_import_supabase

Crate cratefield_import_supabase 

Source
Expand description

cratefield-import-supabase: step one of moving a Supabase project onto the harness (ADR 0026, issue #658). inspect connects read-only to the project’s Postgres — plus, optionally, the Supabase Management API for what Postgres cannot see — and returns a Report: every schema object, RLS policy, auth provider, storage bucket, Edge Function and Realtime publication, each classified as automatic, needs work or a blocker, with a size and transfer-time estimate.

It never writes. The later steps (auth users, schema and data, storage, cutover) read the report’s JSON; docs/import/supabase-report.md documents it.

Step two (issue #659) is read_users: the same read-only snapshot, but rows — the auth users as the admin import contract, plus the map record_mapping writes so the data step can rewrite their references.

use cratefield_import_supabase::{InspectOptions, Secret, inspect};

let options = InspectOptions::new("abcdefghijklmnopqrst", Secret::new(std::env::var("SUPABASE_DB_URL").unwrap()));
let report = inspect(&options).await?;
println!("{}", report.to_markdown());

Re-exports§

pub use dispositions::DispositionsError;
pub use dispositions::DispositionsFile;
pub use dispositions::apply as apply_dispositions;
pub use dispositions::skeleton;
pub use management::AuthConfig;
pub use management::DEFAULT_API_BASE;
pub use management::ManagementApi;
pub use management::ManagementError;
pub use plan::PLAN_VERSION;
pub use plan::Plan;
pub use plan::PlanBlocker;
pub use plan::PlanDrift;
pub use plan::TargetFacts;
pub use plan::build_plan;
pub use plan::check_drift;
pub use plan::inspection_hash;
pub use plan::read_target;
pub use report::*;

Modules§

dispositions
Dispositions: the per-item decision every needs-work and blocker item needs before cutover (ADR 0026, Decision 5).
extensions
What the harness Postgres target can do with each extension a Supabase project may have installed.
management
The two Supabase Management API reads inspect makes, for what Postgres cannot see: the Edge Functions and the auth configuration.
plan
The migration plan: what the importer will do, tied to the inspection it was written from (ADR 0026, Decision 3; issue #728).
policy
What an RLS policy amounts to, and the Cratefield check to write for it.
report
The migration report: what inspect saw, and what each item needs.

Structs§

ImportIdentity
One OIDC link for ImportRecord::identities: the harness slug and the source’s sub.
ImportPlan
Everything read_users read, in auth.users.id order; every count is exact (the whole table, not a page of it). Debug prints counts only — never a record, an address or the metadata.
ImportRecord
One user in the admin import contract. Debug prints ids, flags and counts only — never the address, a subject or the hash; the JSON carries the address and the hash for the import to store.
InspectOptions
What inspect needs.
MappedUser
One row for the mapping table: a Supabase user, the account the import created for it, and its source metadata.
MappingCounts
What record_mapping did.
ReadOnlySession
One connection, in one read-only transaction.
Secret
A secret string: cleared on drop, and Debug prints [redacted], so a stray {:?} cannot disclose it.
SkippedUser
A user not imported, and why.
SourceName
The part of a connection string a report may show.
UnmappedProvider
One Supabase OAuth provider none of whose identities were linked, with the users left to sign in by magic link.
UserMetadata
A user’s source-side metadata (raw_user_meta_data / raw_app_meta_data): carried to the mapping table, never to the harness, whose accounts have no metadata column yet. No Debug: the values are the source’s own, so a stray {:?} must not print them.
UsersOptions
What read_users needs.

Enums§

InspectError
Why an inspection stopped. The exit code is non-zero for every one of them; a blocker is never one of them (it is part of the report).
MappingError
Why a mapping write failed.
SkipReason
Why a user is not imported.

Constants§

DEFAULT_BATCH_SIZE
Users read per keyset page when none is set on UsersOptions.
DEFAULT_TRANSFER_MBPS
The throughput the transfer estimate assumes when none is given, in megabits per second.
EXTERNAL_PROVIDER
The external_provider every record carries: the source system, so a re-run and another source’s ids never collide.

Functions§

connect_mapping
Opens a writable connection to the target database — the harness Postgres, not the Supabase source — for record_mapping.
inspect
Inspects the project. Read-only throughout; see ReadOnlySession.
read_users
Reads the source’s auth users through one read-only snapshot and plans their import.
record_mapping
Creates import_supabase_users if needed and upserts rows in one transaction: a new Supabase id is inserted; one already mapped to the same account has its metadata refreshed (counted unchanged); a new id may share an account with an existing row (--merge-by-email maps several source users to one account). The only drift is an existing id that maps to a different account — MappingError::Drift.
source_name
Parses url as a postgres:// or postgresql:// connection string and returns its host, port and database, and nothing else.
validate_project_ref
A project ref is lower-case letters and digits: it goes into a URL path.