Repository navigation
driver-sql on MySQL: a declared datetime field defaulting to NOW() gets a precision-less CURRENT_TIMESTAMP default on its datetime(3) column, so MySQL 8.0 refuses the table: sys_activity is never created and its data door answers 500 #21241
Description
Activity
objectstack-fleet commented
on Oct 1, 2026 ContributorAuthorMore actionsTriage: first grade —
bug·priority:p2·domain:engine·area:records·pm:queue. ANOW()default on MySQL carries the column's precisionTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-01T20:53Z. ⛔ Not a claim, ⛔ not a dispatch.Why p2. On MySQL, a declared supported target, one platform table is never created, so its data door answers 500. That covers
sys_activity, andsys_presenceby the same declaration. The boot reports the failure loudly.- This is not the whole-target outage of driver-sql on MySQL: create() answers the insert id (0) instead of the inserted record, so sign-up answers 400 FAILED_TO_CREATE_USER, the dev admin seed fails and no user can sign in #21227 (p1). With driver-sql on MySQL: create() answers the insert id (0) instead of the inserted record, so sign-up answers 400 FAILED_TO_CREATE_USER, the dev admin seed fails and no user can sign in #21227's fix, the dev's boot otherwise served.
- Raise rule: if the claim measures that the missing table breaks a record write (the activity writers run on every mutation), it raises this card to p1 and says so here.
Routing.
driver-sqlisdomain:engine.Direction (the card's scope, accepted):
nowColumnDefault'sdatetimearm on MySQL takes its precision from the one source the builtin columns already use. ⛔ No second literal.- PostgreSQL and SQLite stay as they are, unless measurement shows the same mismatch.
sys_presence.last_seenis measured in the same run.
Pins: the card's MySQL cell (sync, plus an insert answering the stored default), with the SQLite and PostgreSQL cells as the control.
Fold or serial. PR #21239 (#21227, p1, draft) edits the same file, in the same lane, on the same MySQL target. #21227's holder may fold this card into that PR and say so on this card. Otherwise whichever lands second merges
main.Not this card. The
sys_packagesraw DDL observation (domain:services) becomes a card only once a door is measured.
Generated by Claude Code
- addedarea:recordsBusiness objects, records, the views that show data, usable forms, searchBusiness objects, records, the views that show data, usable forms, searchbugSomething isn't workingSomething isn't workingpriority:p2Medium: important, M3Medium: important, M3
on Oct 1, 2026 objectstack-fleet commented
on Oct 1, 2026 ContributorAuthorMore actionsClaim: PM loop round 1
Session:session_017xfMoEjKUuSh2xYB8sCozp
Account:huangyiirene(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-21241-mysql-now-default-precision
Worktree:objectstack-issue-21241
Domain:domain:engine
Seat:domain:engine#1(seat post #6367)
File surface:packages/drivers/driver-sql/src/sql-driver.ts, thenowColumnDefaultmethod (its non-SQLitedatetimearm) and the one precision source the builtin columns already use; pins indriver-sql(the live-dialect cells) and adriver-sqlchangeset. ⛔ No change toplugin-auditorservice-realtimedeclarations (the defect is the driver's), ⛔ notcreate/bulkCreate/upsert.
Container & model:S(one arm, judgment in the precision source and the measurement),mode:subagent,model: opus(dispatch-gates --tier: no path-derived mandate, floor sonnet · default opus · ceiling fable)
Clause-②: no
Thread-read: 5940340798
Serial constraints cleared: read at 2026-10-01T21:34Z againstorigin/mainbe5a83cf. #21227 (PR #21239,create/bulkCreatein the same file) has landed asbe5a83cfa, so the fold triage offered is moot; this branch starts from it. #21236 (area:records, the JSON-column refusal's prescription) is queued behind this card. In flight elsewhere in the lane: #21226 (driver-tursoremote doors) and #20595 stage 2 (metadata-protocolcomments), file-disjoint.
Generated by Claude Code
objectstack-fleet commented
on Oct 1, 2026 ContributorAuthorMore actionsRaise rule applied, at 2026-10-01T21:50Z: it does not hold, so this card stays p2.
domain:engine#1·session_017xfMoEjKUuSh2xYB8sCozp. ⛔ Not a claim.Triage's rule (5940340798) raises the card to p1 if the claim measures that the missing table breaks a record write. The dev measured it on MySQL 8.0.46 at
origin/mainbe5a83cf, through the public data door as the seeded admin:- Create, update and delete of a record all succeed (201, 200, 200), and a read afterwards confirms each.
sys_audit_logholds its rows; that writer is unaffected. - Each mutation's activity row is lost. A
WARNnaming the missing table is logged on the server, and nothing appears in the API answer. - The card's own reach reproduces: schema sync fails for
sys_activity, andGET /api/v1/data/sys_activityanswers 500.
A record write is not broken, so the rule as written does not raise the card. The silent loss of the activity timeline on every mutation is recorded here for the reviewer. The fix proceeds unchanged.
Generated by Claude Code
- Create, update and delete of a record all succeed (201, 200, 200), and a read afterwards confirms each.
objectstack-fleet commented
on Oct 1, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 21241,
"status": "done",
"branch": "claude/issue-21241-mysql-now-default-precision",
"pr": "#21252",
"session": "session_017xfMoEjKUuSh2xYB8sCozp — subagent run; this is the parent's harness-stamped id (Claude-Session trailer on every commit)",
"premise_still_valid": true,
"summary": "Draft PR #21252 (head d334fe3; 3 files, +358/-9, all in driver-sql plus the changeset). IMPLEMENTED: a module constant MYSQL_DATETIME_PRECISION in sql-driver.ts is now the one source for MySQL DATETIME precision. nowColumnDefault('datetime') on MySQL returns knex.fn.now(MYSQL_DATETIME_PRECISION), rendered CURRENT_TIMESTAMP(3). createAuditTimestampColumn's MySQL default is routed through nowColumnDefault, as on SQLite; its emitted DDL is byte-identical. createColumn, updatedAtStamp and the TIMESTAMP widening read the same constant. That takes five literal 3s down to one, with no new literal. PostgreSQL and SQLite emit unchanged SQL. FORK FROM THE TRIAGE TEXT, reported rather than taken silently: 'the one source the builtin columns already use' did not exist. Measured at be5a83c, the builtin columns used literal now(3) and precision: 3, and the declared column used another literal precision: 3. So the source was created, and the builtin columns now read it too. H1 confirmed: at be5a83c nowColumnDefault fell to bare knex.fn.now() for datetime; the audit column used now(3) at sql-driver.ts:17904 and updatedAtStamp at :8351; createColumn's datetime arm used precision: 3 at :19436. H2: PostgreSQL 16.14 accepts CURRENT_TIMESTAMP on timestamptz (what the driver builds), and also on timestamp(3), where it rounds silently. No mismatch, so PostgreSQL is unchanged. H3 (raise rule; sent to the seat by SendMessage, applied as 5941379243, card stays p2): at be5a83c on MySQL 8.0.46 with sys_activity absent, POST crm_account answered 201, PATCH 200 and DELETE 200; the record landed on disk and sys_audit_log has 3 rows. Each mutation's sys_activity row was lost: WARN 'Insert operation failed' and ERROR 'Audit write FAILED (ER_NO_SUCH_TABLE)' in the server log, nothing in the API answer. After the fix (showcase on MySQL, e5cab5f) the same three mutations left created/updated/deleted rows in sys_activity. sys_presence reading: at the base, the showcase boot on MySQL gave schema sync synced 102 / skipped 2 / failed 2. sys_presence was refused with 'Invalid default value for last_seen' and GET /api/v1/data/sys_presence answered 500 DATABASE_ERROR. After the fix there was no Schema sync FAILED, sys_presence and sys_activity both answered 200, and information_schema showed last_seen and timestamp as datetime(3) DEFAULT CURRENT_TIMESTAMP(3), equal to created_at. H4: pins go through declareDialectCell; live MySQL 8.0.46 (+08:00) and PostgreSQL 16.14 (Asia/Shanghai) were run locally with TZ=America/New_York. H5: confirmed for fresh MySQL tables, which could never be created with the refused default, so no migration is owed. But measuring H5 found a sibling in the same statement this PR touches: the legacy TIMESTAMP-to-DATETIME(3) widening (migrateMysqlDatetimeColumns) restated the audit columns' default and DROPPED a declared NOW() default. Measured with a driver built from this branch: COLUMN_DEFAULT null afterwards, and create without the field answered stamped_at null. It is fixed IN PLACE under the bounded exemption. Its shape is the TIME twin's (migrateMysqlTimeColumns already restates NOW()); it is in the same file and gate family; it is named with evidence in the PR body; and it has its own pin (§3) and its own ablation. SEAT ACTION OWED: add migrateMysqlDatetimeColumns to the claim's declared file surface (the dev cannot edit the claim). DEVIATIONS: (1) the container restarted at about 22:35Z, after the PR was opened (22:32Z) and the assignee written (22:33Z); everything since was redone in a fresh worktree off the pushed branch. (2) Per the PM note, origin/main 4727fcb was merged once as a merge (d334fe3, no conflicts, no driver-sql or lockfile change). The workspace was rebuilt, and pins, reverse verification, both suites, typechecks, inheritor tests and all 63 gates were re-run at d334fe3. (3) The PR body, written once at pr_create, quotes HEAD e5cab5f and was not PATCHed. At d334fe3 every reading is identical except driver-turso, now 87 files / 2349 passed | 33 skipped after #21226 landed on main. If the seat wants the body current, it changes the 'Verification (HEAD e5cab5f)' heading to d334fe3 and that driver-turso line. (4) The PostgreSQL data dir had to live in /var/tmp/os-issue-21241-pg, because the postgres user cannot traverse the 0700 scratchpad. It was removed, as was the MySQL data dir. Cleanup: every DB server and dev server I started was stopped by recorded PID or process group; the worktree was removed after node_modules, without --force.",
"tests": "ALL AT HEAD d334fe3 UNLESS NOTED. Pins: pnpm --filter @objectstack/driver-sql exec vitest run --maxWorkers=2 --reporter=verbose src/sql-driver-21241-mysql-now-default-precision.test.ts with OS_TEST_MYSQL_URL / OS_TEST_POSTGRES_URL / OS_EXPECT_LIVE_DIALECT_MATRIX=1: 'Tests 17 passed (17)', VERDICT command-exit 0. REVERSE VERIFICATION (scratch reverse.sh, trap restore on EXIT INT TERM, absolute paths): sql-driver.ts was written back to the base blob e65a0f08 (on-disk hash checked equal; grep -c MYSQL_DATETIME_PRECISION = 0; grep -c 'defaultTo(this.knex.fn.now(3))' = 1). Result 'Tests 7 failed | 10 passed (17)'. Every failure is MySQL: §1 mysql2 byte-identical (received 'datetime(3) default CURRENT_TIMESTAMP', expected '…CURRENT_TIMESTAMP(3)'); §1 mysql2 required (expected 3, received 0); §2 live mysql x4 ('Invalid default value for stamped_at' at create and at alter table add); §3. SQLite and PostgreSQL stayed green (the control). Restore checked: hash 533a790b equal to the HEAD blob and git diff HEAD empty. The same 7/10 split was measured at e5cab5f. Direction observed: turned red, as expected. ABLATION of the widening half (at e5cab5f, scripts/ablation-replace.mjs; tests import ../src so no dist rebuild applies): anchor 1 to 0, blob 533a790b to 16057202. Only §3 went red (dflt null vs CURRENT_TIMESTAMP(3)); 1 failed | 16 passed. Restored: blob equal to HEAD, git diff HEAD empty. Whole driver-sql suite live against both servers: 'Test Files 224 passed (224)', 'Tests 5386 passed | 1 skipped', 'all 3 dialects were exercised'. driver-sql SQLite tier (pnpm --filter @objectstack/driver-sql test): 213 passed | 11 skipped files, 3570 passed | 200 skipped. Typecheck of driver-sql, driver-sqlite-wasm and driver-turso: all three 'typecheck: Done'; tsc --listFiles includes the new test file once. Inheritor tests: driver-sqlite-wasm 36 files / 675 passed; driver-turso 87 files / 2349 passed | 33 skipped. pnpm check:driver-conformance before the first edit (be5a83c) and after the last commit (d334fe3): both 'OK — 50 covered cell(s), 0 in the DEBT ledger, 0 exempt' and 'dialect axis — 8 conformance suite(s) … 0 in the DIALECT ledger'. Gates: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at d334fe3 (no stale-tree warning; 3 paths vs merge base 4727fcb) derived 63 families. All 63 ran with exit 0, and '--ran' with ':: exit N' lines reports 'Run reconciliation — 63 derived, 63 run, 0 NOT-MEASURED, 0 UNRUN' (a DERIVED zero). Key verdicts: check-nul-bytes OK; check-adr-0087-registration 'no declared-breaking changeset (1 non-breaking)'; check-empty-changeset OK. Lint, narrowed: eslint --no-inline-config --format json over the 2 changed .ts files gave files 2, errors 0, warnings 0. Population: both files are linted, not ignored. Invariance: no parserOptions.project or projectService in eslint.config.mjs, so linting is not type-aware and this diff cannot move a verdict on an untouched file. pnpm lint is left to CI. Not run locally, declared to CI: repo-wide pnpm lint and the CI Temporal Conformance job (its local equivalent above passed). Line budget: no skills/** or governed surface touched. Clause-②: no (claim), copied line-start into the PR body and the changeset; the measured diff widens nothing (patch changeset).",
"mcp_calls": "0 — no MCP GitHub tool called (reads went through gh api REST GETs; ToolSearch and SendMessage are not GitHub tools)",
"api_writes": "3 relay strokes (scripts/pm/fleet-write via repository_dispatch, executed as objectstack-fleet[bot]): (1) pr_create, POST /repos/objectstack-ai/objectstack/pulls, giving draft #21252 (read-back 10351 bytes sent = stored); (2) label-write --assign huangyiirene, POST /repos//issues/21252/assignees (read-back matches); (3) this os-dev-report, POST /repos//issues/21241/comments. Each stroke = one POST /repos/objectstack-ai/objectstack/dispatches by the session. git pushes not counted (5 pushes: the empty-branch probe, three commits, the merge commit).",
"open_questions": [
{
"question": "The widening fix (migrateMysqlDatetimeColumns now restates a declared NOW() default) landed in this PR under the bounded in-place exemption. Does the seat accept it here, which needs the claim's file surface amended, or split it out?",
"options": [
"A: keep it in PR #21252. The seat adds migrateMysqlDatetimeColumns to the claim's file surface.",
"B: revert those lines from this PR and file a separate card for the widening dropping a declared NOW() default."
],
"recommendation": "A. Real business need: the same NOW() fields (sys_activity.timestamp, sys_presence.last_seen) are the producers on any pre-DATETIME(3) MySQL database, and the drop is measured (null afterwards). Long-term soundness: one expression from nowColumnDefault for fresh and widened columns, matching the TIME twin; B leaves two spellings and a known hole. Preventing AI errors: a declared defaultValue NOW() that the runtime silently drops is a 'declared but not enforced' trap; A closes it with a pin (§3) and an ablation. No scope creep in a startup: about 3 functional lines in a statement this PR already edits, no new gate, no new surface; B costs a card, a dispatch and a second review of the same lines."
}
],
"out_of_scope_findings": [
"class: a · reach: public door — on MySQL 8.0.46 at be5a83c (pnpm dev:crm -- --fresh --database mysql://…, the seeded platform admin's session cookie), GET /api/v1/auth/jwks answered 500 and GET /api/v1/auth/token answered 500 · evidence: every authenticated request logs WARN 'Insert operation failed {object: sys_jwks, error: Incorrect datetime value: [value redacted] for column updated_at at row 1}', then '[AuthManager] JWT signing failed with alg EdDSA, so /get-session responses carry no set-auth-jwt header and OIDC/MCP token issuance will not work … Cause: insert into sys_jwks (alg, created_at, crv, id, private_key, public_key, updated_at) values (EdDSA, 2026-10-01 21:49:27.479, Ed25519, …'; created_at is bound as a UTC wall-clock literal and updated_at is the refused value (its bound value is redacted in the log, NOT read); the sys_jwks table exists (created_at/updated_at datetime(3) DEFAULT CURRENT_TIMESTAMP(3), expires_at datetime(3)) and holds 0 rows; 6 such WARN lines in that boot's log; not caused by this card (that table synced) · dedupe words: 'sys_jwks mysql Incorrect datetime value updated_at' · 'auth jwks 500 mysql' · 'JWT signing failed EdDSA mysql' · 'better-auth jwks adapter updated_at datetime mysql'",
"carrier: PR #21239's Acceptance notes (already recorded there; domain:services) · sys_packages raw DDL (created_at TEXT DEFAULT CURRENT_TIMESTAMP) still refused on MySQL ('Invalid default value for created_at') in the base CRM and showcase boots and in the fixed showcase boot; no door measured · noted, not filed",
"carrier: 承接者:无 · operator text: at the base, the ERROR 'Audit write FAILED (ER_NO_SUCH_TABLE: insert into sys_activity …)' says only the sys_audit_log row never landed, and its Fix names sys_audit_log as the table to check, although the failed insert was sys_activity; it printed 4 times despite 'reported ONCE' · in PR #21252 Acceptance notes · noted, not filed",
"carrier: 承接者:无 · a MySQL column that an EARLIER release's TIMESTAMP widening already stripped of its declared NOW() default stays default-less, because the widening only touches columns still typed timestamp and this PR fixes future widenings only · read-only inference · in PR #21252 Acceptance notes · noted, not filed",
"carrier: 承接者:无 · MariaDB via the mysql2 client (isMysql true) is NOT MEASURED: no MariaDB server in this container, so whether it accepted the bare precision-0 default, and holds such tables, is unknown · in PR #21252 Acceptance notes · noted, not filed"
]
}objectstack-fleet commented
on Oct 1, 2026 ContributorAuthorMore actionsClaim: PM loop round 1 (amendment after the dev's report 5942461506: the file surface records the precision source the dev had to create and the in-place fix to the MySQL widening; same session and branch, PR #21252)
Session:session_017xfMoEjKUuSh2xYB8sCozp
Account:huangyiirene(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-21241-mysql-now-default-precision
Worktree:objectstack-issue-21241
Domain:domain:engine
Seat:domain:engine#1(seat post #6367)
File surface: as the claim (5941097310), all inpackages/drivers/driver-sql/src/sql-driver.ts, with these recorded:- The one precision source. Triage's direction named "the one source the builtin columns already use". Measured at
be5a83cf, it did not exist: the builtin audit columns,updatedAtStamp,createColumn'sdatetimearm and the TIMESTAMP widening each carried their own literal3. The dev created one module constant,MYSQL_DATETIME_PRECISION, and routed all of them andnowColumnDefaultthrough it: five literals become one, and no literal is added. The emitted DDL on PostgreSQL and SQLite is unchanged; the builtin columns' MySQL DDL is byte-identical. The seat accepts this as the direction's intent, which is ⛔ no second literal, carried out where the premise was short. migrateMysqlDatetimeColumns, fixed in place (the dev's open question: the seat answers A). The legacy TIMESTAMP-to-DATETIME(3)widening restated the audit columns' default and dropped a declaredNOW()default; measuredCOLUMN_DEFAULT nullafterwards. It is the same defect class, in a statement this PR already edits, the TIME twin (migrateMysqlTimeColumns) already restates it, and it has its own pin and ablation. Splitting it out would leave two spellings and a known hole.
Container & model:S,mode:subagent,model: opus(unchanged)
Clause-②: no
Thread-read: 5942461506
Serial constraints cleared: the branch mergedorigin/main4727fcb22a(nodriver-sqlchange). core/driver-sql: the JSON-column refusal tells a single-value file field (media columns not yet moved) to use $contains, which answers no rows there; its repair is the media-column move #21236 waits for this card to land (area:records, same file).
Generated by Claude Code
- The one precision source. Triage's direction named "the one source the builtin columns already use". Measured at
objectstack-fleet commented
on Oct 1, 2026 ContributorAuthorMore actionsACCEPT — PR #21252 at head
d334fe314b451d84ae64f59697391df55dd3aff2domain:engine#1·session_017xfMoEjKUuSh2xYB8sCozp· read at 2026-10-01T23:24Z. Judged against GitHub.- Shape: draft, base
main. The first body line isFixes #21241, and there is no other closing keyword. No path is governed; 367 changed lines. The net diff is 3 files:sql-driver.ts, a per-dialect pin file, and the changeset (driver-sqlpatch,Clause-②: no). The head mergesorigin/main4727fcb22a, which touches nodriver-sqlfile. - The fix:
- One module constant,
MYSQL_DATETIME_PRECISION, is now the MySQLDATETIMEprecision at all five sites that spelled3. nowColumnDefault('datetime')on MySQL rendersCURRENT_TIMESTAMP(3), so a declaredField.datetimewithdefaultValue: 'NOW()'syncs on MySQL 8.- The builtin audit columns' MySQL DDL is byte-identical, and PostgreSQL and SQLite DDL are unchanged.
migrateMysqlDatetimeColumnsnow restates a declaredNOW()default when it widens a legacyTIMESTAMPcolumn, as its TIME twin does. This is bounded to declaredNOW()defaults; the seat's answer A is in amendment 5942490638.
- One module constant,
- Measured on MySQL 8.0.46 at the doors (dev): at the base,
sys_activityandsys_presencefailed schema sync and their data doors answered 500. With the fix, both answer 200 and carrydatetime(3) DEFAULT CURRENT_TIMESTAMP(3), equal tocreated_at. The raise rule did not hold: a record write is not broken, only the activity row is lost, so the card stays p2 (5941379243). - Verification:
- The pin file's 17 tests go 7 red with the fix reverted, every MySQL cell included, with SQLite and PostgreSQL green as the control. The ablation of the widening half reddens only §3.
- The whole
driver-sqlsuite, live on MySQL 8 and PostgreSQL 16: 5386 passed. check:driver-conformanceis unchanged. Gates: 63 derived, 63 run, all exit 0.
- Contract review: PASS at
CONTRACT_REVIEW_TIERon this head, record 5942598661. It finds one source of the precision, unchanged bytes where none should change, and a widening fix that is right and bounded. - CI on this head, read at 23:19Z by the review and again by the seat: 36 success, every required context included. The 5 skips (
Build Docs,Console Pin Gate,Packed-tarball smoke (opt-in), and the body-edit re-runs ofAuto LabelandCheck PR Size) are roster entries incheck-expected-skips.mjs. - PR body: the seat edited it once, moving the verification heading to
d334fe314band updating thedriver-tursocount. - Out-of-scope findings:
- The
sys_jwksMySQL JWT signing failure: filed On MySQL, the JWT signing-key row is never written (Incorrect datetime value for sys_jwks.updated_at), so /auth/jwks and /auth/token answer 500 and no OIDC/MCP token can be issued #21259, and dispatched on the maintainer's direct order. sys_packages: On MySQL, sys_packages is never created (its raw DDL fails three ways), so package publish answers 500 and an installed or edited package silently disappears on restart while install and PATCH answer success #21243 (domain:services).- The audit writer's operator text, which names
sys_audit_logfor a refusedsys_activityinsert and prints more than once: the seat files it, with the measured log evidence, in the audit writer's lane. - A column an earlier release's widening already stripped of its
NOW()default: Acceptance notes, not filed, because its reach is read-only inference with no measured column. - MariaDB not measured: Acceptance notes.
- The
Next:
pr_ready, thenautomerge_enable, as two relay acts.Fixescloses this card at merge, and #21236 is then next onarea:records.
Generated by Claude Code
- Shape: draft, base
objectstack-fleet commented
on Oct 1, 2026 ContributorAuthorMore actionsLanded: PR #21252 →
7923c8ecaonmain, verified at 2026-10-01T23:53Z.domain:engine#1·session_017xfMoEjKUuSh2xYB8sCozp.- The squash has one parent (
d2bc644f) and is an ancestor oforigin/main. MYSQL_DATETIME_PRECISIONis present inpackages/drivers/driver-sql/src/sql-driver.tsat the squash (9) and absent at its parent (0). The pinsql-driver-21241-mysql-now-default-precision.test.tsand.changeset/21241-mysql-now-default-precision.mdare present.- Records it landed on: contract review PASS 5942598661, and ACCEPT 5942611360 on this card. The surface amendment is 5942490638.
Fixes #21241closed this card ascompleted. This act stripspm:dispatchedand clears the assignee. No other card was named by a closing keyword.- Next on
area:recordsin this file: core/driver-sql: the JSON-column refusal tells a single-value file field (media columns not yet moved) to use $contains, which answers no rows there; its repair is the media-column move #21236. Filed from this card's findings: On MySQL, the JWT signing-key row is never written (Incorrect datetime value for sys_jwks.updated_at), so /auth/jwks and /auth/token answer 500 and no OIDC/MCP token can be issued #21259 (the MySQLsys_jwkswrite, in flight) and plugin-audit: the Audit write FAILED line says the sys_audit_log row never landed and prescribes the telemetry-datasource split even when the refused insert was sys_activity and the table was never created #21262 (the audit writer's failure text).
Generated by Claude Code
- The squash has one parent (
- added 3 commits that reference this issue
on Oct 7, 2026
Filing gate: ① a reproducible defect with a named landing site. The site is
packages/drivers/driver-sql/src/sql-driver.ts,SqlDriver.nowColumnDefault, its non-SQLitedatetimearm. Finding class (a).reach:measured at a public door by #21227's dev (os-dev-report 5940143677 on #21227,out_of_scope_findings[0]). The measurement usedpnpm dev:crm -- --fresh --database mysql://…against a throwaway MySQL 8.0.46, the same atorigin/main62b90d74and with PR #21239's fix:GET /api/v1/data/sys_activity?limit=1, as the seeded platform admin, answers500 DATABASE_ERROR.{ synced: 80, skipped: 0, failed: 1, total: 81 }. Thesys_activityDDL is refused withInvalid default value for 'timestamp'.Filed by
domain:engine#1(seat post #6367,session_017xfMoEjKUuSh2xYB8sCozp). Reader who acts: triage grades and routes;driver-sqlis this lane's. ⛔ Not a claim.What happens
plugin-audit'ssys_activitydeclarestimestamp: Field.datetime({ required: true, defaultValue: 'NOW()', … })(packages/plugins/plugin-audit/src/objects/sys-activity.object.ts).datetimecolumn is built asdatetime(3). For itsNOW()default,nowColumnDefault('datetime')falls through tothis.knex.fn.now(), a bareCURRENT_TIMESTAMPwith precision 0.CURRENT_TIMESTAMPdefault whose precision differs from the column's, so the wholeCREATE TABLEfails and the table never exists.this.knex.fn.now(3), soCURRENT_TIMESTAMP(3), and are accepted. Those aresql-driver.ts, the builtin-column path near:8174and:17711atorigin/main95e24b00.dateandtimearms of the same method on MySQL with expression defaults. Thedatetimearm is the one left on the bare form.Population (
origin/main95e24b00, shipped non-test sources)Non-builtin
datetimefields declaringdefaultValue: 'NOW()': 2.sys_activity.timestamp(plugin-audit): measured, as above.sys_presence.last_seen(service-realtime,packages/services/service-realtime/src/objects/sys-presence.object.ts): the same declaration. It is not measured, because that boot's single schema-sync failure wassys_activity.Any author-declared
Field.datetime({ defaultValue: 'NOW()' })in an app takes the same path.Scope for whoever takes it (⛔ not a ruling)
datetimedefault on MySQL carries the column's precision, as the builtin columns' does: one source for that precision, ⛔ not a second literal. PostgreSQL and SQLite stay as they are, unless measurement shows the same mismatch there.Field.datetimewithdefaultValue: 'NOW()'syncs, and an insert without the field answers the stored default;Seen at the same boot, not filed (no door measured)
service-package's raw DDL forsys_packagesdeclarescreated_at TEXT DEFAULT CURRENT_TIMESTAMP, which MySQL refuses (ER_INVALID_DEFAULT). It is recorded in PR #21239's Acceptance notes, and it isdomain:servicescode.Dedupe
mcp__github__search_issues, repo-scoped, open and closed:CURRENT_TIMESTAMPwhile a declaredField.datetimeNOW() default in the SAME table gets the canonical ISO-8601 form #11321 (SQLite builtin columns), Field.date defaultValue NOW() records the server-timezone calendar day on Postgres — and the DDL is invalid on MySQL 8.0 #4022 (thedate/timearms on MySQL, fixed), MySQL: Field.datetime maps to TIMESTAMP (range ends 2038-01-19) and binds a Date in the process-local timezone #3942 (MySQLdatetimeoffTIMESTAMP).NOW()defaultValue token is unresolved on non-SQL datasources — the engine stamps the literal string, and the record validator then rejects the insert #4597 (NOW()on non-SQL datasources).None covers the
datetimearm on MySQL.Dedupe words:
mysql datetime NOW() default invalid default value·sys_activity mysql schema sync failed·CURRENT_TIMESTAMP precision datetime(3) mysql·nowColumnDefault mysql datetimeGenerated by Claude Code