Documentation
¶
Overview ¶
Package queryaccess owns the immutable MySQL/TiDB builtin semantic manifest. input: application-owned profile and parser-shape entries output: copy-safe semantic manifests and the session-only service capability pos: private semantic proof root, independent from PostgreSQL catalog trust
Package queryaccess defines application-level query access contracts. input: query access requests, results, resolvers, and online catalog hints output: domain-typed query access contracts and MySQL/TiDB catalog binding via connresolve pos: application contract layer above parsing and transport adapters note: if this file changes, update this header and module README.md.
Package queryaccess contains the narrow PostgreSQL COUNT(integer_one) proof predicate. input: exact parser envelope, resolved domain result, requirements, and internal candidate facts output: fail-closed proof-completeness decision for one physical table pos: PostgreSQL-only proof gate before catalog identity promotion note: if this file changes, update this header and module README.md.
Package queryaccess defines application-level contracts for query access analysis. input: SQL text, dialect, mode, and optional schema resolver output: domain-typed query access results for transport adapters pos: application contract layer for the query access analysis foundation note: if this file changes, update this header and module README.md.
Package queryaccess provides the PostgreSQL query access stub when built without the postgresql tag. input: none (stub only) output: ErrPostgreSQLNotAvailable for all calls pos: application stub for non-PostgreSQL builds note: if this file changes, update this header and module README.md.
Package queryaccess provides TiDB query access extraction bridging infrastructure facts to domain types. input: SQL text, dialect, mode, default schema, and optional schema resolver output: domain-typed query access results for transport adapters pos: application adapter bridging TiDB infrastructure query access facts to domain query access types note: if this file changes, update this header and module README.md.
Package queryaccess defines the effect-identity resolver contract (facts only). input: internal EffectCandidate batch keyed by stable ordinal output: per-ordinal IdentityStatus + optional catalog facts (never Trusted/admission) pos: facts-only identity helpers; only PostgreSQL adapter-called functions stay exported note: if this file changes, update this header and module README.md.
Package queryaccess defines the fail-closed Phase-1 pure-effect eligibility gate. input: internal effect candidates collected from PostgreSQL query extraction output: bounded eligibility decision and reason code pos: application proof boundary before catalog identity promotion note: if this file changes, update this header and module README.md.
Package queryaccess defines the closed internal query access profile contract. input: validated profile values and canonical dialect names output: bounded profile validation errors for application requests pos: shared profile authority used by public SDK and application service note: if this file changes, update this header and module README.md.
Package queryaccess owns the single proof-orchestration point between requirements and final state. input: service capability, request, and extracted result with requirements already attached output: promotion permission fact for the common promotion checks; proof-specific reason removal mutates the kept reason set pos: application proof sequencing before the final normalize/reclassify/admission computation note: if this file changes, update this header and module README.md.
Package queryaccess implements requirement generation for query access analysis. input: resolved query access facts (relations, columns, outputs, unresolved) and mode output: access requirements, warnings, and reason codes pos: application requirement layer bridging resolved facts to permission requirements note: if this file changes, update this header and module README.md.
Package queryaccess implements metadata-backed resolution for query access analysis. input: domain Result with extracted facts, SchemaResolver for metadata lookup output: enriched Result with resolved wildcards, columns, aliases, and lineage pos: application resolution layer bridging extracted facts to metadata-resolved results note: if this file changes, update this header and module README.md.
Package queryaccess provides the application service for query access analysis. input: SQL text, dialect, mode, profile, default schema, optional schema resolver, and shared input normalization output: domain-typed query access results with metadata resolution, normalized final state, or a bounded BOM-empty input error pos: application orchestration and cross-surface state-normalization layer for query access note: if this file changes, update this header and module README.md.
Package queryaccess defines the Phase-1 PG17 trusted effect manifest. input: T2 ledger plus PG17 pure aggregate/window expansion output: immutable TrustedEffectManifest for PG17 pos: T8 Phase-1 manifest; compile-time owned, versioned, deterministically hashed note: if this file changes, update this header and module README.md.
Package queryaccess implements the TrustPolicy for PostgreSQL effect identity proof. input: resolved EffectIdentityBatch + immutable PG17 manifest output: TrustDecision indicating whether all effects are manifest-proven pos: T8 trust policy layer; sole path to Trusted for PostgreSQL admission note: if this file changes, update this header and module README.md.
Index ¶
- Constants
- Variables
- func BuildRequirements(mode domain.Mode, relations []domain.RelationReference, ...) ([]domain.Requirement, []domain.WarningCode, []domain.ReasonCode, error)
- func CandidateExplicitlyQualified(c EffectCandidate) bool
- func ComputeManifestHash(entries []TrustedEffectEntry) string
- func FormatRelationSchemaKey(schema, name string) string
- func IsExactCountIntegerOneCandidate(candidate EffectCandidate) bool
- func MapCatalogErrorToStatus(err error) domain.IdentityStatus
- func MarshalManifestJSON(m TrustedEffectManifest) ([]byte, error)
- func NewResolutionState(ctx context.Context, resolver SchemaResolver, dialect, defaultSchema string, ...) *resolutionState
- func ResolutionContextSessionCompatible(a, b EffectIdentityResolutionContext) bool
- func ResolutionContextSessionComplete(rc EffectIdentityResolutionContext) bool
- func ResolutionContextUsableForUnqualified(rc EffectIdentityResolutionContext) bool
- func ResolveMetadata(ctx context.Context, resolver SchemaResolver, dialect, defaultSchema string, ...) domain.Result
- func ResolveMySQLTiDBOnlineSchema(dialect, database, connectionSchema, requestedSchema string) (string, string, error)
- func StampFactsFromResolution(facts *EffectIdentityFacts, rc EffectIdentityResolutionContext)
- func ValidTrustDecision(d TrustDecision) bool
- func ValidateAnalysisProfile(profile AnalysisProfile, dialect string) error
- func ValidateEffectIdentityRequest(req EffectIdentityRequest) error
- func ValidateManifest(m TrustedEffectManifest) error
- type AnalysisProfile
- type AtomicProofResolver
- type BuiltinSemanticCallClass
- type BuiltinSemanticEntry
- type BuiltinSemanticManifest
- type ColumnSchema
- type ColumnTypeOIDResolver
- type ControlledEffectIdentityResolver
- type EffectCandidate
- type EffectCandidateKind
- type EffectCastMethod
- type EffectIdentityBatch
- type EffectIdentityFacts
- type EffectIdentityItem
- type EffectIdentityRequest
- type EffectIdentityResolutionContext
- type EffectIdentityResolutionMode
- type EffectIdentityResolver
- type EffectVolatility
- type LiveResolutionContext
- type OperandColumnRef
- type QueryAccessRequest
- type QueryAccessResult
- type RelationSchema
- type SchemaResolver
- type Service
- type TrustDecision
- type TrustPolicy
- type TrustedEffectEntry
- type TrustedEffectManifest
Constants ¶
const ( ReasonMissingMetadata domain.ReasonCode = "missing_metadata" ReasonRelationNotFound domain.ReasonCode = "relation_not_found" ReasonColumnNotFound domain.ReasonCode = "column_not_found" ReasonAmbiguousColumn domain.ReasonCode = "ambiguous_column" ReasonRelationAmbiguous domain.ReasonCode = "relation_ambiguous" ReasonUnresolvedWildcard domain.ReasonCode = "unresolved_wildcard" ReasonUnresolvedAlias domain.ReasonCode = "unresolved_alias" )
UnresolvedReason constants for bounded unresolved tracking.
const PgCatalogNamespaceName = "pg_catalog"
PgCatalogNamespaceName is the PostgreSQL system catalog schema name. Used only for internal explicit-schema checks; not a trust claim.
Variables ¶
var ( // ErrDuplicateIdentityOrdinal indicates the request repeated a candidate ordinal. ErrDuplicateIdentityOrdinal = errors.New("duplicate effect identity candidate ordinal") // ErrIdentityRequestInvalid indicates the request failed structural validation. ErrIdentityRequestInvalid = errors.New("invalid effect identity request") // ErrIdentityBatchIncomplete indicates results omitted required ordinals. ErrIdentityBatchIncomplete = errors.New("effect identity batch incomplete") )
var ( ErrInvalidAnalysisProfile = errors.New("invalid query access analysis profile") ErrAnalysisProfileDialectMismatch = errors.New("query access analysis profile does not match dialect") )
var ( // ErrManifestInvalid indicates the manifest failed validation. ErrManifestInvalid = errors.New("invalid trust manifest") // ErrManifestHashMismatch indicates the manifest hash does not match contents. ErrManifestHashMismatch = errors.New("manifest hash mismatch") // ErrPolicyVersionMismatch indicates the server version is outside the manifest range. ErrPolicyVersionMismatch = errors.New("server version outside manifest range") )
var ErrBOMOnlySQL = errors.New("query access SQL must not be empty")
ErrBOMOnlySQL indicates SQL became empty after removing one leading UTF-8 BOM.
var ErrBuiltinSemanticManifestInvalid = errors.New("invalid builtin semantic manifest")
var ErrExtractionFailed = errors.New("query access extraction failed")
ErrExtractionFailed indicates query access extraction failed without exposing SQL text.
var ErrMySQLTiDBSchemaConflict = errors.New("MySQL/TiDB database, schema, and default schema must match when set; use one catalog value")
ErrMySQLTiDBSchemaConflict indicates that online MySQL/TiDB catalog hints disagree.
var ErrPostgreSQLNotAvailable = errors.New("postgresql support requires build tag: go build -tags postgresql")
ErrPostgreSQLNotAvailable indicates PostgreSQL support was not compiled in.
var ErrTrustedBundleInvalid = errors.New("invalid trusted bundle")
ErrTrustedBundleInvalid indicates the trusted bundle failed validation.
var PG17Manifest = NewPG17Manifest()
PG17Manifest is deprecated: use NewPG17Manifest() for immutable copies. Retained for backward compatibility with existing tests.
Functions ¶
func BuildRequirements ¶
func BuildRequirements( mode domain.Mode, relations []domain.RelationReference, columns []domain.ColumnReference, outputs []domain.OutputColumn, unresolved []domain.Unresolved, ) ([]domain.Requirement, []domain.WarningCode, []domain.ReasonCode, error)
BuildRequirements exposes requirement generation for testing.
func CandidateExplicitlyQualified ¶ added in v0.390.0
func CandidateExplicitlyQualified(c EffectCandidate) bool
CandidateExplicitlyQualified reports whether the candidate names an explicit schema (NamePath/TargetTypePath multi-segment or ExplicitSchema flag). Explicit qualification does not imply trust — only that search_path ranking is not required to pick the namespace segment.
func ComputeManifestHash ¶ added in v0.390.0
func ComputeManifestHash(entries []TrustedEffectEntry) string
ComputeManifestHash computes a deterministic SHA-256 hash of the manifest entries. Entries are sorted by (Kind, ObjectOID, NamespaceOID, CanonicalSignature) before hashing.
func FormatRelationSchemaKey ¶
FormatRelationSchemaKey returns a cache key for a relation schema lookup.
func IsExactCountIntegerOneCandidate ¶ added in v0.480.0
func IsExactCountIntegerOneCandidate(candidate EffectCandidate) bool
func MapCatalogErrorToStatus ¶ added in v0.390.0
func MapCatalogErrorToStatus(err error) domain.IdentityStatus
MapCatalogErrorToStatus maps a transport/catalog error to a bounded status. The error text is discarded: it must never become status, reason, or facts. context.Canceled / DeadlineExceeded are not mapped here — callers return them as batch-level errors.
func MarshalManifestJSON ¶ added in v0.390.0
func MarshalManifestJSON(m TrustedEffectManifest) ([]byte, error)
MarshalManifestJSON serializes the manifest to deterministic JSON.
func NewResolutionState ¶
func NewResolutionState(ctx context.Context, resolver SchemaResolver, dialect, defaultSchema string, relations []domain.RelationReference) *resolutionState
NewResolutionState creates a resolution state for testing.
func ResolutionContextSessionCompatible ¶ added in v0.390.0
func ResolutionContextSessionCompatible(a, b EffectIdentityResolutionContext) bool
ResolutionContextSessionCompatible reports whether two contexts share the same session/database/role/server/epoch binding. Zeros never match (incomplete). Search_path is intentionally not compared here — explicit schema may skip it.
func ResolutionContextSessionComplete ¶ added in v0.390.0
func ResolutionContextSessionComplete(rc EffectIdentityResolutionContext) bool
ResolutionContextSessionComplete reports whether the context is fully bound for Phase-1 promotion: Bound plus non-zero SessionBinding, PathEpoch, DatabaseOID, RoleOID, and ServerVersionNum. Missing any field is incomplete (not "optional"). Search_path may still be empty (explicit-schema-only batches).
func ResolutionContextUsableForUnqualified ¶ added in v0.390.0
func ResolutionContextUsableForUnqualified(rc EffectIdentityResolutionContext) bool
ResolutionContextUsableForUnqualified reports whether the context may resolve unqualified operators/functions: session-complete plus non-empty search path.
func ResolveMetadata ¶
func ResolveMetadata(ctx context.Context, resolver SchemaResolver, dialect, defaultSchema string, result domain.Result) domain.Result
ResolveMetadata exposes the metadata resolution for testing.
func ResolveMySQLTiDBOnlineSchema ¶ added in v0.500.0
func ResolveMySQLTiDBOnlineSchema(dialect, database, connectionSchema, requestedSchema string) (string, string, error)
ResolveMySQLTiDBOnlineSchema canonicalizes MySQL/TiDB database, connection schema, and request default hints into one catalog and one qualifier.
func StampFactsFromResolution ¶ added in v0.390.0
func StampFactsFromResolution(facts *EffectIdentityFacts, rc EffectIdentityResolutionContext)
StampFactsFromResolution copies database/server locality pins from the resolution context onto facts. Adapters should call this for every resolved item before gating. Does not set Trusted or admission.
func ValidTrustDecision ¶ added in v0.390.0
func ValidTrustDecision(d TrustDecision) bool
ValidTrustDecision reports whether d is a known trust decision.
func ValidateAnalysisProfile ¶ added in v0.410.0
func ValidateAnalysisProfile(profile AnalysisProfile, dialect string) error
ValidateAnalysisProfile checks the closed profile set and dialect ownership.
func ValidateEffectIdentityRequest ¶ added in v0.390.0
func ValidateEffectIdentityRequest(req EffectIdentityRequest) error
ValidateEffectIdentityRequest checks ordinal uniqueness and structural bounds. Empty candidate slices are valid (resolver returns an empty batch). Resolution may be zero (unbound); that is valid and forces all candidates to unavailable via gateIdentityBatchByResolutionContext (no promotion-ready facts). Bound=true requires a fully complete session context (binding, epoch, database, role, server version); partial Bound contexts are invalid, not "optional fields".
func ValidateManifest ¶ added in v0.390.0
func ValidateManifest(m TrustedEffectManifest) error
ValidateManifest checks the manifest for structural validity and hash integrity.
Types ¶
type AnalysisProfile ¶ added in v0.410.0
type AnalysisProfile string
AnalysisProfile identifies a closed engine/version compatibility target.
const ( AnalysisProfileEmpty AnalysisProfile = "" AnalysisProfileMySQL57 AnalysisProfile = "mysql-5.7" AnalysisProfileMySQL80 AnalysisProfile = "mysql-8.0" AnalysisProfileMySQL84 AnalysisProfile = "mysql-8.4" AnalysisProfileTiDB85 AnalysisProfile = "tidb-8.5" )
type AtomicProofResolver ¶ added in v0.390.0
type AtomicProofResolver interface {
ResolveColumnTypesAndEffectIdentities(
ctx context.Context,
candidates []EffectCandidate,
req EffectIdentityRequest,
) (map[int][]uint32, EffectIdentityBatch, EffectIdentityResolutionContext, error)
}
AtomicProofResolver combines column type OID resolution and effect identity resolution in a single atomic operation. This ensures both come from the same catalog snapshot (REPEATABLE READ), preventing TOCTOU issues with concurrent DDL.
Only implementations that guarantee pinned-session, execution-bound resolution satisfy this contract. The application uses a type assertion to prefer this over separate ResolveColumnTypeOIDs + ResolveEffectIdentities calls when available.
The returned EffectIdentityResolutionContext is captured INSIDE the atomic operation (same pinned session/transaction) and represents the final execution-bound state after all lookups. The application compares this with the initial captured context to detect TOCTOU drift.
INV-12 (Defense-in-Depth): These checks protect against malformed, cross-wired, buggy, or contract-violating trusted-adapter output. They do NOT protect against a compromised in-process dependency: a malicious resolver that controls CaptureExecutionBoundContext, atomic resolution, facts, and type output can fabricate a mutually consistent proof. NewTrustedService accepts an in-process dependency that is necessarily trusted by construction.
type BuiltinSemanticCallClass ¶ added in v0.410.0
type BuiltinSemanticCallClass string
const ( BuiltinSemanticAggregate BuiltinSemanticCallClass = "aggregate" BuiltinSemanticWindow BuiltinSemanticCallClass = "window" BuiltinSemanticScalar BuiltinSemanticCallClass = "scalar" )
type BuiltinSemanticEntry ¶ added in v0.410.0
type BuiltinSemanticEntry struct {
Dialect string
Profile AnalysisProfile
Name string
CallClass BuiltinSemanticCallClass
Arity int
OperandKinds []string
// MinArity and MaxArity support variable-arity functions (e.g. COALESCE).
// When MinArity > 0, the entry uses range-based arity matching:
// candidate.Arity >= MinArity && (MaxArity == 0 || candidate.Arity <= MaxArity).
// MaxArity == 0 means unlimited. Fixed-arity entries leave both at zero
// and use Arity for exact match.
MinArity int
MaxArity int
AllowFilter bool
AllowDistinct bool
AllowAggOrder bool
AllowWithinGroup bool
AllowFrame bool
AllowNamedWindow bool
AllowWindowPartition bool
AllowWindowOrder bool
// RequireWindowPartition and RequireWindowOrder enforce that the parser
// observed the corresponding clause with direct column operands. This is
// stricter than MySQL's syntax contract (which accepts ranking windows
// without ORDER BY): the design's "strict partition/order dependencies"
// boundary deliberately fails closed when either clause is absent.
RequireWindowPartition bool
RequireWindowOrder bool
}
BuiltinSemanticEntry describes one exact native call shape. It contains no server identity, trust bit, catalog identity, or caller-provided evidence.
type BuiltinSemanticManifest ¶ added in v0.410.0
type BuiltinSemanticManifest struct {
// contains filtered or unexported fields
}
BuiltinSemanticManifest is immutable after construction. Entries are returned only through deep-copy accessors.
func NewBuiltinSemanticManifest ¶ added in v0.410.0
func NewBuiltinSemanticManifest(entries []BuiltinSemanticEntry) (*BuiltinSemanticManifest, error)
NewBuiltinSemanticManifest validates and deep-copies application-owned data.
func (*BuiltinSemanticManifest) Entries ¶ added in v0.410.0
func (m *BuiltinSemanticManifest) Entries() []BuiltinSemanticEntry
Entries returns a deep copy of the manifest entries.
type ColumnSchema ¶
type ColumnSchema struct {
Name string
Ordinal int
// TypeOID is the catalog type OID when known (PostgreSQL atttypid).
// Zero means unknown / not provided. Facts only — never a trust signal.
// MySQL/TiDB resolvers may leave this zero. T6 does not implement catalog
// population; T7 may fill it when needed for identity resolution.
TypeOID uint32
}
ColumnSchema contains metadata about a column.
type ColumnTypeOIDResolver ¶ added in v0.390.0
type ColumnTypeOIDResolver interface {
ResolveColumnTypeOIDs(ctx context.Context, candidates []EffectCandidate) (map[int][]uint32, error)
}
ColumnTypeOIDResolver resolves column type OIDs for operand provenance on a pinned session. This is a narrow capability interface satisfied by the T7 EffectIdentityAdapter. The application uses a type assertion to access this when the controlled resolver also supports column type lookup.
Only binary operators with two fully-qualified column operands from base tables are resolved. Missing or unresolvable columns are skipped (fail-closed for the affected candidate; other candidates may still succeed).
type ControlledEffectIdentityResolver ¶ added in v0.390.0
type ControlledEffectIdentityResolver interface {
EffectIdentityResolver
// CaptureExecutionBoundContext returns the current session's resolution
// context. Must return a session-complete context (all fields non-zero)
// or an error. The application uses this to set explicit Resolution on
// EffectIdentityRequest, proving the facts are bound to the expected
// execution session.
CaptureExecutionBoundContext(ctx context.Context) (EffectIdentityResolutionContext, error)
}
ControlledEffectIdentityResolver is the narrow contract for promotion-ready identity resolution. Only implementations that guarantee pinned-session, execution-bound resolution and TOCTOU gating satisfy this contract.
Generic EffectIdentityResolver implementations MUST NOT satisfy this interface. The application uses CaptureExecutionBoundContext to set explicit Resolution on the request, proving session binding before the resolver runs.
type EffectCandidate ¶ added in v0.390.0
type EffectCandidate struct {
Kind EffectCandidateKind
Ordinal int
NamePath []string
OriginalNamePath []string
ExplicitSchema bool
IsQuoted bool
Canonical bool
Ambiguous bool
ParserClassification string
UnqualifiedRelation bool
Arity int
OperandKinds []string
IsAggregate bool
HasWindow bool
HasFilter bool
HasDistinct bool `json:"-"`
HasAggOrder bool `json:"-"`
HasWithinGroup bool `json:"-"`
HasFrame bool `json:"-"`
HasNamedWindow bool `json:"-"`
HasWindowPartition bool `json:"-"`
HasWindowOrder bool `json:"-"`
WindowPartitionKinds []string `json:"-"`
WindowOrderKinds []string `json:"-"`
WindowFrameKinds []string `json:"-"`
WindowPartitionColumnRefs []OperandColumnRef `json:"-"`
WindowOrderColumnRefs []OperandColumnRef `json:"-"`
TargetTypePath []string
// OperandColumnRefs maps operand position to base-table column reference.
// Indexed by operand position; nil entries indicate non-column operands.
// Only populated for column operands against base tables.
OperandColumnRefs []OperandColumnRef
}
EffectCandidate is an internal, untrusted effect fact for future catalog identity resolution. It is NOT a trust root and is never serialized on domain.Result or SDK/CLI/HTTP JSON.
type EffectCandidateKind ¶ added in v0.390.0
type EffectCandidateKind string
EffectCandidateKind mirrors parser-internal candidate kinds (application copy).
const ( EffectCandidateOperator EffectCandidateKind = "operator" EffectCandidateFunction EffectCandidateKind = "function" EffectCandidateCast EffectCandidateKind = "cast" EffectCandidateUnknown EffectCandidateKind = "unknown" )
type EffectCastMethod ¶ added in v0.390.0
type EffectCastMethod string
EffectCastMethod is a bounded PostgreSQL castmethod fact (f/b/i). Values are catalog facts only — never a trust claim.
const ( // EffectCastMethodFunction is castmethod 'f'. EffectCastMethodFunction EffectCastMethod = "f" // EffectCastMethodBinary is castmethod 'b'. EffectCastMethodBinary EffectCastMethod = "b" // EffectCastMethodInOut is castmethod 'i'. EffectCastMethodInOut EffectCastMethod = "i" )
type EffectIdentityBatch ¶ added in v0.390.0
type EffectIdentityBatch struct {
Items []EffectIdentityItem
}
EffectIdentityBatch is the ordered set of per-candidate outcomes.
func BuildUnavailableBatch ¶ added in v0.390.0
func BuildUnavailableBatch(candidates []EffectCandidate) EffectIdentityBatch
BuildUnavailableBatch returns one unavailable item per candidate ordinal. Used when no EffectIdentityResolver is configured (fail-closed, facts-only). Result is sorted by ordinal. Does not inspect or leak candidate names.
func GateIdentityBatchAgainstLiveContext ¶ added in v0.390.0
func GateIdentityBatchAgainstLiveContext(req EffectIdentityRequest, batch EffectIdentityBatch, live LiveResolutionContext) EffectIdentityBatch
GateIdentityBatchAgainstLiveContext applies policy gating and TOCTOU protection.
When live is non-nil:
- live error or incomplete live snapshot → all candidates unavailable
- session/database/role/server/epoch mismatch → all candidates unavailable (explicit schema does NOT skip these checks)
- search_path order mismatch only → unqualified unavailable; explicit schema may keep facts if session-compatible and facts still match request pins
When live is nil, only gateIdentityBatchByResolutionContext runs (T7 must not skip live re-check for promotion-ready paths).
func NormalizeEffectIdentityBatch ¶ added in v0.390.0
func NormalizeEffectIdentityBatch(items []EffectIdentityItem) EffectIdentityBatch
NormalizeEffectIdentityBatch sorts by ascending ordinal, drops facts on non-resolved statuses, and rewrites free-text/invalid statuses to lookup_failed (fail-closed). Duplicate ordinals keep the first item and discard later ones after a stable sort (callers should validate requests first).
Partial failure: missing ordinals are not invented here; use completeEffectIdentityBatch against the request to fill gaps.
type EffectIdentityFacts ¶ added in v0.390.0
type EffectIdentityFacts struct {
Kind EffectCandidateKind
AggregateClass string
// ObjectOID is the primary catalog OID (pg_operator.oid / pg_proc.oid / cast identity).
ObjectOID uint32
// NamespaceOID is the schema namespace OID (e.g. pg_namespace.oid for pg_catalog).
NamespaceOID uint32
// OperandTypeOIDs are left/right or argument type OIDs in catalog order.
OperandTypeOIDs []uint32
// ResultTypeOID is the result type OID when known (0 if not applicable/unknown).
ResultTypeOID uint32
// ImplementationOID is operator oprcode (function implementing the operator), when applicable.
ImplementationOID uint32
// Volatility is a bounded function/operator volatility fact when known.
Volatility EffectVolatility
// CastMethod is set for cast identities (f/b/i).
CastMethod EffectCastMethod
// CastFunctionOID is the cast function OID when CastMethod is function; 0 otherwise.
CastFunctionOID uint32
// CanonicalSignature is an internal, deterministic identity key for manifest
// membership checks. Not a public field; not a trust claim by itself.
CanonicalSignature string
// ResolvedSchemaName is the resolved schema name (e.g., "pg_catalog").
// Empty for unqualified resolution.
ResolvedSchemaName string
// ResolvedObjectName is the resolved object name (e.g., "=", "count").
ResolvedObjectName string
// DatabaseOID pins ObjectOID locality (must match the resolution context).
// Zero is incomplete; gates discard such resolved facts.
DatabaseOID uint32
// ServerVersionNum pins the server major/minor used for catalog lookup.
// Zero is incomplete; gates discard such resolved facts.
ServerVersionNum int
}
EffectIdentityFacts are catalog facts for one uniquely resolved effect. There is intentionally no Trusted, Admission, or free-text reason field.
CanonicalSignature is an internal manifest-matching key for T8; it must never be copied into domain.Result, SDK/CLI/HTTP JSON, or reason codes.
type EffectIdentityItem ¶ added in v0.390.0
type EffectIdentityItem struct {
Ordinal int
Status domain.IdentityStatus
Facts *EffectIdentityFacts
}
EffectIdentityItem is the resolution outcome for one candidate ordinal. Status is always a bounded IdentityStatus; free-text must not be stored here. Facts is non-nil only when Status == resolved (and even then is not trusted).
type EffectIdentityRequest ¶ added in v0.390.0
type EffectIdentityRequest struct {
// Dialect is the analysis dialect (identity resolution is PostgreSQL-only in phase 1).
Dialect string
// Candidates are internal untrusted effect facts (kind, name path, arity, flags).
// They are resolver INPUTS, not trust roots.
Candidates []EffectCandidate
// OperandTypeOIDs optionally supplies pre-resolved operand/argument type OIDs
// keyed by candidate ordinal. Missing keys mean types are unknown (may yield
// unknown or coercion_gap). Values must not include literal SQL text.
OperandTypeOIDs map[int][]uint32
// Resolution is the execution-bound resolution environment (internal only).
// Zero value means unbound: unqualified candidates must stay unavailable.
Resolution EffectIdentityResolutionContext
}
EffectIdentityRequest is a batch of internal untrusted candidates for fact resolution. Inputs are associated by candidate Ordinal from T5 extraction.
Callers cannot inject domain.Result fields, Trusted bits, or public reason text through this request: only internal candidate facts, optional type OID hints, and an optional execution-bound resolution context (internal only).
type EffectIdentityResolutionContext ¶ added in v0.390.0
type EffectIdentityResolutionContext struct {
// Bound is true only when this context is proven to match the intended
// execution environment. Never set Bound from untrusted public JSON.
// Bound=true requires SessionComplete fields (see ValidateEffectIdentityRequest).
Bound bool
// SessionBinding is an opaque internal id for the controlled session or
// frozen catalog snapshot. Required non-empty when Bound. Never a DSN or password.
SessionBinding string
// PathEpoch is a stable non-zero compatibility marker for the captured
// session snapshot. Required when Bound. Session/database/role/version
// are compared field-wise; search_path is compared separately via
// NamespaceSearchOIDs. Not a mutation counter.
PathEpoch uint64
// NamespaceSearchOIDs is the ordered schema OID list used for unqualified
// resolution (PostgreSQL search_path after expansion). Required non-empty for
// unqualified resolution; may be empty only when every candidate is explicit
// schema (session fields still required).
NamespaceSearchOIDs []uint32
// DatabaseOID is the current database OID. Required non-zero when Bound.
// Object OIDs are local to this database.
DatabaseOID uint32
// RoleOID is the session role OID used for name resolution. Required non-zero when Bound.
RoleOID uint32
// ServerVersionNum is PostgreSQL server_version_num. Required non-zero when Bound.
// Version-scoped manifests (T8) must not accept facts from a different major.
ServerVersionNum int
}
EffectIdentityResolutionContext is an internal, execution-bound name-resolution environment for effect identity lookup.
It must never appear on domain.Result, SDK/CLI/HTTP JSON, reason codes, or public error text (no DSN, password, search_path string dump, or SQL).
Phase-1 policy (normative, T2-aligned):
- A promotion-ready bound context (ResolutionContextSessionComplete) requires ALL of: Bound, non-empty SessionBinding, PathEpoch != 0, DatabaseOID != 0, RoleOID != 0, ServerVersionNum != 0. Zero fields are incomplete — never optional for Phase-1 promotion.
- Unqualified operators/functions also require non-empty NamespaceSearchOIDs (ResolutionContextUsableForUnqualified). Without that proof they MUST be IdentityStatusUnavailable. Adapters must not invent pg_catalog.* names.
- Explicitly schema-qualified candidates skip search_path ranking for the namespace segment, but still require ResolutionContextSessionComplete. They share the same database/server catalog as the session; OIDs are database-local. Multi-match remains ambiguous.
- Bound=true attests the caller controls the session used for both analysis resolution and execution. PathEpoch is a stable non-zero compatibility marker; session/database/role/version are compared field-wise, and search_path is compared separately via NamespaceSearchOIDs.
- TOCTOU: re-read live context on the same session after lookup; any session field mismatch fails closed for every candidate (including explicit schema). Search_path order mismatch alone fails closed for unqualified only.
type EffectIdentityResolutionMode ¶ added in v0.390.0
type EffectIdentityResolutionMode string
EffectIdentityResolutionMode classifies how a candidate may use the context. Bounded machine identifiers only — not public Result fields.
const ( // ResolutionModeExplicitSchema: NamePath/TargetTypePath is schema-qualified. ResolutionModeExplicitSchema EffectIdentityResolutionMode = "explicit_schema" // ResolutionModeUnqualifiedBound: unqualified with usable execution context. ResolutionModeUnqualifiedBound EffectIdentityResolutionMode = "unqualified_bound" // ResolutionModeUnqualifiedUnbound: unqualified without proven execution context. // Must fail closed as unavailable (no pg_catalog name guess). ResolutionModeUnqualifiedUnbound EffectIdentityResolutionMode = "unqualified_unbound" )
type EffectIdentityResolver ¶ added in v0.390.0
type EffectIdentityResolver interface {
ResolveEffectIdentities(ctx context.Context, req EffectIdentityRequest) (EffectIdentityBatch, error)
}
EffectIdentityResolver resolves catalog identity facts for effect candidates.
Contract (normative for T6+ adapters):
- Returns catalog FACTS only. Must never return Trusted, admission, reason free-text, connection strings, catalog SQL, or driver error text as status.
- Trust is decided only by later application/domain manifest policy (T8).
- Batch-primary: ResolveEffectIdentities accepts all candidates at once. Per-candidate implementations may wrap single lookups but must still emit one result item per input ordinal (partial failure uses status, not omission).
- Ordinals in the request must be unique (stable 0-based traversal order from T5).
- Result ordering is ascending by Ordinal after NormalizeEffectIdentityBatch.
- Context cancellation: check ctx; if cancelled before/during work, return an error wrapping context.Canceled (batch-level). Do not encode cancel as a per-item status. Callers fail the analysis request as today.
- Catalog/transport errors for individual candidates map to IdentityStatusLookupFailed (or whole-batch error if the adapter cannot start).
- unknown / ambiguous / coercion_gap / lookup_failed / unavailable are all fail-closed for pure-read promotion.
- Execution resolution context (EffectIdentityRequest.Resolution) is required for any Phase-1 promotion-ready identity. Adapters MUST NOT guess pg_catalog.<name> from spelling alone (T2 forbids name/schema allowlists). Call GateIdentityBatchAgainstLiveContext (or Gate + live check) after lookup so incomplete/mismatched contexts discard facts.
- Phase-1 bound context REQUIRES non-zero SessionBinding, PathEpoch, DatabaseOID, RoleOID, and ServerVersionNum. OIDs are database-local; cross-database or cross-major resolved facts must never feed T8 promotion.
- Explicit schema skips search_path ranking only — it still requires the same session/database/role/server binding as unqualified resolution.
- TOCTOU: T7 must read live context, run identity lookup, and re-check live context on the SAME controlled session before handing facts to T8. Session/db/role/version/epoch mismatch fails closed for ALL candidates; search_path-only mismatch fails closed for unqualified only.
This interface is intentionally NOT attached to public SDK/CLI/HTTP request schemas in T6. Wiring into Service.Analyze and public injection points is a later task once a catalog adapter exists.
type EffectVolatility ¶ added in v0.390.0
type EffectVolatility string
EffectVolatility is a bounded PostgreSQL provolatile / operator volatility fact. Values are catalog facts only — never a trust claim.
const ( // EffectVolatilityImmutable is provolatile 'i'. EffectVolatilityImmutable EffectVolatility = "i" // EffectVolatilityStable is provolatile 's'. EffectVolatilityStable EffectVolatility = "s" // EffectVolatilityVolatile is provolatile 'v'. EffectVolatilityVolatile EffectVolatility = "v" )
type LiveResolutionContext ¶ added in v0.390.0
type LiveResolutionContext func() (EffectIdentityResolutionContext, error)
LiveResolutionContext is an adapter callback that re-reads the session's current resolution snapshot on the same controlled connection used for lookup. T7 must supply this (or equivalent) before T8 promotion.
type OperandColumnRef ¶ added in v0.390.0
OperandColumnRef identifies a base-table column for operand type resolution. Schema may be empty for unqualified references (resolved via search_path).
type QueryAccessRequest ¶
type QueryAccessRequest struct {
SQL string
Dialect string
Mode string
DefaultSchema string
AnalysisProfile AnalysisProfile
SchemaResolver SchemaResolver // optional
}
QueryAccessRequest is the input for query access analysis. Callers cannot inject effect candidates or trust bits: there is no candidate or Trusted field on the request.
EffectIdentityResolver remains intentionally absent. Profile selection is compatibility metadata only and does not inject candidates or trust facts.
type QueryAccessResult ¶
type QueryAccessResult struct {
DomainResult domain.Result
EffectCandidates []EffectCandidate `json:"-"` // internal only; never public transport fields
ExactCountIntegerOneStatement bool `json:"-"`
}
QueryAccessResult wraps the domain result for application-layer consumption. EffectCandidates are internal-only (untrusted, non-public).
func AnalyzePostgreSQL ¶
func AnalyzePostgreSQL(_ context.Context, _ QueryAccessRequest) (QueryAccessResult, error)
AnalyzePostgreSQL returns ErrPostgreSQLNotAvailable when built without the postgresql tag.
func ExtractTiDBQueryAccess ¶
func ExtractTiDBQueryAccess(ctx context.Context, req QueryAccessRequest) (QueryAccessResult, error)
ExtractTiDBQueryAccess extracts query access facts from TiDB SQL and converts to domain types.
type RelationSchema ¶
type RelationSchema struct {
Schema string
Name string
Kind string // "table" or "view"
Columns []ColumnSchema
IsView bool
}
RelationSchema contains metadata about a relation for resolution.
type SchemaResolver ¶
type SchemaResolver interface {
ResolveRelation(ctx context.Context, dialect string, schema, name string) (RelationSchema, error)
}
SchemaResolver resolves relation metadata for name resolution.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service orchestrates query access analysis.
func NewMySQLTiDBSemanticService ¶ added in v0.410.0
func NewMySQLTiDBSemanticService(schemaResolver SchemaResolver) (*Service, error)
NewMySQLTiDBSemanticService is the only production constructor for the private semantic capability. It accepts only the session-owned resolver; manifests remain application-owned. The production registry is populated for mysql-5.7, mysql-8.0, mysql-8.4, and tidb-8.5 and is session-only.
func NewService ¶ added in v0.390.0
func NewService() *Service
NewService creates a basic Service without manifest proof (fail-closed for PG effects).
func NewTrustedService ¶ added in v0.390.0
func NewTrustedService(effectResolver ControlledEffectIdentityResolver, trustPolicy *TrustPolicy, schemaResolver SchemaResolver) (*Service, error)
NewTrustedService creates a Service with PostgreSQL manifest proof capability. effectResolver must be a ControlledEffectIdentityResolver that can capture execution-bound context (pinned session with TOCTOU protection). All dependencies must be non-nil. The trust policy's manifest is validated on construction.
func (*Service) Analyze ¶
func (s *Service) Analyze(ctx context.Context, req QueryAccessRequest) (QueryAccessResult, error)
Analyze performs query access analysis with optional metadata resolution. When SchemaResolver is nil, wildcards and unqualified columns remain unresolved. For PostgreSQL with a trusted bundle, effect identities are resolved and manifest-proven effects may promote classification from indeterminate to read_only.
type TrustDecision ¶ added in v0.390.0
type TrustDecision string
TrustDecision is the outcome of manifest proof. Values are bounded machine identifiers — never public JSON.
const ( // TrustDecisionAllProven means every effect candidate is resolved and manifest-proven. TrustDecisionAllProven TrustDecision = "all_proven" // TrustDecisionHasUnproven means some candidates are resolved but not in manifest. TrustDecisionHasUnproven TrustDecision = "has_unproven" // TrustDecisionHasUnknown means some candidates are not resolved. TrustDecisionHasUnknown TrustDecision = "has_unknown" // TrustDecisionEmpty means no candidates to prove (vacuous truth). TrustDecisionEmpty TrustDecision = "empty" )
type TrustPolicy ¶ added in v0.390.0
type TrustPolicy struct {
// contains filtered or unexported fields
}
TrustPolicy evaluates whether resolved facts are manifest-proven. It is the sole path to Trusted for PostgreSQL admission.
func NewTrustPolicy ¶ added in v0.390.0
func NewTrustPolicy(manifest TrustedEffectManifest) (*TrustPolicy, error)
NewTrustPolicy creates a new TrustPolicy with the given manifest. The manifest is validated on construction. Entries are deeply copied to prevent post-construction mutation.
func (*TrustPolicy) IsTrusted ¶ added in v0.390.0
func (p *TrustPolicy) IsTrusted(batch EffectIdentityBatch, serverVersionNum int) TrustDecision
IsTrusted evaluates whether the resolved batch is fully manifest-proven.
Requirements for TrustDecisionAllProven:
- Every item in the batch must be resolved with facts
- Every fact's CanonicalSignature must exist in the manifest
- Every fact's ObjectOID, NamespaceOID must match the manifest entry
- Server version must be within the manifest's version range
- Facts must be stamped with matching DatabaseOID/ServerVersionNum
Returns:
- TrustDecisionAllProven if all above conditions met
- TrustDecisionHasUnproven if some resolved but not in manifest
- TrustDecisionHasUnknown if some not resolved
- TrustDecisionEmpty if batch has no items
func (*TrustPolicy) Manifest ¶ added in v0.390.0
func (p *TrustPolicy) Manifest() TrustedEffectManifest
Manifest returns a deep copy of the policy's manifest (read-only safe).
type TrustedEffectEntry ¶ added in v0.390.0
type TrustedEffectEntry struct {
// Kind is the effect candidate kind (operator, function, cast).
Kind EffectCandidateKind
// AggregateClass is the catalog prokind fact for aggregate entries.
AggregateClass string
// ObjectOID is the primary catalog OID (pg_operator.oid / pg_proc.oid).
ObjectOID uint32
// NamespaceOID is the schema namespace OID (pg_catalog = 11).
NamespaceOID uint32
// OperandTypeOIDs are left/right or argument type OIDs in catalog order.
OperandTypeOIDs []uint32
// ResultTypeOID is the result type OID when known.
ResultTypeOID uint32
// ImplementationOID is operator oprcode (function implementing the operator).
ImplementationOID uint32
// Volatility is the catalog provolatile fact (i/s/v).
Volatility EffectVolatility
// CanonicalSignature is the internal manifest-matching key.
CanonicalSignature string
// AuditNotes records the semantic audit rationale.
AuditNotes string
}
TrustedEffectEntry is one entry in the versioned manifest. Each entry represents an audited effect identity that is permitted to promote PostgreSQL queries from indeterminate to read_only + admissible.
type TrustedEffectManifest ¶ added in v0.390.0
type TrustedEffectManifest struct {
// SchemaVersion is the manifest schema version.
SchemaVersion string
// PostgreSQLMajorMin is the minimum supported PostgreSQL major version.
PostgreSQLMajorMin int
// PostgreSQLMajorMax is the maximum supported PostgreSQL major version.
PostgreSQLMajorMax int
// Entries is the sorted list of trusted effect entries.
Entries []TrustedEffectEntry
// Hash is the SHA-256 hash of the entries (computed by ComputeManifestHash).
Hash string
}
TrustedEffectManifest is the immutable, versioned manifest of trusted effects. It is compile-time owned, versioned, schema-validated, and deterministically hashed. No filesystem, remote, request, or caller-supplied manifest is accepted.
func NewPG17Manifest ¶ added in v0.390.0
func NewPG17Manifest() TrustedEffectManifest
NewPG17Manifest returns a deep copy of the PG17 manifest (immutable safe). Entries and nested OperandTypeOIDs slices are copied so callers cannot mutate the compile-time manifest backing store.
func UnmarshalManifestJSON ¶ added in v0.390.0
func UnmarshalManifestJSON(data []byte) (TrustedEffectManifest, error)
UnmarshalManifestJSON deserializes and validates the manifest from JSON.