Commit Graph
161 Commits
Author SHA1 Message Date
Hein aec87a81e7 fix(bun): ignore scanonly columns in ExcludeColumn
Tests / Integration Tests (push) Skipped
Tests / Unit Tests (push) Successful in 1m37s
Tests / Race Detector (push) Successful in 3m52s
Build , Vet Test, and Lint / Build (push) Successful in 1m33s
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Successful in 2m16s
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Successful in 2m19s
Build , Vet Test, and Lint / Lint Code (push) Successful in 2m19s
Bun's ExcludeColumn errors with "can't find column" for scanonly fields
because they are not in the table's writable fields. Filter the exclude
list to writable bun fields so models with scanonly buffers can insert
and update again. Add tests for the adapter and reflection.
2026-10-05 14:10:52 +02:00
warkanum 9235292586 fix(crud): skip generated and read-only columns on insert and update
Tests / Integration Tests (push) Skipped
Build , Vet Test, and Lint / Build (push) Successful in 1m34s
Tests / Unit Tests (push) Successful in 1m42s
Build , Vet Test, and Lint / Lint Code (push) Successful in 2m11s
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Successful in 2m25s
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Successful in 2m28s
Tests / Race Detector (push) Successful in 4m6s
Read-merge-update wrote every model column back, so GENERATED ALWAYS
columns failed with SQLSTATE 428C9. Add a bun 'generated' tag option,
reflection.NonWritableColumns/RemoveNonWritableColumns, and apply them
in resolvespec, restheadspec, websocketspec, mqttspec, resolvemcp and
the nested CUD processor. Add ExcludeColumn to InsertQuery/UpdateQuery
for model-based writes.
2026-10-02 22:43:45 +02:00
Hein f54b707040 feat(pgsql): add WhereGroup and a podman/docker hardening test
- PgSQLSelectQuery implements common.WhereGrouper so x-custom-sql-or
  is grouped with the client's own conditions on the pgx adapter too.
- Add a container test (opt-in via RESOLVESPEC_TEST_CONTAINERS=1) that
  starts PostgreSQL with podman or docker and checks the hardening
  against a real database: parenthesis escape, pg_sleep, catalog
  subquery, stacked statements, x-custom-sql-or grouping and the
  legacy behaviour when hardening is switched off.
2026-10-01 14:41:46 +02:00
Hein ca89cb8a73 fix(common): harden CORS, sort, raw-SQL WHERE and x-custom-sql-or
Add a `hardening` config section (RESOLVESPEC_HARDENING_*) so each
fix can be switched off to restore the previous behaviour:

- cors_strict_origins: only reflect origins listed in
  cors.allowed_origins / server URLs, with credentials; `*` never
  sends credentials; fix shared-slice append of expose headers.
- sort_strict: join aliases must match `alias.identifier` (empty alias
  no longer matches everything); sort expressions reject dangerous
  functions/catalogs; cql* columns must be identifier-safe.
- sql_strict: client raw-SQL fragments must have balanced parens and
  quotes, no comments/`;`/`$$`, DML keywords, dangerous functions or
  system catalogs; a rejected fragment now fails closed ("(1=0)")
  instead of dropping the filter. Subqueries stay allowed unless
  sql_block_subqueries is set.
- x-custom-sql-or is grouped together with the client's own
  conditions (new optional WhereGrouper, implemented for bun and gorm)
  so it can no longer OR past server-side filters.
2026-10-01 13:46:01 +02:00
Hein e49c3a916e feat(resolvemcp): replace per-model tools with fixed meta tools, guarded filter writes and a function registry
Tools: list_tables, describe_table, select_table, insert_into_table, update_table,
delete_from_table, list_functions, call_function. Visibility follows the model rules.
Filter-based update/delete require filters (never dropped silently), cap the matched rows
(MaxWriteRows), support dry_run, and need a single-use confirm token bound to caller, table,
filters, data and the matched rows. RegisterFunction adds Go-callback and SQL-procedure
functions run in a transaction with BeforeCall/AfterCall hooks. Per-model tools and
resources are removed.

fix(pgsql): UPDATE with SET and a multi-placeholder WHERE renumbered the WHERE parameters
wrongly ($1, $2 became $3, $2); shift them in one pass.
2026-10-01 13:40:00 +02:00
Hein c9fa8c60f2 refactor(security): move all database access into pkg/security/lookup
pkg/security no longer contains SQL. Every provider calls a store interface
from lookup, implemented by a procedure backend (Postgres stored procedures,
the default there) and a direct backend (dialect-driven SQL for postgres,
sqlite, mysql and mssql with configurable table and column names).

- add sectypes, lookup, lookup/{dialect,procedure,direct,backends,ddl,conformance}
- split totp and providers sub packages out of the core package
- replace SQLNames/TableNames/QueryMode with lookup.Config (see breaking_changes.md)
- direct backend now covers column/row security and API-key login
- move txsettings SQL to lookup.ApplyTxSettings; remove password.go
- move schema scripts under lookup/, add reference DDL per dialect
- add a shared conformance suite; run it on sqlite, and on Postgres in a
  podman/docker container (RESOLVESPEC_TEST_CONTAINERS=1)
- fix procedure schema bugs found on real Postgres: duplicate p_data
  parameter, JSON null arrays, expires_at timezone casts, passkey list
  GROUP BY, missing resolvespec_passkey_login; accept zone-less timestamps
2026-10-01 13:19:44 +02:00
Hein 982c90bfdd feat(websocketspec): fire BeforeDisconnect/AfterDisconnect hooks on close
Hooks fire from Connection.Close() once per connection. ConnectionManager
Shutdown now closes connections outside its lock so hooks can call back
into the manager. Update the single-transaction audit plan status.
2026-10-01 10:53:21 +02:00
warkanum a65ca5f5ce fix: fire resolvespec AfterRead/AfterCreate/AfterDelete, key restheadspec total cache by record id 2026-09-30 23:40:32 +02:00
warkanum 7f84debdc5 test(tx): regression tests for per-request transactions across all specs 2026-09-30 23:19:58 +02:00
warkanum 2042205817 fix(pgsql): return subquery preload errors instead of logging and continuing 2026-09-30 23:11:30 +02:00
warkanum ff76eb8e1f feat(security): stamp transaction-local settings on OnTxBegin in all specs 2026-09-30 22:55:26 +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 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
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
2026-09-30 17:03:42 +02:00
Hein f66930c3c9 chore(gosec): enable gosec and address findings 2026-09-30 13:16:12 +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.
2026-09-28 12:30:56 +02:00
Hein 6687a7a5cd fix(bun): spread variadic args correctly in ColumnExpr 2026-09-28 12:01:38 +02:00
Hein e957753ce4 chore(common): satisfy linter on json_column.go (named results, De Morgan) 2026-09-07 17:07:22 +02:00
Hein 206edd4bfd feat: add JSON/JSONB sub-field select, filter and sort
Support column references that traverse into JSON/JSONB values —
data->>'x', data#>>'{a,b}', data->'a'->>'b', and the dotted data.a.b
shorthand — in SELECT column lists, WHERE filters and ORDER BY, across
the restheadspec, resolvespec, websocketspec and mqttspec handlers.

- pkg/common/json_column.go: canonical ParseColumnRef + ColumnRef.SQL()
  builder. JSON path segments are bound as a single ?::text[] parameter,
  never interpolated; cast targets are whitelisted via NormalizeCastTarget.
- pkg/common/json_condition.go: shared entry points mirroring
  BuildSpatialCondition - ResolveJSONColumnExpr (select/sort),
  BuildJSONFilterCondition (where, full operator set; infers ::numeric for
  ordered comparisons on numeric values when no explicit cast is given),
  and the ApplySelectColumns helper.
- pkg/reflection.IsJSONColumn / pkg/spectypes.IsJSONType: disambiguate the
  dotted shorthand (data.city is JSON only when the base is a JSON column).
- pkg/common/validation.go: ColumnValidator accepts JSON tokens.
- Handlers: thread model through the filter call chains and wire the
  select/sort paths.

funcspec (raw-SQL string builder, no param binding or model) and the
FetchRowNumber raw-SQL builders are left as follow-ups, as is OpenAPI
reporting of JSON sub-field columns.
2026-09-07 17:05:52 +02:00
warkanum f259df1258 feat(spectypes): add support for PostGIS and pgvector types
* Implement custom types: SqlGeometry, SqlGeography, SqlHalfVector, SqlSparseVector, SqlBitVector
* Add spatial filter operators and vector similarity operators
* Include metadata and OpenAPI reporting for geometry/vector column types
* Create tests for EWKB and WKT conversions
2026-08-29 21:27:42 +02:00
warkanum 798bb47e71 fix: scan relation preloads through configured model
Tests / Unit Tests (push) Failing after 46s
Build , Vet Test, and Lint / Lint Code (push) Successful in 2m48s
Tests / Integration Tests (push) Failing after 19s
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Successful in 2m56s
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Successful in 2m58s
Build , Vet Test, and Lint / Build (push) Failing after 1m32s
2026-08-28 22:55:44 +02:00
warkanum 105a5e1b87 fix(bun): handle panic in PreloadRelation without returning 2026-08-28 22:47:55 +02:00
warkanum c60565e4e0 feat(resolvespec): add 'contains' operator for array overlap
* Implemented 'contains' operator using BuildArrayOverlapCondition for real array containment.
* Updated documentation to clarify differences between text-cast ILIKE and array overlap.
2026-08-10 15:01:23 +02:00
Hein ef28959c4d test(types): add test for ResolveSortColumns with descending order 2026-07-29 10:15:52 +02:00
Hein 7c737afc5a feat(handler): implement default sort configuration for models
* Add SetDefaultSort method to configure default sort order
* Implement getDefaultSort method to retrieve configured defaults
* Update handleRead to apply default sort when none specified
* Add tests for default sort functionality
2026-07-29 10:05:24 +02:00
Hein 8a06aacfb2 fix(cors): update CORS headers handling for requests
Tests / Integration Tests (push) Failing after 1s
Tests / Unit Tests (push) Failing after 22s
Build , Vet Test, and Lint / Build (push) Successful in 1m1s
Build , Vet Test, and Lint / Lint Code (push) Successful in 1m19s
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
* Reflect request origin for Access-Control-Allow-Origin
* Set Vary header for caching based on origin
* Allow specific headers from preflight requests
* Enable credentials only for specific origins
2026-07-01 12:27:39 +02:00
Hein 11ef16f75a fix(sql_helpers): adjust parenthesis nesting depth comment 2026-06-23 09:41:40 +02:00
Hein 48b72a7631 fix(sql_helpers): enhance splitByAND to handle BETWEEN and quotes
* Add support for BETWEEN-aware AND detection
* Ensure AND inside single-quoted strings does not cause splits
* Update tests to cover new BETWEEN and quote scenarios
2026-06-23 09:41:27 +02:00
Hein 0e8f8925c6 fix(reflection): replace reflect.Ptr with reflect.Pointer
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Failing after 0s
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 0s
Build , Vet Test, and Lint / Build (push) Failing after 0s
Tests / Unit Tests (push) Failing after 1s
Tests / Integration Tests (push) Failing after 1s
* Updated all instances of reflect.Ptr to reflect.Pointer for consistency in type checking.
2026-06-22 16:40:07 +02:00
Hein c120b49529 fix(router): prevent HTML escaping in JSON responses
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Has been cancelled
Build , Vet Test, and Lint / Lint Code (push) Has been cancelled
Build , Vet Test, and Lint / Build (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / Unit Tests (push) Has been cancelled
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Has been cancelled
fix(sql_helpers): avoid prefix extraction in subqueries
2026-06-08 15:13:58 +02:00
Hein 66348dac97 test(handler): add tests for valid nested request verbs 2026-06-08 09:06:29 +02:00
Hein a87cd18b1b fix(handler): validate nested request structure for relations
* added checks for valid _request values in single and multiple relations
* introduced isValidNestedRequest function to encapsulate validation logic
fix(crud): expand operation handling for nested CUD
* added "add" to insert operations and "modify" to update operations
* included "remove" in delete operations
2026-06-08 09:02:29 +02:00
Hein 29449c93d5 fix(test): add tests for asymmetric join column handling
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Has been cancelled
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Has been cancelled
Build , Vet Test, and Lint / Lint Code (push) Has been cancelled
Build , Vet Test, and Lint / Build (push) Has been cancelled
Tests / Unit Tests (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
2026-06-07 19:13:59 +02:00
Hein 3b6e5c75be fix(handler): update foreign key field resolution logic
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Has been cancelled
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Has been cancelled
Build , Vet Test, and Lint / Lint Code (push) Has been cancelled
Build , Vet Test, and Lint / Build (push) Has been cancelled
Tests / Unit Tests (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
* Adjust foreign key field name selection for has-many/has-one relationships
* Improve logging to clarify foreign key and child field usage
2026-06-07 14:20:55 +02:00
Hein 69cc3e2839 fix(db): update Returning method to accept multiple columns 2026-05-27 14:11:20 +02:00
Hein 4018af0636 fix(validation): enhance filter logic for column validation
* adjust handling of "all" filter to consider filtered columns
fix(function_api): improve variable substitution in SQL queries
* add safeSubstituteVar for context-aware value sanitization
2026-05-27 12:17:31 +02:00
Hein c4e79d6950 fix(validation): use strings.EqualFold for case-insensitive comparison 2026-05-27 12:07:08 +02:00
Hein 982a0e62ac fix(validation): add Columns method to retrieve valid column names 2026-05-27 12:06:46 +02:00
Hein 1ce0ab1ab4 fix(validation): improve preload column validation logic
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Failing after -35m6s
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Failing after -35m6s
Build , Vet Test, and Lint / Lint Code (push) Failing after -35m6s
Build , Vet Test, and Lint / Build (push) Failing after -35m6s
Tests / Unit Tests (push) Failing after -35m7s
Tests / Integration Tests (push) Failing after -35m7s
2026-05-21 20:18:01 +02:00
Hein 1f9b230f7f fix(validation): improve preload column validation logic
* Use related model's validator for filtering preload columns
* Ensure valid columns are checked against the correct validator
2026-05-21 20:16:53 +02:00
Hein c42d09238f fix: better error detail for failed sql
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Failing after -35m9s
Build , Vet Test, and Lint / Build (push) Failing after -35m9s
Tests / Unit Tests (push) Failing after -35m10s
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Failing after -35m9s
Build , Vet Test, and Lint / Lint Code (push) Failing after -35m9s
Tests / Integration Tests (push) Failing after -35m10s
2026-05-20 13:06:26 +02:00
Hein 4493bfa40f feat(reflection): add IsEmptyValue helper; guard CUD ops against missing PK
Add reflection.IsEmptyValue to detect nil, empty string, and zero numbers.
Use it in recursive CUD processing to skip update/delete when the primary
key is absent, logging a warning instead of proceeding with an invalid operation.
2026-05-19 09:14:19 +02:00
Hein b157379ff8 fix(restheadspec): return 200 OK with empty body instead of 204 on zero results
Frontend clients are sensitive to 204 No Content responses; always return 200
with an empty array/object and rely on X-No-Data-Found header to signal absence
of records.

Also treat "change" as an alias for "update" in recursive CUD processing.
2026-05-19 08:56:11 +02:00
Hein 52752d9c8b fix(bun): adjust field alignment in BunSelectQuery struct
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Successful in -33m53s
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Successful in -33m29s
Build , Vet Test, and Lint / Lint Code (push) Failing after -33m33s
Build , Vet Test, and Lint / Build (push) Successful in -33m41s
Tests / Unit Tests (push) Successful in -34m28s
Tests / Integration Tests (push) Failing after -34m36s
2026-05-18 17:12:32 +02:00
Hein baca5ad29e fix(bun): add relation alias handling for separate-query preloads
* implement preloadRelationAlias to rewrite WHERE conditions
* update Where method to handle relation alias in queries
2026-05-18 17:12:21 +02:00
Hein 53ab22ce02 fix(nestedCUD): handle error in processChildRelations gracefully 2026-05-18 16:14:24 +02:00
Hein 6590cd789a fix(nestedCUD): re-select rows after insert/update for accurate state
* Ensure result.Data reflects DB-generated defaults after insert.
* Update result.Data with current DB state after update.
2026-05-18 13:10:13 +02:00
Hein 4244e838b1 fix(reflection): enhance GetForeignKeyColumn logic for self-referential models
* Add support for self-referential models in GetForeignKeyColumn
* Update comments for clarity on foreign key resolution strategies
* Introduce selfRefItem struct for testing self-referential behavior
2026-05-18 13:03:07 +02:00
Hein c42fa11c1a fix(reflection): update GetForeignKeyColumn to return multiple columns
* Change return type to []string for composite keys
* Adjust related logic in injectForeignKeys method
* Update tests to validate new behavior for composite foreign keys
2026-05-18 12:39:06 +02:00
Hein cd65946191 fix(database): add Scan method to insert query interfaces
* Implement Scan method for BunInsertQuery, GormInsertQuery, and PgSQLInsertQuery
* Update mock implementations to support Scan method
* Introduce GetForeignKeyColumn utility for foreign key resolution
* Add tests for GetForeignKeyColumn functionality
2026-05-18 12:04:50 +02:00