Documentation
¶
Overview ¶
Package postgres is Harbor's Postgres-backed `skills.SkillStore` driver. It brings the skills subsystem to the three-driver persistence parity every other persistence-shaped subsystem already has (in-memory / SQLite / Postgres) defined by RFC §6.7 + §9: skills persist durably in shared Postgres for multi-instance deployments instead of only a per-instance SQLite file.
The driver uses `pgx/v5/stdlib` so the rest of Harbor sees a `database/sql.DB`. Parametric queries everywhere; no string concatenation into SQL (AGENTS.md §9). An advisory lock serialises the migration runner so multi-replica boots are race-free.
Behavioural parity with the SQLite (`localdb`) driver is proven by the shared `internal/skills/conformancetest` suite, which this driver passes unchanged — no interface change, no `Supports*` capability ceremony (AGENTS.md §4.4). The conflict policy (pack-overwrite refusal, generated-to-generated idempotency, LWW), identity-scoped `WHERE` filters, and the search ranking ladder all match the SQLite driver.
Search ¶
Search feeds the same backend-agnostic ranking ladder the SQLite driver uses: full-text first, then a regex fallback, then an exact lowercase-equality fallback. The full-text tier rides a STORED generated `tsvector` column + a GIN index (Postgres' analogue of SQLite's FTS5 virtual table); the regex + exact tiers are pure-Go / parameterised-SQL over the identity-scoped rows, byte-for-byte the same scoring constants as the SQLite driver. Scores are normalised to 0..1 so ranking is backend-independent. The opt-in semantic retrieval mode ranks by embedding similarity over the identity- scoped catalog, mirroring the SQLite driver.
Skill state lives in this driver's OWN `skills` table — the driver does NOT piggyback on the Postgres StateStore. The injected `events.EventBus` dep IS used (for the identity-rejection emit path AND the four `skill.*` audit events). The skills `Deps` struct does NOT carry a `StateStore`.
The driver self-registers under `"postgres"` from its `init()`. The production binary picks it up via the `internal/drivers/prod` aggregator's blank import; tests may call `New` directly to skip the registry.
Concurrency contract (AGENTS.md §5 "Concurrent reuse"):
- The driver struct holds a `*sql.DB` (an internally-synchronised connection pool), an `atomic.Bool` close flag, and immutable retrieval config computed at open. All safe for N concurrent goroutines without external locking.
- Per-call state lives on the call stack / supplied `ctx`. Nothing mutable on the driver ever crosses run boundaries.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func New ¶
func New(cfg skills.ConfigSnapshot, deps skills.Deps) (skills.SkillStore, error)
New constructs a Postgres-backed `skills.SkillStore` against `cfg.DSN`. Production callers go through `skills.Open`; tests may call `New` directly to skip the registry.
`deps.Bus` is required. A misconfigured DSN fails loudly at boot via an eager ping — never on the first Upsert. Semantic retrieval (opt-in) requires the injected embedder; a nil embedder under `RetrievalSemantic` fails loudly at construction, never a stub fallback (AGENTS.md §13).
Types ¶
This section is empty.