Commit Graph
528 Commits
Author SHA1 Message Date
warkanum ff76eb8e1f feat(security): stamp transaction-local settings on OnTxBegin in all specs 2026-09-30 22:55:26 +02:00
warkanum 3b93802a25 fix(tx): run restheadspec AfterRead in a second short transaction 2026-09-30 22:53:07 +02:00
warkanum 6b6f540ab0 feat(tx): run funcspec OnTxBegin and BeforeResponse in transactions 2026-09-30 22:50:41 +02:00
warkanum 4cbe4f597d feat(tx): run resolvemcp operations in per-operation transactions with OnTxBegin 2026-09-30 22:49:47 +02:00
warkanum ed457eb14a feat(tx): run websocketspec and mqttspec operations in per-message transactions
Reads and deletes run in one transaction; create and update write in one
and re-fetch plus After hooks in a second. OnTxBegin fires first in each.
2026-09-30 22:46:46 +02:00
warkanum 97bcb44fdc fix(clients): verify C# client, read Content-Range from content headers 2026-09-30 22:44:15 +02:00
warkanum 17bb6ea76d fix(clients): verify Dart client, case-insensitive Content-Range lookup 2026-09-30 22:42:55 +02:00
warkanum ce706bacda feat(tx): run update re-fetch and post-commit hooks in a second transaction
Re-fetch, BeforeScan and AfterUpdate/AfterCreate now run on a short
transaction that fires OnTxBegin. Existence selects inside the first
transaction use tx instead of the pool.
2026-09-30 22:42:33 +02:00
warkanum eb492d52aa feat(clients): add Go, Rust, C# and Dart clients for ResolveSpec and FunctionSpec 2026-09-30 22:40:33 +02:00
warkanum f2dbe2561c feat(hooks): add OnTxBegin and runInTx for resolvespec and restheadspec
Every transaction the handlers open now fires OnTxBegin first, with the
transaction in hookCtx.Tx, via common.RunRequestTx.
2026-09-30 22:40:06 +02:00
warkanum cd96404cdd fix(delete): run delete hooks and queries in one transaction
- resolvespec/restheadspec: single and batch delete use one transaction
- add sqlmock tests for delete transaction behaviour
- testmodels: serial integer ids; update tests accordingly
- add compose testserver, smoke script, podman-first Makefile targets
2026-09-30 22:33:25 +02:00
warkanum b2b815552f refactor: move JS and Python clients under clients/ 2026-09-30 22:31:43 +02:00
warkanum f6a9daa89e docs(audit): add plan for single transaction per request 2026-09-30 22:18:24 +02:00
warkanum 54e6a3b17c feat(resolvespec-python): add Python client for ResolveSpec, HeaderSpec, FunctionSpec and WebSocketSpec 2026-09-30 22:18:01 +02:00
warkanum ab3d2b5b04 docs(audit): add funcspec server-side audit 2026-09-30 22:18:01 +02:00
warkanum 3e327d0c78 fix(db): reduce per-request connection bursts and add dbtrace
* Throttle async session-activity writes to once per token per minute
* Add singleflight to session lookups, keystore validation and
  column/row security loads to stop cold-cache stampedes
* Preload security rules in BeforeHandle (restheadspec, resolvespec) so
  they no longer need a second connection while the read tx is open
* Add pkg/dbtrace: opt-in per-request DB call counting and pool logging
  (db_trace.* config, RESOLVESPEC_DB_TRACE_* env), wired into testserver
* Add tests for load dedup, activity throttle and dbtrace
2026-09-30 21:44:28 +02:00
warkanum 62cc14c02a feat(resolvespec-js): support extended restheadspec headers
Add HeaderSpecOptions, vector_search, X-Preload-Where, X-Expand,
custom SQL joins/or, spatial/vector filters, response format, flags
and X-Files to buildHeaders, types and README.
2026-09-30 21:37:41 +02:00
Hein 4c5dffc3d1 test(mqttspec): add tests for update behavior with empty strings 2026-09-30 17:15:55 +02:00
Hein 2898b335f8 feat(db): add ApplicationName to connection configuration
* Introduced ApplicationName field to identify clients in DSN
* Set default ApplicationName to "ResolveSpec"
* Updated tests for ApplicationName handling in DSN
v1.2.6 v1.2.5
2026-09-30 17:12:04 +02:00
Hein 20ba8ed112 feat(update): allow clearing values with "" and null on update
Update handlers skipped empty strings and nulls, so a client could not
blank or null out a column. Every key present in the payload now
overwrites the stored value, including "" and null.

- add common.MergeUpdateValues and use it in resolvespec and restheadspec
- add Handler.SetDisallowNulls to skip null values (""still overwrites)
- websocketspec and mqttspec now write only the keys present in the
  payload via SetMap instead of updating the whole zeroed model, which
  clobbered absent fields
v1.2.4
2026-09-30 17:03:42 +02:00
Hein 1214f69e0c feat(middleware): export clientqueue_enqueued_total counter
Counts every request placed in a wait queue regardless of outcome, so the
total ever queued no longer has to be summed from queued, timeout and
canceled.
v1.2.3
2026-09-30 16:16:25 +02:00
Hein 89a58ab3a0 feat(middleware): export clientqueue_waiting_clients gauge
Counts clients with at least one queued request, updated whenever a
client's waiter count crosses zero (enqueue, grant, timeout, cancel).
2026-09-30 16:14:27 +02:00
Hein 48081b4aa4 docs: document client queue and dbmanager pool stats v1.2.1 2026-09-30 15:46:43 +02:00
Hein 467dbd66c8 feat(middleware): add per-client FIFO request queue with burst metrics
ClientQueue limits concurrent requests per client (X-Client-Id, then
Authorization, session, IP) and queues the rest first-in-first-out, with
bounded depth, max wait and idle eviction. Chain composes it with auth for
the Setup*Routes middleware slot. Exports burst, wait and depth metrics.
The test server uses it with a limit of 10.
2026-09-30 15:46:42 +02:00
Hein 178d40587d feat(dbmanager): report pool max size and total connections opened
Add MaxOpenConnections to provider and connection stats, exposed as the
max state of dbmanager_connection_pool_size. Count physical dials through a
counting driver connector and export dbmanager_connections_opened_total;
existing_db pools derive an approximate count from sql.DBStats.
2026-09-30 15:46:41 +02:00
Hein d3a99550d9 fix(security): name GetTemplate results to satisfy gocritic
Tests / Race Detector (push) Failing after 25s
Tests / Unit Tests (push) Failing after 25s
Tests / Integration Tests (push) Failing after 27s
Build , Vet Test, and Lint / Build (push) Successful in 1m3s
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Successful in 1m30s
Build , Vet Test, and Lint / Lint Code (push) Successful in 1m31s
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Successful in 1m31s
v1.2.0
2026-09-30 13:46:03 +02:00
Hein 8a94d884e7 fix(security): verify passwords, bind row-security args, fail closed on panic
Verify bcrypt passwords in Direct mode and the shipped procedures, hash on
register/reset, ignore client-supplied roles and level at registration and
drop the password from the jwt_login payload. Legacy cleartext upgrade is
opt-in. Row security templates now bind the user as a parameter, validate
identifiers, attach via common.SelectQuery and fail the request if the
filter cannot be attached. ApplyColumnSecurity and GetRowSecurityTemplate
convert panics to errors and the hooks fail closed. Update audit status.
2026-09-30 13:44:59 +02:00
Hein f9c948ca4e fix(tracing): address audit findings
Default to TLS export with Insecure/TLSConfig/Headers options, parent-based
ratio sampling (default 0.1), and no query string or Host in span attributes.
Name spans by route template, record status and panics (re-raised), guard the
tracer with atomic.Pointer, reject double init, add init timeout and attribute
length limit, and move to semconv v1.26.0. Add tracing.insecure and
tracing.sample_rate config keys and tests.
2026-09-30 13:39:50 +02:00
Hein 164ba2b240 fix(security): remove lock contention, cache rules, stop leaked goroutines
Load column/row security without holding locks across provider calls,
honour pOverwrite with a 30s TTL and pruning, cap tokens per
Authorization header, detach session activity updates with a timeout,
stop OAuth2 cleanup goroutines via Close, move nil-map checks inside
locks, and drop O(n^2) string building. Update audit status.
2026-09-30 13:31:03 +02:00
Hein 97fe88b3a6 fix(modelregistry): address audit findings
Replace try-lock/sleep scheme with blocking locks, add ErrModelNotFound/
ErrModelExists/ErrInvalidModel sentinels, make RegisterModelWithRules
atomic, snapshot in IterateModels, guard defaultRegistry access, cap the
pointer-unwrap depth, and recover panics in callbacks and reflection.
Security hooks now allow-by-default only on ErrModelNotFound. Add tests.
2026-09-30 13:26:55 +02:00
Hein a4e1abc1df fix(logger): address audit findings
Redact and rate-limit error tracker fan-out, cap panic stack capture,
sanitise stdlib fallback output, strip contexts in Info/Debug, sync the
replaced logger, add Sync, UpdateLoggerE and CatchPanicRethrow, cache
the PID, and add tests.
2026-09-30 13:19:52 +02:00
Hein d7cb111496 docs(audit): add audit report for pkg/common 2026-09-30 13:16:47 +02:00
Hein f66930c3c9 chore(gosec): enable gosec and address findings 2026-09-30 13:16:12 +02:00
Hein 9533c3a0ed fix(cache): harden providers and default cache handling
Make cache-write failures non-fatal in GetOrSet/Remember, replace the
unsynchronised default cache with an atomic pointer, fix tag-index leaks
and write-lock-on-read in the memory provider, add a janitor, closed
state and byte copies, hash/namespace memcache keys with CAS tag index,
gate Clear behind AllowFlush, return ErrNotFound without the key, and
allowlist Redis stats. Mark audit status.
2026-09-30 13:13:06 +02:00
Hein 652621a70e ci: add race detector job 2026-09-30 13:09:44 +02:00
Hein c7b4530689 fix(race): make make test-race pass across ./pkg/...
Add a test-race target and run test-unit over ./pkg/...

Production races:
- logger: guard Logger/errorTracker with an RWMutex
- security: copy UserContext for the async session-activity goroutine
  and track it with a WaitGroup

Test fixes:
- eventbroker, websocketspec: use atomics for state shared with workers
- security: wait for async activity updates before touching sqlmock
- mqttspec: build full HookContext, set SubscriptionID, pin the
  in-memory SQLite to one connection

Update the cross-cutting audit (X1) with status and findings.
2026-09-30 13:07:47 +02:00
Hein e1cf72834e fix(config): lock Manager, harden defaults handling and path/IP helpers
Guard viper with an RWMutex, make the singleton race-free and stop
NewManager replacing the global (add SetConfigManager), write saved
configs 0600, search CWD last, add ConfigFileUsed and Config.Validate,
nil-safe PathsConfig.Set, confine PathsConfig.Join, bound GetIPs DNS
lookup, and drop dead Unmarshal in SetConfig. Mark audit status.
2026-09-30 13:02:40 +02:00
HeinandClaude Sonnet 5.5 3657aa94cc fix(dbmanager): explicitly ignore best-effort listener close errors
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 12:40:22 +02:00
HeinandClaude Sonnet 5.5 da1af1487e fix(dbmanager): keep the pool alive across errors and restarts
Implements the fixes from audit/pkg/dbmanager.audit.md.

- Stop closing the shared *sql.DB to recover from errors. Adapter
  factories and the health checker no longer call Reconnect; Reconnect is
  atomic and operator-only.
- Postgres uses a custom driver.Connector: Reconnect retires pooled
  connections by generation without closing the pool, so held Bun/GORM
  handles keep working. Verified against a live server restart.
- Add TCP keepalive, TCP_USER_TIMEOUT, a bounded reuse ping and
  statement_timeout as a runtime parameter; drop the 2 min timeout floor.
- Health check pings without holding the connection lock.
- Listener: single goroutine pair, bounded Close without UNLISTEN, and
  serialised use of the pgx connection (fixes conn busy and a close race).
- Fix Connect/Close/Connect/Close panic, idempotent Connect, dial outside
  the manager lock, clean up on partial failure.
- SQLite: pin :memory: to one connection, pragmas via DSN.
- Escape credentials in Postgres/MSSQL/Mongo DSNs; sslmode defaults to
  prefer. Wire retry settings, publish metrics, fix logger calls.
- NewConnectionFromDB: Close is a no-op with a warning (caller owns the
  pool); Reconnect only pings.
- Document correct usage in the README; mark the audit with what was done.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 12:40:14 +02:00
Hein bc8bff7955 docs(audit): add audit reports for pkg/testmodels and pkg/tracing
Tests / Unit Tests (push) Failing after 24s
Tests / Integration Tests (push) Failing after 26s
Build , Vet Test, and Lint / Build (push) Successful in 1m7s
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Successful in 1m31s
Build , Vet Test, and Lint / Lint Code (push) Successful in 1m33s
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Successful in 1m34s
2026-09-29 17:15:00 +02:00
Hein a74eebc7f3 fix(json-columns): skip JSON select columns with no model scan target
Tests / Unit Tests (push) Failing after 28s
Tests / Integration Tests (push) Failing after 29s
Build , Vet Test, and Lint / Build (push) Successful in 1m12s
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Successful in 1m43s
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Successful in 1m46s
Build , Vet Test, and Lint / Lint Code (push) Successful in 1m48s
Requesting a JSON sub-field (e.g. jsonvalue->'product'->>'cost') that has
no matching bun scanonly field on the model made the whole read fail with
"bun: ModelX does not have column Y", since bun scans SELECT results
straight into the typed model struct.

Add reflection.HasColumn to check whether the model can actually receive
a given column (including scanonly fields, walking embedded structs), and
gate the JSON select-column expression on it in ApplySelectColumns
(shared by websocketspec/mqttspec) and the resolvespec/restheadspec
handlers. When there's no scan target, drop just that column with a
warning instead of erroring the whole request.
v1.1.55
2026-09-28 12:30:56 +02:00
Hein 6687a7a5cd fix(bun): spread variadic args correctly in ColumnExpr v1.1.54 2026-09-28 12:01:38 +02:00
warkanum e8fbbede7e chore: update version to 1.0.2 and changelog
Tests / Unit Tests (push) Failing after 25s
Tests / Integration Tests (push) Failing after 26s
Build , Vet Test, and Lint / Build (push) Successful in 1m9s
Build , Vet Test, and Lint / Lint Code (push) Successful in 1m29s
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Successful in 1m32s
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Successful in 1m33s
2026-09-23 20:58:18 +02:00
warkanum 7f8982fa35 feat(headerspec): add UTF-8 encoding/decoding support
* Implement round-trip encoding/decoding for UTF-8 values in header functions.
* Update encodeHeaderValue and decodeHeaderValue to use base64 utility functions.
* Add tests for UTF-8 header value handling.
* Update Vite config to externalize base64 utility.
2026-09-23 20:57:50 +02:00
warkanum b587cbd3c4 feat(headers): add support for custom HTTP headers in clients
* Introduced `headers` property in `ClientConfig` interface.
* Updated `HeaderSpecClient` and `ResolveSpecClient` to utilize custom headers.
* Implemented `mergeHeaders` function to handle case-insensitive header merging.
* Added tests for custom header functionality in clients.
2026-09-23 19:47:05 +02:00
Hein a220338eea feat(spectypes): add CIString, LCString, and UCString types with tests
Tests / Unit Tests (push) Failing after 28s
Tests / Integration Tests (push) Failing after 30s
Build , Vet Test, and Lint / Build (push) Successful in 1m8s
Build , Vet Test, and Lint / Lint Code (push) Successful in 1m18s
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Successful in 1m35s
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Successful in 1m36s
v1.1.53
2026-09-21 14:06:33 +02:00
Hein 20c67166d0 fix(handler): support implicit updates from request body v1.1.52 2026-09-21 11:18:10 +02:00
Hein 749dad4ed1 fix(quickproxy): ensure request body is preserved on fallback
Tests / Unit Tests (push) Failing after 26s
Tests / Integration Tests (push) Failing after 41s
Build , Vet Test, and Lint / Build (push) Successful in 4m26s
Build , Vet Test, and Lint / Lint Code (push) Successful in 4m58s
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Successful in 5m1s
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Successful in 5m3s
v1.1.51
2026-09-21 09:21:58 +02:00
warkanum d6c5740f9c fix(handler): add operation type to hook context
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Failing after 1s
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Failing after 1s
Build , Vet Test, and Lint / Lint Code (push) Failing after 1s
Build , Vet Test, and Lint / Build (push) Failing after 1s
Tests / Unit Tests (push) Failing after 0s
Tests / Integration Tests (push) Failing after 10s
v1.1.50
2026-09-20 16:12:44 +02:00
warkanum 817b781c88 fix(security): skip loading security rules if disabled v1.1.49 2026-09-20 15:52:25 +02:00