@oimlsmart/platform-server 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oimlsmart/platform-server",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "The OIML SMART platform server kernel: the store seam (ServerStore + the D1 and SQLite implementations), the canonical D1 migration set both deployments apply, the instance profile, the mailer, the RBAC map, the OIDC/OAuth client cones, and the shared role/permission vocabulary. Consumed by the smart monorepo (browser/) and the identity service.",
5
5
  "type": "module",
6
6
  "repository": {
package/src/store/d1.ts CHANGED
@@ -3664,14 +3664,20 @@ export class D1ServerStore implements ServerStore {
3664
3664
  async workflowStoreRowCeiling(): Promise<number> {
3665
3665
  await this.ensureInstrumentRegistrationSupport()
3666
3666
  await this.ensureNotifyDeliverySupport()
3667
+ // NEVER a compound SELECT here: D1 caps a compound's term count at
3668
+ // 5 (stock SQLite allows 500 — measured on the live fleet
3669
+ // 2026-09-04: five terms answer, six fail with "too many terms in
3670
+ // compound SELECT"). The six-table UNION ALL form this replaces
3671
+ // crossed that cap the night the demo hub's redeploy brought it
3672
+ // (the 2026-09-03/04 demo-reset reds: the reset phase's FIRST read
3673
+ // died, slice 1 answered 400, the wipe never started). The scalar
3674
+ // max() over per-table scalar subqueries keeps ONE round-trip with
3675
+ // a term count of one, and the table list derives from WIPE_TABLES
3676
+ // — a wipe-set addition can never again grow the statement past
3677
+ // the cap by hand. COALESCE keeps an empty table at 0 (the scalar
3678
+ // max() answers NULL on ANY NULL argument).
3667
3679
  const row = await this.stmt(
3668
- `SELECT MAX(ceiling) AS ceiling FROM (
3669
- SELECT MAX(rowid) AS ceiling FROM entity_changes
3670
- UNION ALL SELECT MAX(rowid) FROM evidence_records
3671
- UNION ALL SELECT MAX(rowid) FROM entities
3672
- UNION ALL SELECT MAX(rowid) FROM events
3673
- UNION ALL SELECT MAX(rowid) FROM notify_deliveries
3674
- UNION ALL SELECT MAX(rowid) FROM instrument_registrations)`,
3680
+ `SELECT MAX(${WIPE_TABLES.map(t => `COALESCE((SELECT MAX(rowid) FROM ${t}), 0)`).join(', ')}) AS ceiling`,
3675
3681
  ).first<{ ceiling: number | null }>()
3676
3682
  return row?.ceiling ?? 0
3677
3683
  }
@@ -1111,14 +1111,13 @@ export function createSqliteServerStore(): ServerStore {
1111
1111
  return rows
1112
1112
  },
1113
1113
  async workflowStoreRowCeiling(): Promise<number> {
1114
+ // The D1 half's twin (one rule, two backends): the scalar max()
1115
+ // over per-table scalar subqueries, NEVER a compound SELECT — D1
1116
+ // caps a compound's term count at 5 (the 2026-09 demo-reset
1117
+ // wall), and the table list derives from WIPE_TABLES so the
1118
+ // wipe set and the ceiling set never drift apart by hand.
1114
1119
  const row = getDb().prepare(
1115
- `SELECT MAX(ceiling) AS ceiling FROM (
1116
- SELECT MAX(rowid) AS ceiling FROM entity_changes
1117
- UNION ALL SELECT MAX(rowid) FROM evidence_records
1118
- UNION ALL SELECT MAX(rowid) FROM entities
1119
- UNION ALL SELECT MAX(rowid) FROM events
1120
- UNION ALL SELECT MAX(rowid) FROM notify_deliveries
1121
- UNION ALL SELECT MAX(rowid) FROM instrument_registrations)`,
1120
+ `SELECT MAX(${WIPE_TABLES.map(t => `COALESCE((SELECT MAX(rowid) FROM ${t}), 0)`).join(', ')}) AS ceiling`,
1122
1121
  ).get() as { ceiling: number | null }
1123
1122
  return row.ceiling ?? 0
1124
1123
  },
package/src/store.ts CHANGED
@@ -2333,7 +2333,10 @@ export interface ServerStore {
2333
2333
  wipeWorkflowStores(range?: { after: number; through: number }): Promise<number>
2334
2334
  /** The rowid ceiling across the wiped tables — the reset phase's
2335
2335
  * round planning (rounds = ceil(ceiling / chunk)). 0 on empty
2336
- * stores. */
2336
+ * stores. One statement, NEVER a compound SELECT: D1 caps a
2337
+ * compound's terms at 5 (the 2026-09 demo-reset wall), so the
2338
+ * implementations read per-table scalar subqueries under the scalar
2339
+ * max(), derived from the wipe's own table set. */
2337
2340
  workflowStoreRowCeiling(): Promise<number>
2338
2341
  countEntities(): Promise<number>
2339
2342
  }