On this page
Package imports vendors another pgdesign project's table surface and type closure as pinned content-addressed forms, with an offline drift check.
#internal/imports
#internal/imports
Package imports implements cross-repository schema imports (roadmap 7.2): the surface snapshot, pinning, and offline drift check for another pgdesign project's schema referenced via an [imports.
The import surface is a sub-model under the kernel's encoder (internal/enc, law L1) and its content-addressed store (internal/objstore, law L2): the referenced tables plus the transitive composition-closure of their type definitions are vendored, each as its canonical per-object form, into a store rooted at imports/
- SurfaceHash — hash of the sorted per-object content ids. Integrity: it changes iff the vendored bytes change. Stable across re-lock of the same commit (identical bytes -> identical ids). - SemanticHash — hash of the sorted N-normalized per-object forms. Drift: it is INVARIANT under equivalently-spelled defaults (N folds them), so it does not false-drift where SurfaceHash (raw ids) would. Roadmap 1.2's N dependency made explicit.
This package is pure aside from git plumbing (git.go) and the filesystem: it depends on config, parse, model, enc, objstore, sqlparse, typeinfo. It never touches a database — offline builds and the drift check never need the remote.
#LockfileName
const LockfileName = "lock.json"LockfileName is the per-alias lockfile, co-located with the vendored objects under the alias's store root (imports/import update <alias> writes exactly one directory. Visible (non-dot) name per the roadmap's [%%] committed-load-bearing-data convention.
#ObjectEntry
type ObjectEntry structObjectEntry pins one vendored surface object: its kind-qualified manifest key (enc.Key.String()) and its content id in the alias store.
#Lockfile
type Lockfile structLockfile is the pinned, committed record of one import alias's vendored surface. It is written by import lock/import update and read by the offline check --tag imports.
#Check
func Check(projectDir, alias string, consumer *model.Schema) diagnostic.DiagnosticsCheck runs the OFFLINE import drift check for one alias (roadmap 7.2). It never touches the remote — it reads only the vendored surface and the lockfile. It reports, at Error severity:
- Integrity (E233/E234): every locked object id resolves in the alias store (present, correct epoch, hashes to its id), and the surface hash of the sorted resolved ids matches the lockfile. - Semantic consistency (E235): the N-normalized re-encoding of the vendored surface hashes to the lockfile's semantic hash. Because the semantic hash folds equivalently-spelled defaults, a re-spelled default does NOT trip this; a real column-type change DOES. - Reference drift (E236/E237): every FK in the consumer model that resolves through this alias names a table AND columns the vendored surface actually provides, and the FK's local column type matches the referenced surface column type (compared via typeinfo normalization). A drifted column type yields an exact column+FK error. Columns the consumer does not reference are never examined, so unreferenced framework changes are silent.
#ImportAliases
func ImportAliases(projectDir string, declared []string) []stringImportAliases returns the sorted list of alias names that have a committed lockfile under projectDir. It is the offline check's discovery source — the remote is never consulted.
#CheckGitAvailable
func CheckGitAvailable() errorCheckGitAvailable returns a hard error if the git binary is not on PATH. Import lock/update require git; the absence of git is a loud failure, not a fallback.
#ResolveRemoteRef
func ResolveRemoteRef(url, ref string) (string, error)ResolveRemoteRef probes the remote with git ls-remote to confirm reachability and that ref exists, returning the resolved commit sha when ls-remote reports one. A ref that ls-remote does not list (e.g. a bare commit sha, which ls-remote never returns) yields ("", nil) — reachability succeeded but the ref must be resolved by CloneAt. A non-zero git exit (unreachable/auth) is a hard error naming the remote.
#CloneAt
func CloneAt(url, ref, dest string) (string, error)CloneAt clones url into dest and checks out ref, returning the resolved commit sha (rev-parse HEAD). It handles tags, branches, and bare commit shas uniformly via a full clone + checkout. A clone failure (unreachable remote) or a checkout failure (bad ref) is a hard error with git's stderr attached.
#AliasDir
func AliasDir(projectDir, alias string) stringAliasDir returns the store root directory for an alias under projectDir.
#LockfilePath
func LockfilePath(projectDir, alias string) stringLockfilePath returns the lockfile path for an alias under projectDir.
#WriteLockfile
func WriteLockfile(projectDir string, lf *Lockfile) errorWriteLockfile writes lf to imports/
#ReadLockfile
func ReadLockfile(projectDir, alias string) (*Lockfile, error)ReadLockfile reads and parses imports/
#LockfileExists
func LockfileExists(projectDir, alias string) boolLockfileExists reports whether an alias has a committed lockfile.
#LoadSurface
func LoadSurface(projectDir, alias string) (*model.Schema, error)LoadSurface decodes the vendored surface for one alias (imports/
The returned schema is a bare sub-model: its Tables/Enums/... are populated and each object carries the target Schema it was vendored into, but no canonicalization or FK-graph derivation is performed (the consumer's Build folds these into its own model via WithImportedTables and the registry). A referenced object that fails to resolve or decode is a hard error — the vendored surface is part of the committed project state, so corruption must fail loudly rather than silently drop a reference (which would then trip a spurious E204).
#LoadAllSurfaces
func LoadAllSurfaces(projectDir string, aliases []string) (*model.Schema, error)LoadAllSurfaces decodes the vendored surfaces for every alias that has a committed lockfile under projectDir, aggregating their reference objects into one sub-model. aliases is the set of declared import aliases (typically the keys of the project's [imports] config); aliases without a lockfile are skipped (the project has not run import lock yet — the build proceeds without the union, and the unresolved FK surfaces as a normal E204/E236). The aggregated tables are suitable for model.WithImportedTables; enums/domains/composites/state machines are returned for registry loading so imported types are usable in local columns.
#CheckRequirements
func CheckRequirements(projectDir string, aliases []string, consumer *model.Schema) diagnostic.DiagnosticsCheckRequirements enforces the lockfile's carried REQUIREMENTS against the consumer's own declarations (roadmap 7.3): the consumer must re-declare every extension the imported surface requires, and its pg_version must be >= the imported floor. The lockfile carries these (7.2 InferRequirements); 7.3 turns them into hard errors surfaced by the check --tag imports framework (cmd checkImports calls this) — NOT by the build/parseAndBuild path. So a consumer that would fail at apply time (a missing extension type, or a version-gated feature the consumer's target cannot run) fails loudly at CHECK time, in CI, before ever reaching apply.
- Requirement violations use E241 (missing extension) and E242 (pg_version below floor), naming the requiring alias. (These are distinct from the live import-verification codes E238/E239/E240 raised by revise's DB tier and the drift codes E230-E237 from 7.1/7.2.)
consumer supplies the project's own declared Extensions and PGVersion. aliases is the set of declared import aliases; only those with a committed lockfile are consulted (the remote is never touched).
#ExtractSurface
func ExtractSurface(framework *model.Schema, refTables []string, targetSchema string) (*model.Schema, error)ExtractSurface computes the import surface a consumer needs from a framework model: the referenced tables plus the transitive composition-closure of their type definitions (enums, domains, composites, state machines). Every surface object is re-stamped into targetSchema so it matches how the consumer references it (fk.RefSchema == targetSchema). refTables is the set of table names the consumer references through this alias.
A referenced table absent from the framework model is a hard error (the alias promises a table the framework does not provide). The returned surface is a sub-model containing ONLY the surface objects; it is not canonicalized against a full schema (it has no meta), so callers encode it per-object.
#Vendor
func Vendor(surface *model.Schema, root string) (entries []ObjectEntry, surfaceHash, semanticHash string, err error)Vendor encodes the surface objects, stores them in the alias objstore rooted at root, and returns the per-object entries plus the surface and semantic hashes. Puts are idempotent (content-addressed), so re-vendoring the same surface is a no-op on disk.
#InferRequirements
func InferRequirements(framework *model.Schema) (extensions []string, pgVersion int)InferRequirements returns the extension requirements and pg_version floor to carry in the lockfile. Extensions are the framework's declared set (a safe superset; per-object refinement is deferred — 7.3 wires the re-declaration error). pg_version is the framework model's PGVersion.