Repository navigation
Commit db9c02a
fix(objectql): a federated object whose datasource the connect policy denied is reported at info, not in the wrong-table ERROR (#25117)
Fixes #25079
Clause-②: no (log text and level only: no response, status, outcome,
boot verdict or export moves)
Metadata-protocol: none (a boot log line's level and text; nothing a
metadata author writes changes)
## What changed
`ObjectQLPlugin.reconcileFederatedBindings`
(`packages/objectql/src/plugin.ts`, the report only) reads the
datasource layer's recorded verdict back through the engine
(`this.ql.listUnavailableDatasources()`). An unbound federated object
whose datasource is recorded as `kind: 'blocked'`, meaning the connect
policy denied it on purpose, is now reported in ONE `info` line. The
line names the objects and their datasource, and says every read against
them is refused with `DatasourceUnavailableError` until the policy
allows that datasource. Those objects are no longer counted in the
ERROR.
Unchanged, at `error`, word for word, on every composition:
- an undeclared datasource (no recorded verdict);
- a FAILED connect (`kind: 'failed'`);
- a driver without `registerExternalObject`;
- a registration that threw.
On a boot with both, the info line covers the denied objects and the
ERROR covers the rest, with its counts excluding the denied ones. No
binding, connect policy, read result or export changes. The #9285
registry-read seam is untouched.
## Why
On the stock showcase, `os migrate apply --yes` denies
`showcase_external` (`schemaMode: 'external'`) on purpose, under the
CLI's managed-only policy. The reconciliation then printed an ERROR
saying the federated objects "keep their REST routes and keep rendering
in the UI, while every read … resolves to a table named after the
OBJECT". For a policy-denied datasource that consequence is false on
EVERY composition, because the engine refuses those reads with
`DatasourceUnavailableError` (`engine.ts`, the `unavailableDatasources`
branch of `getDriver`). Under the AGENTS.md degradation-log-level rule,
a deliberate denial whose reads refuse loudly is a functional
degradation: `info`, and named rather than silent, which keeps #7737's
ruling.
The scope is the seat's re-declaration 6315166970, option C of the dev's
`needs_decision` 6314587078. The composition clause of claim 6314457843
is dropped, because no faithful "serves nothing" signal exists: "no
`http.server`" misreads the documented `createHonoApp({ kernel })`
embed. The condition is the recorded verdict alone, so no new signal is
read and nothing outside `packages/objectql` changes.
## Pins
New file
`packages/objectql/src/federated-binding-policy-denied-report.test.ts`,
11 cases:
- `blocked`: exactly one info line naming the denial, the datasource and
both objects, and zero ERROR, on a serving-shaped and a migrate-shaped
context alike;
- controls, each on both shapes, keep exactly one ERROR with the
unchanged counts and no info line: undeclared, `failed`, unsupported
driver, registration threw;
- mixed boot: info for the denied object only, and an ERROR reading `2
federated …` covering the undeclared and failed ones, excluding the
denied one.
`packages/runtime/src/federated-boot-binding.test.ts` (`domain:cli`) is
NOT moved and stays green: its datasource is undeclared.
## Verification record
Base `2e242bb0a9` for the census; built on `ba244f1b4`, then merged
`origin/main` twice. The final head is `b9f2cfec1` (merge base
`f2b6cf230`).
- **Ablation** (`scripts/ablation-replace.mjs`,
`(blocked.has(datasource) ? denied : unbound).push(` replaced by
`unbound.push(`): anchor 1 → 0, blob `aea19b4003ed` → `45e012d1ed12`.
Result: 3 failed | 8 passed (11). The two `blocked` cases and the mixed
case went red; all 8 controls stayed green. Restored: blob == HEAD
(`aea19b4003ed`) and `git diff HEAD` empty. The test imports
`./plugin.js` from source, so no dist leg is involved.
- **objectql:** typecheck exit 0 (the `tsconfig.test.json` program lists
the new file; `check:test-typecheck` OK, no new debt). Full suite at
`55a4c8b9f`, after the merge that brought #25086's objectql change:
459/459 files, 8631/8631 tests. The earlier run at `5cf4a4529` was
459/459, 8621/8621.
- **runtime:** full suite 432/432 files, 6794 passed and 19 skipped, at
`5cf4a4529` against an `objectql/dist` carrying this change. The diff
touches no runtime file. Of the two merges, only #25086 (objectql
`engine.ts`, strict read-only writes) moved a package in runtime's
closure, and objectql's own suite was rerun after it.
- **core `test:repo`:** 6/6 files, 82/82 tests.
- **Gates:** `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` (no paths) derived 67 lines. Every line ran,
each exit code captured before any pipe. At the final head `b9f2cfec1`:
67/67 exit 0, and `--ran` reported `67 derived famil(ies) accounted for
— 67 run, 0 NOT-MEASURED (a DERIVED zero — all 67 recorded an exit code
and none of them is 3)`. The same held at `55a4c8b9f`. An earlier pass
at `5cf4a4529` had three non-zero lines, none a gate verdict:
`check:dual-build-cjs-loads` exit 3 (no full build yet), and
`check:query-options-erasure` / `check:type-check-debt` exit 124 (my own
240 s per-command cap). All three exit 0 after the full build. Full
build `pnpm exec turbo run build --concurrency=2`: 77/77 at both merged
heads.
- **Live, stock `examples/app-showcase`, fresh file DB, same tree:**
- before (the routing line ablated, objectql rebuilt): `os migrate apply
--yes` exit 0, then `INFO datasource 'showcase_external': connect denied
by policy (…)`, then `ERROR 2 federated (external) object(s) are NOT
bound to their remote table, yet stay registered and served: they keep
their REST routes and keep rendering in the UI, …`;
- after: exit 0, the same denial line, then `INFO 2 federated (external)
object(s) left unbound because the connect policy denied their
datasource: showcase_ext_customer -> datasource 'showcase_external',
showcase_ext_order -> datasource 'showcase_external'. Every read against
them is refused (DatasourceUnavailableError) …`, and 0 ` ERROR ` lines;
70 tables created. The after-run was repeated once objectql's dist was
rebuilt from the restored source: same result.
## Acceptance notes
- The `Metadata-protocol:` line follows #25114, which landed after the
claim; its value is `none`, so the level stays `patch`.
- Not built, per the claim: the connection policy and its info line, the
binding logic, the CLI's migrate composition, #25031, #24956.
---
_Generated by [Claude
Code](https://claude.ai/code/session_016cxs5HWHRyhQhA9EaXmnWy)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent edcc8ce commit db9c02a
3 files changed
Lines changed: 258 additions & 1 deletion
File tree
- .changeset
- packages/objectql/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1831 | 1831 | | |
1832 | 1832 | | |
1833 | 1833 | | |
| 1834 | + | |
| 1835 | + | |
| 1836 | + | |
| 1837 | + | |
1834 | 1838 | | |
1835 | 1839 | | |
1836 | 1840 | | |
| |||
1871 | 1875 | | |
1872 | 1876 | | |
1873 | 1877 | | |
| 1878 | + | |
1874 | 1879 | | |
1875 | 1880 | | |
1876 | 1881 | | |
1877 | 1882 | | |
| 1883 | + | |
| 1884 | + | |
| 1885 | + | |
| 1886 | + | |
| 1887 | + | |
| 1888 | + | |
| 1889 | + | |
| 1890 | + | |
1878 | 1891 | | |
1879 | 1892 | | |
1880 | 1893 | | |
1881 | 1894 | | |
1882 | | - | |
| 1895 | + | |
| 1896 | + | |
1883 | 1897 | | |
1884 | 1898 | | |
1885 | 1899 | | |
| |||
1894 | 1908 | | |
1895 | 1909 | | |
1896 | 1910 | | |
| 1911 | + | |
| 1912 | + | |
| 1913 | + | |
| 1914 | + | |
| 1915 | + | |
| 1916 | + | |
| 1917 | + | |
| 1918 | + | |
| 1919 | + | |
| 1920 | + | |
| 1921 | + | |
| 1922 | + | |
| 1923 | + | |
| 1924 | + | |
| 1925 | + | |
1897 | 1926 | | |
1898 | 1927 | | |
1899 | 1928 | | |
| |||
0 commit comments