Documentation
¶
Overview ¶
Package sqlite provides SQLite implementations of the store ports (AgentStore, CertificateStore, EndpointStore, RenewalStore, RevocationStore, ByocCertificateStore) plus an outbox table used by the RA→TL HTTP client for durable event delivery.
The adapter uses modernc.org/sqlite — a pure-Go transpilation of upstream SQLite — so the binaries cross-compile without CGO. Schema migrations are embedded; on Open() the database is created if missing and migrations are applied. The embedded migration files live in migrations/*.sql relative to this package.
Index ¶
- type AgentStore
- func (s *AgentStore) Delete(ctx context.Context, id int64) error
- func (s *AgentStore) ExistsByAnsName(ctx context.Context, ansName domain.AnsName) (bool, error)
- func (s *AgentStore) ExpireLapsedPendingValidation(ctx context.Context, now time.Time) (int64, error)
- func (s *AgentStore) FindAllByAgentHost(ctx context.Context, host string) ([]*domain.AgentRegistration, error)
- func (s *AgentStore) FindByAgentID(ctx context.Context, agentID string) (*domain.AgentRegistration, error)
- func (s *AgentStore) FindByAnsName(ctx context.Context, ansName domain.AnsName) (*domain.AgentRegistration, error)
- func (s *AgentStore) FindByID(ctx context.Context, id int64) (*domain.AgentRegistration, error)
- func (s *AgentStore) FindExistingByFQDN(ctx context.Context, fqdn string) ([]*domain.AgentRegistration, error)
- func (s *AgentStore) ListByOwner(ctx context.Context, ownerID string, filter port.ListFilter) (*port.CursorPage[*domain.AgentRegistration], error)
- func (s *AgentStore) Save(ctx context.Context, agent *domain.AgentRegistration) error
- type ByocCertificateStore
- func (s *ByocCertificateStore) FindByAgentID(ctx context.Context, agentID string) ([]*domain.ByocServerCertificate, error)
- func (s *ByocCertificateStore) FindLatestValidByAgentID(ctx context.Context, agentID string) (*domain.ByocServerCertificate, error)
- func (s *ByocCertificateStore) Save(ctx context.Context, agentID string, cert *domain.ByocServerCertificate) error
- type CertificateStore
- func (s *CertificateStore) FindCSRByID(ctx context.Context, agentID, csrID string) (*domain.AgentCSR, error)
- func (s *CertificateStore) FindIdentityCertificatesByAgent(ctx context.Context, agentID string) ([]*domain.StoredCertificate, error)
- func (s *CertificateStore) FindLatestPendingCSRByType(ctx context.Context, agentID string, csrType domain.CSRType) (*domain.AgentCSR, error)
- func (s *CertificateStore) SaveCSR(ctx context.Context, agentID string, csr *domain.AgentCSR) error
- func (s *CertificateStore) SaveIdentityCertificate(ctx context.Context, agentID string, cert *domain.StoredCertificate) error
- func (s *CertificateStore) UpdateCertificateStatus(ctx context.Context, cert *domain.StoredCertificate) error
- type DB
- type EndpointStore
- func (s *EndpointStore) FindByAgentID(ctx context.Context, agentID string) (*domain.AgentEndpoints, error)
- func (s *EndpointStore) FindByAgentIDs(ctx context.Context, agentIDs []string) (map[string]*domain.AgentEndpoints, error)
- func (s *EndpointStore) Save(ctx context.Context, endpoints *domain.AgentEndpoints) error
- type IdentityLinkStore
- func (s *IdentityLinkStore) Link(ctx context.Context, identityID, agentID string, now time.Time) (bool, error)
- func (s *IdentityLinkStore) ListLiveByAgent(ctx context.Context, agentID string) ([]*domain.IdentityLink, error)
- func (s *IdentityLinkStore) ListLiveByIdentity(ctx context.Context, identityID string) ([]*domain.IdentityLink, error)
- func (s *IdentityLinkStore) Unlink(ctx context.Context, identityID, agentID string, now time.Time) error
- type IdentityStore
- func (s *IdentityStore) ClaimChallenge(ctx context.Context, identityID, nonce string, now, staleBefore time.Time) error
- func (s *IdentityStore) ConsumeChallenge(ctx context.Context, identityID, nonce string, now time.Time) error
- func (s *IdentityStore) ExistsVerified(ctx context.Context, kind domain.IdentifierKind, value string) (bool, error)
- func (s *IdentityStore) FindByID(ctx context.Context, identityID string) (*domain.VerifiedIdentity, error)
- func (s *IdentityStore) FindLive(ctx context.Context, providerID string, kind domain.IdentifierKind, ...) (*domain.VerifiedIdentity, error)
- func (s *IdentityStore) ListByOwner(ctx context.Context, providerID string, limit int, cursor string) (*port.CursorPage[*domain.VerifiedIdentity], error)
- func (s *IdentityStore) MarkRevoked(ctx context.Context, identityID string, now time.Time) error
- func (s *IdentityStore) ReleaseChallenge(ctx context.Context, identityID, nonce string) error
- func (s *IdentityStore) Save(ctx context.Context, v *domain.VerifiedIdentity) error
- func (s *IdentityStore) StageChallenge(ctx context.Context, v *domain.VerifiedIdentity, ...) error
- type OutboxEvent
- type OutboxStore
- func (s *OutboxStore) Claim(ctx context.Context, batchSize int) ([]OutboxEvent, error)
- func (s *OutboxStore) Enqueue(ctx context.Context, eventType, agentID, schemaVersion string, payload []byte, ...) (int64, error)
- func (s *OutboxStore) MarkFailed(ctx context.Context, id int64, attempts int, lastError string, ...) error
- func (s *OutboxStore) MarkSent(ctx context.Context, id int64) error
- type RenewalStore
- func (s *RenewalStore) Delete(ctx context.Context, id int64) error
- func (s *RenewalStore) FindByAgentID(ctx context.Context, agentID string) (*domain.ServerCertificateRenewal, error)
- func (s *RenewalStore) FindPendingByAgentID(ctx context.Context, agentID string) (*domain.ServerCertificateRenewal, error)
- func (s *RenewalStore) ListPendingExpired(ctx context.Context) ([]*domain.ServerCertificateRenewal, error)
- func (s *RenewalStore) Save(ctx context.Context, r *domain.ServerCertificateRenewal) error
- type RevocationStore
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AgentStore ¶
type AgentStore struct {
// contains filtered or unexported fields
}
AgentStore implements port.AgentStore.
func NewAgentStore ¶
func NewAgentStore(db *DB) *AgentStore
NewAgentStore returns a new SQLite-backed AgentStore.
func (*AgentStore) Delete ¶
func (s *AgentStore) Delete(ctx context.Context, id int64) error
Delete removes a registration by ID.
func (*AgentStore) ExistsByAnsName ¶
ExistsByAnsName returns true if any row uses the given ANS name.
func (*AgentStore) ExpireLapsedPendingValidation ¶ added in v0.1.6
func (s *AgentStore) ExpireLapsedPendingValidation(ctx context.Context, now time.Time) (int64, error)
ExpireLapsedPendingValidation flips lapsed PENDING_VALIDATION rows to EXPIRED in one guarded UPDATE and returns the count.
The WHERE clause is the concurrency guard: a row is expired only while it is still PENDING_VALIDATION, its challenge window (acme_challenge_expires_at_ms — shared between the legacy single-token era and the order era) has lapsed, AND its order is still PENDING. A concurrent verify-acme that advances the row (status → PENDING_DNS, or order → ISSUING/COMPLETED/FAILED) removes it from the match set, so the sweep can never clobber a successfully-validated registration or roll its order columns back. Rows with a NULL expiry (pre-challenge-persistence registrations) never match — they carry no window to expire on and remain cancellable instead. Legacy rows have a NULL cert_order_state and are matched by the IS NULL arm.
func (*AgentStore) FindAllByAgentHost ¶
func (s *AgentStore) FindAllByAgentHost(ctx context.Context, host string) ([]*domain.AgentRegistration, error)
FindAllByAgentHost returns all registrations for a given FQDN, newest first.
func (*AgentStore) FindByAgentID ¶
func (s *AgentStore) FindByAgentID(ctx context.Context, agentID string) (*domain.AgentRegistration, error)
FindByAgentID looks up a registration by agent UUID.
func (*AgentStore) FindByAnsName ¶
func (s *AgentStore) FindByAnsName(ctx context.Context, ansName domain.AnsName) (*domain.AgentRegistration, error)
FindByAnsName looks up a registration by versioned ANS name.
func (*AgentStore) FindByID ¶
func (s *AgentStore) FindByID(ctx context.Context, id int64) (*domain.AgentRegistration, error)
FindByID looks up a registration by primary key.
func (*AgentStore) FindExistingByFQDN ¶
func (s *AgentStore) FindExistingByFQDN(ctx context.Context, fqdn string) ([]*domain.AgentRegistration, error)
FindExistingByFQDN returns ACTIVE or PENDING_* registrations for the FQDN.
func (*AgentStore) ListByOwner ¶
func (s *AgentStore) ListByOwner( ctx context.Context, ownerID string, filter port.ListFilter, ) (*port.CursorPage[*domain.AgentRegistration], error)
ListByOwner returns a cursor-paginated list of owned agents.
func (*AgentStore) Save ¶
func (s *AgentStore) Save(ctx context.Context, agent *domain.AgentRegistration) error
Save inserts or updates an AgentRegistration. Endpoints, server cert, and identity CSR are persisted via their dedicated tables — Save only writes the root aggregate row.
type ByocCertificateStore ¶
type ByocCertificateStore struct {
// contains filtered or unexported fields
}
ByocCertificateStore implements port.ByocCertificateStore.
func NewByocCertificateStore ¶
func NewByocCertificateStore(db *DB) *ByocCertificateStore
NewByocCertificateStore returns a new SQLite-backed store.
func (*ByocCertificateStore) FindByAgentID ¶
func (s *ByocCertificateStore) FindByAgentID( ctx context.Context, agentID string, ) ([]*domain.ByocServerCertificate, error)
FindByAgentID returns all BYOC certificates for the agent, newest first.
func (*ByocCertificateStore) FindLatestValidByAgentID ¶
func (s *ByocCertificateStore) FindLatestValidByAgentID( ctx context.Context, agentID string, ) (*domain.ByocServerCertificate, error)
FindLatestValidByAgentID returns the most recently saved BYOC cert that is still within its validity period.
func (*ByocCertificateStore) Save ¶
func (s *ByocCertificateStore) Save( ctx context.Context, agentID string, cert *domain.ByocServerCertificate, ) error
Save persists a BYOC server certificate.
type CertificateStore ¶
type CertificateStore struct {
// contains filtered or unexported fields
}
CertificateStore implements port.CertificateStore.
func NewCertificateStore ¶
func NewCertificateStore(db *DB) *CertificateStore
NewCertificateStore returns a new SQLite-backed CertificateStore.
func (*CertificateStore) FindCSRByID ¶
func (s *CertificateStore) FindCSRByID( ctx context.Context, agentID, csrID string, ) (*domain.AgentCSR, error)
FindCSRByID returns the CSR with the given ID, scoped to the agent. Used both by the CSR-status handler (which already knows the agent from the URL) and by the registration flow (which refreshes the aggregate's embedded slot after a status change).
func (*CertificateStore) FindIdentityCertificatesByAgent ¶
func (s *CertificateStore) FindIdentityCertificatesByAgent( ctx context.Context, agentID string, ) ([]*domain.StoredCertificate, error)
FindIdentityCertificatesByAgent returns all identity certificates for the agent.
func (*CertificateStore) FindLatestPendingCSRByType ¶
func (s *CertificateStore) FindLatestPendingCSRByType( ctx context.Context, agentID string, csrType domain.CSRType, ) (*domain.AgentCSR, error)
FindLatestPendingCSRByType returns the newest PENDING CSR of the given type (IDENTITY | SERVER) for the agent, or (nil, nil) when no such row exists. Used by the verify-acme flow to pick up CSRs submitted at register time for signing once domain control is proven.
func (*CertificateStore) SaveCSR ¶
SaveCSR persists a new or updated CSR (identity or server). Upserts on csr_id; status transitions (PENDING → SIGNED | REJECTED) replace the previous row in place.
func (*CertificateStore) SaveIdentityCertificate ¶
func (s *CertificateStore) SaveIdentityCertificate( ctx context.Context, agentID string, cert *domain.StoredCertificate, ) error
SaveIdentityCertificate persists a newly issued identity certificate.
func (*CertificateStore) UpdateCertificateStatus ¶
func (s *CertificateStore) UpdateCertificateStatus( ctx context.Context, cert *domain.StoredCertificate, ) error
UpdateCertificateStatus updates only the status field.
type DB ¶
type DB struct {
// contains filtered or unexported fields
}
DB wraps a sqlx.DB and is shared by the repository implementations. Use Open to construct one; it applies migrations automatically.
func Open ¶
Open creates or opens the database at path and applies pending migrations. path == ":memory:" yields an in-memory DB (useful for tests).
func (*DB) Run ¶
Run implements port.UnitOfWork. It begins a transaction, threads it through fn's context, and commits or rolls back depending on fn's return.
Rollback errors are wrapped together with the original error so neither is lost — a rollback failure usually points at a deeper problem (deadlock detector firing, connection lost) and silently dropping it would mask the real diagnostic.
Implementation note: SQLite serializes writes inside the process (we cap MaxOpenConns at 1 in `Open`), so opening a transaction also serializes other writers against the same DB. Transactions are expected to be short-lived for that reason.
type EndpointStore ¶
type EndpointStore struct {
// contains filtered or unexported fields
}
EndpointStore implements port.EndpointStore.
func NewEndpointStore ¶
func NewEndpointStore(db *DB) *EndpointStore
NewEndpointStore returns a new SQLite-backed EndpointStore.
func (*EndpointStore) FindByAgentID ¶
func (s *EndpointStore) FindByAgentID(ctx context.Context, agentID string) (*domain.AgentEndpoints, error)
FindByAgentID returns the endpoint collection for the given agent.
func (*EndpointStore) FindByAgentIDs ¶
func (s *EndpointStore) FindByAgentIDs( ctx context.Context, agentIDs []string, ) (map[string]*domain.AgentEndpoints, error)
FindByAgentIDs returns endpoints for multiple agents in a single query.
func (*EndpointStore) Save ¶
func (s *EndpointStore) Save(ctx context.Context, endpoints *domain.AgentEndpoints) error
Save upserts the endpoint collection for the given agent.
type IdentityLinkStore ¶ added in v0.1.6
type IdentityLinkStore struct {
// contains filtered or unexported fields
}
IdentityLinkStore implements port.IdentityLinkStore.
func NewIdentityLinkStore ¶ added in v0.1.6
func NewIdentityLinkStore(db *DB) *IdentityLinkStore
NewIdentityLinkStore returns a new SQLite-backed IdentityLinkStore.
func (*IdentityLinkStore) Link ¶ added in v0.1.6
func (s *IdentityLinkStore) Link(ctx context.Context, identityID, agentID string, now time.Time) (bool, error)
Link upserts a live link for the pair. Idempotent: returns false (and no error) when the pair is already LINKED, so batch calls can skip already-linked agents in the sealed event.
func (*IdentityLinkStore) ListLiveByAgent ¶ added in v0.1.6
func (s *IdentityLinkStore) ListLiveByAgent(ctx context.Context, agentID string) ([]*domain.IdentityLink, error)
ListLiveByAgent returns the agent's live links.
func (*IdentityLinkStore) ListLiveByIdentity ¶ added in v0.1.6
func (s *IdentityLinkStore) ListLiveByIdentity(ctx context.Context, identityID string) ([]*domain.IdentityLink, error)
ListLiveByIdentity returns the identity's live links.
type IdentityStore ¶ added in v0.1.6
type IdentityStore struct {
// contains filtered or unexported fields
}
IdentityStore implements port.IdentityStore.
func NewIdentityStore ¶ added in v0.1.6
func NewIdentityStore(db *DB) *IdentityStore
NewIdentityStore returns a new SQLite-backed IdentityStore.
func (*IdentityStore) ClaimChallenge ¶ added in v0.1.6
func (s *IdentityStore) ClaimChallenge(ctx context.Context, identityID, nonce string, now, staleBefore time.Time) error
ClaimChallenge takes the short-TTL provisional claim that serializes concurrent verify-control attempts across the seal-before-success TL round trip (design §5.6.1). The conditional UPDATE succeeds only while the nonce is live, unconsumed, and not claimed by an attempt fresher than staleBefore — a crashed claimer's stale claim is reclaimable. A claim is NOT consumption.
func (*IdentityStore) ConsumeChallenge ¶ added in v0.1.6
func (s *IdentityStore) ConsumeChallenge(ctx context.Context, identityID, nonce string, now time.Time) error
ConsumeChallenge atomically consumes the live challenge nonce. The conditional UPDATE is the TOCTOU guard: only one of two concurrent verify-control calls can flip challenge_consumed_at_ms from NULL, and an expired or superseded nonce matches zero rows.
func (*IdentityStore) ExistsVerified ¶ added in v0.1.6
func (s *IdentityStore) ExistsVerified(ctx context.Context, kind domain.IdentifierKind, value string) (bool, error)
ExistsVerified reports whether any owner holds a VERIFIED row for (kind, value).
func (*IdentityStore) FindByID ¶ added in v0.1.6
func (s *IdentityStore) FindByID(ctx context.Context, identityID string) (*domain.VerifiedIdentity, error)
FindByID returns the identity with the given identityId.
func (*IdentityStore) FindLive ¶ added in v0.1.6
func (s *IdentityStore) FindLive( ctx context.Context, providerID string, kind domain.IdentifierKind, value string, ) (*domain.VerifiedIdentity, error)
FindLive returns the owner's non-REVOKED row for (kind, value).
func (*IdentityStore) ListByOwner ¶ added in v0.1.6
func (s *IdentityStore) ListByOwner(ctx context.Context, providerID string, limit int, cursor string) (*port.CursorPage[*domain.VerifiedIdentity], error)
ListByOwner returns every identity owned by the principal, newest first.
func (*IdentityStore) MarkRevoked ¶ added in v0.1.6
MarkRevoked is Revoke's conditional Phase C commit: flip VERIFIED → REVOKED, clearing the rotation stage and challenge state, only while the row is still VERIFIED — a verify/rotate that committed during the revoke's seal round trip is never overwritten with the revoker's stale snapshot. Zero rows → conflict (the caller's view was stale; the sealed IDENTITY_REVOKED is the benign residue the retry converges with).
func (*IdentityStore) ReleaseChallenge ¶ added in v0.1.6
func (s *IdentityStore) ReleaseChallenge(ctx context.Context, identityID, nonce string) error
ReleaseChallenge releases a provisional claim after a failed attempt (failed attempts never consume — §3.2). Best-effort: a consumed or superseded nonce matches zero rows, which is fine.
func (*IdentityStore) Save ¶ added in v0.1.6
func (s *IdentityStore) Save(ctx context.Context, v *domain.VerifiedIdentity) error
Save upserts the aggregate. The partial unique indexes enforce the live-row and proven-uniqueness rules; violations surface as conflict errors (the service maps them to IDENTIFIER_DUPLICATE).
func (*IdentityStore) StageChallenge ¶ added in v0.1.6
func (s *IdentityStore) StageChallenge( ctx context.Context, v *domain.VerifiedIdentity, expectedStatus domain.IdentityStatus, expectedNonce string, staleBefore time.Time, ) error
StageChallenge persists a freshly issued challenge onto an existing row, conditional on the load-time snapshot: the status must be unchanged, the nonce must still be the one observed (a concurrent verify consumes it; a concurrent re-add supersedes it), and no fresh seal claim may be live (an in-flight verify must not have its nonce yanked mid-seal). Status, value, and verified_at are deliberately NOT written — issuing a challenge is not a state transition, so a racing commit can never be clobbered.
type OutboxEvent ¶
type OutboxEvent struct {
ID int64
EventType string
AgentID string
SchemaVersion string
PayloadJSON []byte
Attempts int
LastError string
NextAttemptAt time.Time
SentAt time.Time
CreatedAt time.Time
}
OutboxEvent represents a row from the outbox_events table. It is not a port type (the outbox is an internal adapter concept) but it is used by the RA→TL client worker.
SchemaVersion names the envelope schema the RA serialized the inner-event payload for ("V1" or "V2"). The worker uses it to route to the matching TL ingest lane. Both the column and this field were added together (migration 003) so the worker never sees an empty value.
type OutboxStore ¶
type OutboxStore struct {
// contains filtered or unexported fields
}
OutboxStore manages the outbox_events table used for durable RA→TL delivery.
func NewOutboxStore ¶
func NewOutboxStore(db *DB) *OutboxStore
NewOutboxStore returns a new OutboxStore.
func (*OutboxStore) Claim ¶
func (s *OutboxStore) Claim(ctx context.Context, batchSize int) ([]OutboxEvent, error)
Claim returns up to batchSize pending outbox events whose next_attempt_at_ms has passed. Callers process each event and then call MarkSent or MarkFailed. There is no explicit lease — we rely on the single-writer SQLite setup.
func (*OutboxStore) Enqueue ¶
func (s *OutboxStore) Enqueue( ctx context.Context, eventType, agentID, schemaVersion string, payload []byte, earliestAttempt time.Time, ) (int64, error)
Enqueue appends a new outbox event. When the caller wraps this call inside `port.UnitOfWork.Run`, the row is written through the active transaction (via the context-threaded tx in `extx`) and commits or rolls back atomically with whatever domain-state writes preceded it — that's how we guarantee at-least-once delivery without a dual-write window.
schemaVersion must be "V1" or "V2"; the worker reads this value to pick the matching TL ingest lane. An empty value is rejected. Identity events do NOT ride the outbox — they seal synchronously (design §5.6.1: seal-before-success), so there is no "IDENTITY" lane here.
type RenewalStore ¶
type RenewalStore struct {
// contains filtered or unexported fields
}
RenewalStore implements port.RenewalStore.
func NewRenewalStore ¶
func NewRenewalStore(db *DB) *RenewalStore
NewRenewalStore returns a new SQLite-backed RenewalStore.
func (*RenewalStore) Delete ¶
func (s *RenewalStore) Delete(ctx context.Context, id int64) error
Delete removes a renewal by ID.
func (*RenewalStore) FindByAgentID ¶
func (s *RenewalStore) FindByAgentID(ctx context.Context, agentID string) (*domain.ServerCertificateRenewal, error)
FindByAgentID returns the most recent renewal for the agent.
func (*RenewalStore) FindPendingByAgentID ¶
func (s *RenewalStore) FindPendingByAgentID(ctx context.Context, agentID string) (*domain.ServerCertificateRenewal, error)
FindPendingByAgentID returns a pending (not-completed) renewal.
func (*RenewalStore) ListPendingExpired ¶
func (s *RenewalStore) ListPendingExpired(ctx context.Context) ([]*domain.ServerCertificateRenewal, error)
ListPendingExpired returns renewals whose validation window has elapsed without verification.
func (*RenewalStore) Save ¶
func (s *RenewalStore) Save(ctx context.Context, r *domain.ServerCertificateRenewal) error
Save inserts or updates a renewal aggregate.
type RevocationStore ¶
type RevocationStore struct {
// contains filtered or unexported fields
}
RevocationStore implements port.RevocationStore.
func NewRevocationStore ¶
func NewRevocationStore(db *DB) *RevocationStore
NewRevocationStore returns a new SQLite-backed RevocationStore.
func (*RevocationStore) FindByAgentID ¶
func (s *RevocationStore) FindByAgentID(ctx context.Context, agentID string) (*domain.AgentRevocation, error)
FindByAgentID returns the revocation record for an agent.
func (*RevocationStore) Save ¶
func (s *RevocationStore) Save(ctx context.Context, rev *domain.AgentRevocation) error
Save persists a revocation record.