queryaccess

package
v0.511.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 7, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

README

Application Query Access Module

Application-level contracts for query access analysis, defining the schema resolver interface, request/result types, dialect-specific extraction adapters, and metadata-backed resolution.

Files

File Responsibility
doc.go Declares the queryaccess application package boundary
contracts.go Defines SchemaResolver interface, RelationSchema, ColumnSchema, QueryAccessRequest, QueryAccessResult, and delegates MySQL/TiDB online catalog binding to connresolve
profile.go Defines the closed analysis-profile values and dialect validation
builtin_semantic_manifest.go Owns immutable MySQL/TiDB builtin semantic entries and session-only capability assembly
builtin_semantic_gateway.go Proves exact candidate closure and strict physical requirement completeness
identity_resolver.go EffectIdentityResolver facts-only contract, resolution context, adapter-facing identity batch helpers, bounded volatility/cast enums
phase1_effect_eligibility.go Fail-closed Phase-1 pure-effect candidate eligibility before identity promotion
count_integer_one_proof.go Narrow PostgreSQL COUNT(integer_one) single-table requirements proof predicate
count_integer_one_proof_test.go Verifies exact COUNT(integer_one) proof boundaries and fail-closed requirements
corpus_test.go / corpus_pg_test.go / corpus_session_test.go Own the offline Query Access corpus contract and fixture/session coverage; transport suites do not replace this semantic evidence
identity_resolver_test.go Contract tests: ordinal uniqueness, status enum, fail-closed mapping, cancellation, no Trusted field
identity_resolver_context_test.go Execution-context policy: unqualified unbound, shadowing, overload, TOCTOU, no public leak
identity_resolver_no_invoke_test.go Freezes Analyze: no identity resolver invocation or public leak in T6
trusted_service_postgresql_tag_test.go Verifies trusted PostgreSQL Service.Analyze promotion and the foreign-table negative path, which must remain indeterminate
extract_tidb.go Bridges TiDB infrastructure query access facts to domain types with admission computation
extract_tidb_test.go Verifies TiDB extraction bridging: classification, admission, CTE permissions, mode normalization, and column usages
extract_postgresql.go Bridges PostgreSQL infrastructure query access facts to domain types with admission computation
extract_postgresql_stub.go Returns ErrPostgreSQLNotAvailable when built without the postgresql tag
service.go Normalizes one leading UTF-8 BOM, then orchestrates query access analysis: extraction by dialect, optional metadata resolution, Promotion Barriers, requirement generation, one proof-orchestration point, final classification/admission computation, sorting, and validation
proof_orchestration.go Single private proof-orchestration point: routes ordinary PostgreSQL, exact COUNT(1), MySQL/TiDB builtin, and no-effect applicability; owns proof-specific reason removal
proof_orchestration_contract_test.go Locks the application proof-orchestration contract at the Service.Analyze seam for MySQL/TiDB builtin, no-effect, and barrier applicability
proof_orchestration_contract_postgresql_tag_test.go Locks the PostgreSQL ordinary/exact COUNT(1) proof-orchestration contract, probe counts, and cancellation at the Service.Analyze seam
resolve.go Implements metadata-backed resolution: request-scoped caching, wildcard expansion, alias resolution, column disambiguation, view detection, and output lineage enrichment
resolve_test.go Verifies resolution logic with a fake resolver: schema defaulting, cache deduplication, qualified/unqualified columns, missing metadata, cancellation, star expansion, views, CTEs, derived tables, aliases, output lineage
requirements.go Generates access requirements based on mode: strict requires all columns, projection-only requires only output-contributing columns with inference risk warning
requirements_test.go Verifies requirement generation: salary threshold, blacklist JOIN, GROUP/HAVING, ORDER BY, hashed output, subquery correlation, mode equality, stable warnings, invalid mode, unresolved references
service_test.go Verifies service integration: offline mode, metadata mode, mode normalization, classification preservation, wildcard expansion
final_state_invariant_postgresql_tag_test.go Verifies final classification/admission invariants and fallback reason normalization across MySQL, TiDB, and PostgreSQL offline and metadata-resolved paths
unproven_effect_reasons_postgresql_tag_test.go Verifies bounded unproven-effect reason codes for PostgreSQL operator/function/cast presence, identity-failure mapping no-leak, mode freeze, and sort determinism
unproven_effect_mysql_tidb_regression_test.go Guards MySQL/TiDB operator-bearing admissible cases against unproven_* reason regression

Exports

  • SchemaResolver
  • ResolveMySQLTiDBOnlineSchema() / ErrMySQLTiDBSchemaConflict
  • ErrBOMOnlySQL
  • RelationSchema
  • ColumnSchema (optional TypeOID fact; zero when unknown)
  • QueryAccessRequest
  • AnalysisProfile
  • ValidateAnalysisProfile()
  • BuiltinSemanticManifest / BuiltinSemanticEntry
  • BuiltinSemanticCallClass / BuiltinSemanticAggregate / BuiltinSemanticWindow / BuiltinSemanticScalar
  • ErrBuiltinSemanticManifestInvalid
  • NewBuiltinSemanticManifest() / NewMySQLTiDBSemanticService()
  • QueryAccessResult
  • EffectCandidate (application-internal copy; untrusted; never public JSON)
  • EffectCandidateKind
  • EffectIdentityResolver (facts only; not wired into Analyze in T6)
  • ControlledEffectIdentityResolver (T8: narrow contract for promotion; requires CaptureExecutionBoundContext)
  • EffectIdentityRequest / EffectIdentityBatch / EffectIdentityItem / EffectIdentityFacts
  • EffectIdentityResolutionContext / EffectIdentityResolutionMode
  • EffectVolatility / EffectCastMethod
  • ValidateEffectIdentityRequest() / NormalizeEffectIdentityBatch()
  • IsExactCountIntegerOneCandidate()
  • CandidateExplicitlyQualified()
  • ResolutionContextSessionComplete() / ResolutionContextUsableForUnqualified()
  • ResolutionContextSessionCompatible()
  • StampFactsFromResolution()
  • GateIdentityBatchAgainstLiveContext()
  • BuildUnavailableBatch() / MapCatalogErrorToStatus()
  • Service
  • NewService() / NewTrustedService() (T8)
  • TrustPolicy / TrustDecision / TrustedEffectManifest / TrustedEffectEntry (T8)
  • PG17Manifest (T8)
  • ComputeManifestHash() / ValidateManifest() / MarshalManifestJSON() / UnmarshalManifestJSON() (T8)
  • ExtractTiDBQueryAccess()
  • AnalyzePostgreSQL()
  • ResolveMetadata() (testing)
  • BuildRequirements() (testing)

Notes

  • The Query Access corpus owns offline semantic fixtures; the unified SDK owns online semantic breadth, with complete replacement evidence recorded in the milestone ledger.
  • ResolveMySQLTiDBOnlineSchema canonicalizes MySQL/TiDB database/schema aliases and request defaults, accepts equal values, rejects conflicts, and leaves PostgreSQL behavior outside the alias branch.
  • Identity-resolver helpers without a PostgreSQL adapter caller stay unexported. Adapter-called functions remain the export surface. There is no proof-engine seam.
  • QueryAccessResult wraps the domain Result for application-layer consumption.
  • The shared application input boundary removes exactly one leading UTF-8 BOM before Query Access parsing; BOM-only and BOM-plus-whitespace input is rejected as empty, while BOM-free empty-input result semantics remain unchanged.
  • QueryAccessRequest.Mode is a string that the domain layer normalizes via NormalizeMode.
  • ExtractTiDBQueryAccess computes admission from read classification: read_only → admissible, not_read_only → rejected, indeterminate → indeterminate.
  • AnalyzePostgreSQL follows the same admission computation pattern as TiDB.
  • CTE relations are marked with PermissionRequired: false; base tables and derived tables require permission.
  • Service.Analyze routes by dialect, applies optional metadata resolution, applies Promotion Barriers, generates requirements before every Effect Proof, calls the single proof-orchestration point (orchestratePromotionProof, see proof_orchestration.go) for ordinary PostgreSQL, exact COUNT(1), MySQL/TiDB builtin, and no-effect applicability, then normalizes the final classification, admission, and reason-code contract once, sorts output, and validates the result.
  • PostgreSQL unproven-effect reason codes (unproven_operator_effect, unproven_function_effect, unproven_cast_effect) are presence-only machine identifiers emitted by the parser adapter; they explain indeterminate classification without embedding SQL, OIDs, or effect spellings.
  • PostgreSQL EffectCandidates on QueryAccessResult are internal-only and untrusted (future catalog identity resolver input). They are not placed on domain.Result and must not appear in SDK/CLI/HTTP JSON. QueryAccessRequest has no candidate/trust injection fields.
  • T6 EffectIdentityResolver is an internal facts-only batch contract: per-ordinal IdentityStatus + optional OIDs/volatility/cast method/canonical signature. No Trusted, admission, reason text, or free-text status. Batch semantics: unique ordinals, deterministic sort, partial failure via status (not omission), cancel as batch-level context error. T6 does not call the resolver from Service.Analyze, does not implement pg_catalog SQL, and does not promote admission. Public SDK/CLI/HTTP request schemas intentionally omit the resolver field until a complete end-to-end path exists.
  • Operand-type binding (binary operators): a package-private helper cross-checks the atomic resolver's per-ordinal type map against returned fact OperandTypeOIDs. For resolved binary operator candidates, the map entry must exist, have exactly two nonzero OIDs, and equal the fact's operand OIDs. Nil, empty, missing, unexpected, malformed, or mismatched entries fail closed (lookup_failed). Functions, casts, and arity-zero candidates are untouched. This is defense-in-depth against contract-violating adapter output, not hostile in-process resolver protection. It is not part of the adapter export surface.
  • Cast fields removed: CastSourceTypeName and CastTargetTypeName were removed from EffectIdentityFacts. Phase 1 does not trust casts; cast candidates remain outside the manifest proof boundary.
  • T6 P1 execution resolution context: EffectIdentityRequest.Resolution is an internal EffectIdentityResolutionContext. Phase-1 promotion-ready binding requires all of: Bound, non-empty SessionBinding, non-zero PathEpoch, DatabaseOID, RoleOID, ServerVersionNum. Unqualified also needs non-empty NamespaceSearchOIDs. Explicit schema may skip search_path ranking but not session/database/role/server checks. Resolved facts must be stamped (StampFactsFromResolution) with matching database/server pins. Live gate: session mismatch strips all candidates (including explicit); path-only mismatch strips unqualified only. Context never appears on domain.Result or public JSON.
  • T7 catalog adapter lives in internal/infrastructure/metadata/postgresql (PinnedSession + EffectIdentityAdapter). It is facts-only and implements ControlledEffectIdentityResolver. CaptureExecutionBoundContext returns the pinned session's live resolution context so the application can set explicit Resolution on the request. Callers that use it must pin one session, run live→lookup→live+gate, and must not promote admission until T8 manifest proof.
  • T8 manifest proof enables PostgreSQL admission promotion when all effect candidates are exactly proven by an audited manifest. NewTrustedService() accepts ControlledEffectIdentityResolver (not generic EffectIdentityResolver) so only controlled implementations can trigger promotion. The application captures execution-bound context explicitly via CaptureExecutionBoundContext() before resolution. TrustPolicy evaluates resolved facts against the versioned PG17Manifest. TrustDecisionAllProven is the sole path to read_only + admissible for PostgreSQL. The PG hard-stop in reclassifyAfterResolution is replaced with manifest-gated promotion. Without a trusted bundle, PostgreSQL remains fail-closed (indeterminate). Phase-1 provable queries: SELECT count(*) FROM users (arity-0 aggregate, no type inference). Operators with literals (id = 1) remain indeterminate (literal type unknown → coercion_gap).
  • Identity-failure categories map only through domain.ReasonForIdentityFailure / ReasonForIdentityStatus; free-text errors cannot be injected as trusted reasons. Manifest trust policy and admission promotion remain T8.
  • Callers cannot supply ReasonCodes on QueryAccessRequest; transports passthrough the single application domain result.
  • buildRequirements generates access requirements based on mode: strict requires all resolved columns, projection-only requires only output-contributing columns and emits inference_risk warning.
  • Both modes require every permission-bearing relation (PermissionRequired: true).
  • Required unresolved references produce indeterminate requirements.
  • Resolution caches relation schemas per request (key: schema.name). CTEs and derived tables bypass resolution.
  • Views are detected from metadata and marked as RelationView kind without definition expansion.
  • Unqualified columns resolve only when exactly ONE source relation has the column.
  • Wildcards expand in deterministic ordinal order when metadata is available.
  • Unbound relation safety (PostgreSQL): When Service.Analyze detects unqualified base relations in PostgreSQL with a trusted bundle, it marks those relations as Unbound and adds a bounded unqualified_relation indeterminate requirement. Unbound relations are excluded from the resolution state (nameMap, aliasMap, relationOrder) so the resolver never calls DefaultSchema on them. resolveQualifiedColumn, expandTableStar, and expandTableWildcard skip resolution when the relation is unbound and has no qualified entry in nameMap. buildRequirements skips columns with empty Schema when unbound relation names exist, preventing unresolved references from producing physical read_column requirements. resolveSourceKeys and sourceIsUnbound treat schema-qualified references (3-part keys with non-empty schema) as non-unbound, preserving requirements for qualified relations that share a table name with an unbound relation.
  • The PostgreSQL parser resolves aliases to table names, so SELECT p.id FROM public.users p JOIN users u produces both columns with Table: "users". The unbound check uses resolveRelationRefnameMap to distinguish: if nameMap has a qualified entry, resolution proceeds; if not (all entries unbound), resolution is skipped.
  • Same-connection metadata resolver (T15): QueryAccessConnResolver in internal/infrastructure/metadata/postgresql wraps a single *sql.Conn directly (no *sql.DB field). It satisfies SchemaResolver and ensures metadata queries run on the same backend as the identity adapter. The public SDK wrapper (PostgreSQLQueryAccessSession in pkg/deltascope) creates all resolvers from the same caller-owned *sql.Conn. The assembly helper newTrustedServiceFromSession lives in pkg/deltascope (postgresql-tagged) to avoid import cycles.
  • MySQL/TiDB builtin semantic proof is independent from PostgreSQL catalog trust. Its production registry is populated for mysql-5.7, mysql-8.0, mysql-8.4, and tidb-8.5; only the explicit same-connection SDK session can construct the private capability. Default SDK/CLI/HTTP remain offline and fail-closed for function-bearing MySQL/TiDB queries. Test-owned manifests may also exercise the gateway without mutating the production registry.
  • COUNT(integer_one) proof is narrower than generic physical requirements: only a single schema-qualified base table, one exact read_table requirement, no columns/unresolved references, and the parser's complete unqualified COUNT(1) statement envelope may enter the dedicated pg_catalog.count(any) proof path. Other literals, modifiers, joins, relationless queries, views, CTEs, derived tables, and unresolved relations remain indeterminate.

Dependencies

  • Upstream: internal/interfaces/*
  • Downstream: internal/application, internal/application/connresolve, internal/domain/queryaccess, internal/infrastructure/parser/tidb, internal/infrastructure/parser/postgresql, internal/infrastructure/metadata/mysql, internal/infrastructure/metadata/postgresql

Update Rule

  • If members/interfaces/dependencies change, update this file in same change.

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

View Source
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.

View Source
const PgCatalogNamespaceName = "pg_catalog"

PgCatalogNamespaceName is the PostgreSQL system catalog schema name. Used only for internal explicit-schema checks; not a trust claim.

Variables

View Source
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")
)
View Source
var (
	ErrInvalidAnalysisProfile         = errors.New("invalid query access analysis profile")
	ErrAnalysisProfileDialectMismatch = errors.New("query access analysis profile does not match dialect")
)
View Source
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")
)
View Source
var ErrBOMOnlySQL = errors.New("query access SQL must not be empty")

ErrBOMOnlySQL indicates SQL became empty after removing one leading UTF-8 BOM.

View Source
var ErrBuiltinSemanticManifestInvalid = errors.New("invalid builtin semantic manifest")
View Source
var ErrExtractionFailed = errors.New("query access extraction failed")

ErrExtractionFailed indicates query access extraction failed without exposing SQL text.

View Source
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.

View Source
var ErrPostgreSQLNotAvailable = errors.New("postgresql support requires build tag: go build -tags postgresql")

ErrPostgreSQLNotAvailable indicates PostgreSQL support was not compiled in.

View Source
var ErrTrustedBundleInvalid = errors.New("invalid trusted bundle")

ErrTrustedBundleInvalid indicates the trusted bundle failed validation.

View Source
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

func FormatRelationSchemaKey(schema, name string) string

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

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):

  1. 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.
  2. Unqualified operators/functions also require non-empty NamespaceSearchOIDs (ResolutionContextUsableForUnqualified). Without that proof they MUST be IdentityStatusUnavailable. Adapters must not invent pg_catalog.* names.
  3. 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.
  4. 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.
  5. 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

type OperandColumnRef struct {
	Schema string
	Table  string
	Column string
}

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

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL