Skip to content

Give audit, IDs and unstorable text their shared homes - #313

Merged
SaladDay merged 1 commit into
mainfrom
refactor/shared-persistence
Sep 30, 2026
Merged

SaladDay merged 1 commit into
mainfrom
refactor/shared-persistence

Conversation

@SaladDay

@SaladDay SaladDay commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Part of #1 (store layering), foundation PR 1d. Gives audit, identifier parsing and unstorable-text handling one home each, so domain adapters can use them inside their own transactions.

Audit

  • writeaudit and adminaudit own the sources, validation, ErrInvalidSource and the read models: Reader, Filter, Page and ErrInvalidQuery.
  • New persistence/postgres/auditpg:
    • RecordWriteAudit, RecordAdminMutation and RecordDeploymentMutation run on the caller's transaction queries and never begin or commit.
    • auditpg.Store serves the audit reads in one snapshot and runs retention.
  • Behaviour is unchanged:
    • Administrator provenance takes precedence.
    • An unattributed write records nothing.
    • Malformed provenance fails closed.
    • An audit failure aborts the business write.
  • api gets a separate AdminAudit dependency.
  • Deleted from store: write_audit.go, admin_audit.go, admin_history.go and write_audit_queries.go.

IDs

  • pgunit gets ErrInvalidID, ParseID, PathID and LookupCursor.
  • api passes path IDs unchanged, and storage resolves them with PathID.
  • store.UnknownResourceID, parsePathID and lookupCursor are deleted.

Shared errors

  • textvalue.ErrUnstorable is paired with pgunit.IsUnstorableText.
  • credentialcrypto.ErrUnavailable replaces store.ErrCredentialStorageUnavailable.
  • api has one helper for each shared error: writeTextValueError (400), writeCredentialUnavailableError (503) and writeAuditSourceError (400).

Also

  • pgunit.Pool.Queries() is added for single-statement pooled reads.
  • cmd/server builds one units := pgunit.NewPool(pool).
  • IMPLEMENTATION.md Layering names the new owners.

HTTP responses are unchanged, and a new test checks the audit error bodies byte for byte. The OpenAPI schema names moved from store.* to writeaudit.*/adminaudit.*; their shapes are identical.

Checks

Check Result
go build ./..., go vet ./services/core/... pass
api 1372 passed
cmd/... 116 passed
auditpg (PostgreSQL) 12 passed
pgunit and pgtest (PostgreSQL) 11 and 1 passed
execution/... 201 passed
sandbox/providers 433 passed
full store package 1008 passed, 33 opt-in skips
make openapi no diff
scripts/check-names.py pass

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Audit recording and reads move out of store. writeaudit and adminaudit own
the sources, validation, Resource, ErrInvalidSource and the read models;
persistence/postgres/auditpg records rows inside the caller's business
transaction (RecordWriteAudit, RecordAdminMutation,
RecordDeploymentMutation) and serves the audit reads through auditpg.Store,
wired in cmd/server as the new AdminAudit and WriteAudit dependencies.

pgunit owns identifier parsing (ParseID, PathID, LookupCursor), unstorable
text detection (IsUnstorableText) and pool-bound queries for
single-statement reads. api passes malformed path IDs through and storage
resolves them with pgunit.PathID. textvalue.ErrUnstorable and
credentialcrypto.ErrUnavailable are the shared errors, each mapped by one
api helper.
@SaladDay
SaladDay merged commit 41e0a73 into main Sep 30, 2026
9 checks passed
@SaladDay
SaladDay deleted the refactor/shared-persistence branch September 30, 2026 16:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant