|
| 1 | +--- |
| 2 | +'@objectstack/spec': patch |
| 3 | +'@objectstack/cli': patch |
| 4 | +--- |
| 5 | + |
| 6 | +The liveness gate now governs every registered metadata type (#4487) |
| 7 | + |
| 8 | +`GOVERNED` in `check-liveness.mts` was a hand-maintained list, and nothing ever |
| 9 | +compared it against the registry it claims to cover. It governed **15 of 25** |
| 10 | +registered metadata types while reporting itself complete. A type in the other |
| 11 | +ten was authorable — served by `/api/v1/meta/types/:type`, editable in Studio — |
| 12 | +and was never asked who reads its properties, so an inert key on it was |
| 13 | +invisible to CI and its silence read as success. |
| 14 | + |
| 15 | +`datasource` was in that state for its entire life. #4410, #4465 and #4481 found |
| 16 | +six inert keys on it **by hand**, two of them security-shaped: `schemaMode` was |
| 17 | +dropped between the record and the connection spec, so a database ObjectStack |
| 18 | +must never run DDL against was constructed as `managed`; `ssl` stopped at the |
| 19 | +record, so a TLS block with a CA certificate in it configured nothing while |
| 20 | +looking identical to one that worked. |
| 21 | + |
| 22 | +**The gate is now answerable to the registry.** Every registered type must be in |
| 23 | +`GOVERNED` or in `PENDING_GOVERNANCE` with a reason and an issue. Registering a |
| 24 | +type and forgetting the ledger fails CI with the entry to write. The reverse rots |
| 25 | +too, so it also fails: a `PENDING_GOVERNANCE` row for a type that has since been |
| 26 | +governed claims a debt that no longer exists. |
| 27 | + |
| 28 | +**`datasource` is now governed** — `liveness/datasource.json`, all 43 properties |
| 29 | +classified with evidence. The result is the highest dead ratio of any governed |
| 30 | +type: **20 of 43 have no runtime consumer.** |
| 31 | + |
| 32 | +| Dead cluster | Why | |
| 33 | +| --- | --- | |
| 34 | +| `capabilities.*` (11) | The engine gates pushdown on the runtime driver's own `supports.*` object — `autonumber`, `batchSchemaSync`, `queryDateGranularity` — a different mechanism whose vocabulary does not overlap this block at all. `having-filter.ts` says it outright: "SQL pushdown can come later behind a driver capability flag." | |
| 35 | +| `healthCheck.*` (3) | Nothing schedules a datasource probe. Liveness is checked on demand through the driver handle's `ping()`. | |
| 36 | +| `retryPolicy.*` (4) | No connect or query path retries. | |
| 37 | +| `external.label`, `external.requirePermission` | No reader. | |
| 38 | + |
| 39 | +**One correction ships with this**, and it is the reason the audit was worth |
| 40 | +doing rather than a bookkeeping exercise. `capabilities.readOnly` reads as a |
| 41 | +safety switch and gates nothing — and **two shipped prescriptions pointed |
| 42 | +authors at it**: the `externalSettingsUnknownKeyError` guidance in |
| 43 | +`datasource.zod.ts` ("or `capabilities.readOnly` to describe the driver") and |
| 44 | +the #4465 changeset's relocation table. Both now name `external.allowWrites: |
| 45 | +false`, which is the write gate the ObjectQL engine actually checks. An author |
| 46 | +who followed the old advice believed they had marked a datasource non-writable |
| 47 | +and had not. The v17 release notes carried a matching false claim — that an |
| 48 | +unregistered `capabilities` key made the engine stop pushing work down to the |
| 49 | +driver — corrected in the same change. |
| 50 | + |
| 51 | +Two traps worth naming, because both nearly produced a wrong verdict here: |
| 52 | + |
| 53 | +- **`healthCheck` and `retryPolicy` are name collisions.** A bare grep for |
| 54 | + either returns plenty of live readers — the plugin health monitor, `hook`, |
| 55 | + `job` — none of which is this type. `hook.retryPolicy` even spells its delay |
| 56 | + `backoffMs` where this declares `baseDelayMs`; the shape mismatch is the tell |
| 57 | + that nothing reads both. |
| 58 | +- **objectui's `DatasourcePreview` renders `pool`, `ssl`, `retryPolicy` and |
| 59 | + `healthCheck` as panels**, and is cited as evidence for none of them. That is |
| 60 | + the standing rule in `liveness/README.md`, and #4481 is the fresh precedent: |
| 61 | + the only "consumer" of `readReplicas` in either repo was a preview pill. |
| 62 | + |
| 63 | +The CLI advisory lint picks the ledger up automatically, so `os compile` now |
| 64 | +warns an author who sets any of the 20. That needed one line beyond the ledger — |
| 65 | +`datasource` had to be added to `TYPE_COLLECTIONS`. Coverage grows by marking |
| 66 | +entries `authorWarn` only *within* a type the lint already walks; a newly |
| 67 | +governed type needs its collection registered or its ledger warns nobody. |
| 68 | + |
| 69 | +Nine types remain ungoverned and are now enumerated rather than implied: |
| 70 | +`app`, `book`, `doc`, `email_template`, `job`, `mapping`, `seed`, `translation`, |
| 71 | +`validation` (#4488). |
0 commit comments