~bigbes/sr-ht-spec: dc1e5d0c

feat: Postgres schema, initial migration and the db/ query layer

The six tables of the design's Postgres schema — space, document_id,
proposal, agent_token, index_stamp, digest_mark — plus a typed query layer
over them. project and comment stay deliberately absent.

Two invariants are enforced in SQL rather than in Go, because a
check-then-write in Go has a window and this does not:

  - Global document ID uniqueness is the doc_id PRIMARY KEY, and the merge
    path's multi-row upsert guards its ON CONFLICT branch on the owning
    space, so a batch claiming another space's ID leaves that row untouched
    and surfaces as a CollisionError naming where the ID really lives.
  - Proposal transitions run as UPDATE ... WHERE state = 'open'; the current
    state is read back only to name it in the error. CHECK constraints make
    an unknown state, a merged row without an approval kind or merged_rev,
    and empty provenance unwritable by anything, including SQL that does not
    go through this package.

MergeProposal wraps the transition and the registry re-pointing in one
transaction: a merged proposal whose documents are still registered at their
pre-merge paths would break link resolution and the next staleness check.

Agent tokens store only a SHA-256 hash; the lookup boundary re-verifies with
subtle.ConstantTimeCompare and rejects revoked tokens distinctly.

Tests skip when SPECSRHT_TEST_PG is unset, so the pure-logic half — batch
duplicate detection, token comparison, argument guards, and the agreement
between schema.sql and migrations/0001_initial.sql — still runs with no
database available.

Eugene Blikh <bigbes@gmail.com> — 2026-07-22 08:16:37 UTC

Commit dc1e5d0c4000dd1a900a14975c44327a87f2c14dview raw patch

Parent(s): 7c827866

15 changed file(s)

FileStatus+
db/db_test.go A +154
db/document.go A +327
db/document_test.go A +176
db/proposal.go A +282
db/proposal_test.go A +295
db/space.go A +117
db/space_test.go A +77
db/stamps.go A +101
db/stamps_test.go A +97
db/store.go A +178
db/token.go A +201
db/token_test.go A +118
db/unit_test.go A +381
migrations/0001_initial.sql A +66
schema.sql A +97