Repository navigation
Commit 8692a08
fix(cloud-connection)!: the marketplace reseed door converts the ledger body forward once, as install and rehydrate do (#24169)
Fixes #24040
Clause-②: no (narrowing)
The marketplace `reseed-sample-data` door now converts the ledger body
forward once, through the one entry point the install and the rehydrate
use, before its side effects read it. It reloads the translations those
two doors load, and no longer a retired shape they strip.
**BREAKING** (a served-set narrowing), shipped as `minor` under the
launch-window convention. Disposition in the changeset: ADR-0087
`not-required (already-registered …)`, naming the four translation
conversions.
## Premise check, on `origin/main` (base `7cda377c1`, merged up to
`697301491`)
- **Assumption 1 holds.** `handleReseed` called
`this.applySideEffects(ctx, entry.manifest, { seedNow: true, c, door:
'reseed' })` with the raw ledger body. Install (`:1572` / `:1651`) and
rehydrate (`:783` / `:806`) hand `applySideEffects` the body converted
through `convertPackageBodyForward` (PR #24028).
- **Assumption 2 holds, measured.** The new pin, run against the unfixed
door, went red with the i18n service receiving `+ "settings": { "mail":
… }` beside `apps`. The reseed loaded the per-app `settings` group that
install and rehydrate strip. A census of the 142 entries in
`ALL_CONVERSIONS` (each entry's own fixture, before against after, with
every entry touching `translations`, `data`, `i18n`, `engines`, jobs,
hooks or mappings then replayed through the real
`ObjectQL.convertPackageBodyForward` at floor 17.0.0) finds four that
rewrite `translations`, all replayed at this door:
`translation-per-app-settings-removed` (the one the pin exercises),
`translation-validation-messages-removed`,
`translation-component-submit-label-removed` and
`translation-widget-sub-caption-removed`. None touches `data`, `i18n` or
`engines`.
- **Assumption 3: the two other doors answer a converter throw
differently, each by its own existing failure path.** Measured with an
injected throwing converter:
- **install:** the handler rejects (the host renders the error), nothing
is registered and no ledger entry is written;
- **rehydrate:** the per-entry catch logs `rehydrate failed for ID` at
`error` with the thrown error attached, the entry is not loaded, and the
boot continues.
- The reseed is an HTTP door like the install, so it now does what the
install does: the conversion call is not wrapped, the throw propagates,
and nothing is loaded. Before, it answered and reloaded the raw body. No
new answer is invented, and the install/rehydrate difference is reported
here, not changed.
- Can a real body throw? The engine's converter is documented as never
throwing, but it can. A body whose top-level range is admitted
(`>=17.0.0`) while a nested `manifest.engines.protocol` is a number
passes the D1 handshake (which reads the top level) and throws
`TypeError … trim is not a function` in the converter (which reads the
nested `manifest` first). A non-string top-level range throws at the D1
handshake first, at every door. The install never writes the first shape
to the ledger, because it throws before the ledger write.
## Change
`packages/cloud-connection/src/marketplace-install-local-plugin.ts`,
`handleReseed` only:
- After `refuseProtocolIncompatibleEntry` (unchanged, still FIRST, still
judging the entry as stored), the door calls the plugin's existing
`convertPackageBodyForward(ctx, entry.manifest)` once and hands the
result to `applySideEffects`.
- The ledger keeps the body as installed. The entry written back for
`withSampleData` still carries its raw `manifest`, and the pin asserts
the `settings` group is still in the ledger after the reseed.
- `convertPackageBodyForward`, the install and rehydrate doors, the
conversion registry and every other reader are untouched.
## Pin: `marketplace-install-local-reseed-convert-forward.test.ts`
The pin goes through the real reseed route, with a real `ObjectQL`
engine's `convertPackageBodyForward` (counted at the seam), a recording
i18n service and a recording `runInlineSeed`:
- **declared body** (`>=17.0.0`, translations carrying a per-app
`settings` group beside `apps`): `200`, i18n receives `zh-CN` with
`apps` only, the seed run gets the declared `data` unchanged, the
converter runs exactly once and the named conversion warning prints
once, and the ledger still holds `settings`;
- **CONTROL, range-less body:** `200`, the converter hands the body back
by reference, no warning, and i18n receives `settings` and `apps` as
declared;
- **D1 first:** an entry declaring `^17.0.0` is answered `422
OS_PROTOCOL_INCOMPATIBLE` with the converter never called and nothing
loaded or seeded.
### Ablation (once, `scripts/ablation-replace.mjs` under a shell trap)
- Mutation: the one call reverted to `this.applySideEffects(ctx,
entry.manifest, …)`. Anchor x1 to x0, blob `86ebbc183687` to
`3b914c584c12`.
- Mutant leg: 1 red (the declared-body case, i18n received `+
"settings"`), 2 green (CONTROL, D1 first).
- Restore leg: blob after restore equals HEAD (`86ebbc183687`), and `git
diff HEAD` is empty. The pin imports the plugin from `src/`, so no
`dist/` leg applies.
## Acceptance 3: the other body readers in this file
| line | reader | reads | verdict |
|---|---|---|---|
| `:766` | rehydrate `checkProtocolCompat(entry.manifest)` | `engines` /
`engine` | judged as stored by ruling; no conversion touches it |
| `:2786` | `refuseProtocolIncompatibleEntry` (reseed, purge) |
`engines` / `engine` | same |
| `:1884` | `sampleDataInScope` (listing `withSampleData`),
`seedDatasetsOf(entry.manifest)` | `data` | no conversion touches `data`
|
| `:2693` | `handlePurge`, `seedDatasetsOf(entry.manifest)` | `data` |
same |
| `:1435` | install `unrunnableCode(ctx, manifest, …)` (raw install
body, before `:1572`) | jobs `enabled`/`pull`/`body`/`handler`/`name`,
mappings `name`/`connectorSource`, hooks `body`
presence/`name`/`handler` | disjoint: job conversions touch `id`,
`timeout`, `retryPolicy`; mapping conversions touch
`extractQuery`/`errorPolicy`/`batchSize` and `fieldMapping[].params`;
hook conversions touch `timeout` and `body.capabilities` (not `body`
presence). No verdict changes. |
`:783`, `:1572` and `:2564` are the three conversion calls; `:2565` is
the reseed's `applySideEffects` call this PR moves off the raw body.
## Verification, on head `e601aad52` (after merging `origin/main` at
`697301491`)
- `@objectstack/cloud-connection`: `pnpm test`, 49 files / 598 tests
passed. `pnpm typecheck` exit 0. `tsc --listFiles` puts the new test in
both programs (count 1 each).
- `test:repo`: core 6 files / 84 tests (exit 0), objectql 1 / 5, types 1
/ 11, rest 5 files / 254 passed, 12 skipped, runtime 3 / 808, all exit 0
on `e601aad52`. spec ran 66 files / 1105 tests, exit 0, on `dcb51cd45`.
The merge after it touched no `packages/spec` path and none of this PR's
files.
- `eslint --no-inline-config` on both changed `.ts` files: exit 0.
- `dispatch-gates --commands --repo objectstack-ai/objectstack` on
`e601aad52`: 64 derived, 63 exit 0, and 1 NOT MEASURED: `pnpm
check:dual-build-cjs-loads` exit 3, `PREREQUISITE NOT MET` (it needs
every package's `dist/`; CI runs it). `--ran` exit 0: 64 accounted, 63
run, 1 NOT-MEASURED derived from the recorded code.
- `check-adr-0087-registration` exit 0 (`not-required
(already-registered)`), and `check-changeset-no-major` exit 0.
## Clause-② judgement
`no (narrowing)`, not the claim's bare `no`. No accept set widens. The
reseed now serves less (a retired translation group no longer reloads
into i18n on reseed), and it now raises on a body whose conversion
throws, where it answered before. Both are the dispatch's stated
narrowing tests. A `CONTRACT_REVIEW_TIER` review is owed.
## Patch round 1 (`ec9f15c6b`, comment only)
- The JSDoc on `convertPackageBodyForward` said "this plugin's two loads
of a ledger body — the install and the rehydrate". This PR makes the
reseed a third load, so the block now names three loads, and says the
reseed hands only `applySideEffects` because it neither registers nor
binds. The seat widened the claim's hold-off by that JSDoc block for
this fix. No code moved.
## Acceptance notes (not fixed here)
- The install's ADR-0120 D5e gate (`:1522`,
`collectGlobalUniques(manifest.objects)`) reads the raw install body,
while `declared-index-unique-scope` rewrites `indexes[].unique: true` to
`'global'`. The gate treats both spellings as global with the same
finding id, so the verdict is unchanged; only the `spelling` field in
the refusal's details reads `true`. This is an observation, not a
defect.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01BVm1pAXVXQ3PjC42j1kPFf)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent bd4276a commit 8692a08
3 files changed
Lines changed: 269 additions & 15 deletions
File tree
- .changeset
- packages/cloud-connection/src
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2525 | 2525 | | |
2526 | 2526 | | |
2527 | 2527 | | |
| 2528 | + | |
| 2529 | + | |
| 2530 | + | |
| 2531 | + | |
| 2532 | + | |
| 2533 | + | |
2528 | 2534 | | |
2529 | 2535 | | |
2530 | 2536 | | |
| |||
2548 | 2554 | | |
2549 | 2555 | | |
2550 | 2556 | | |
2551 | | - | |
| 2557 | + | |
| 2558 | + | |
| 2559 | + | |
| 2560 | + | |
| 2561 | + | |
| 2562 | + | |
| 2563 | + | |
| 2564 | + | |
| 2565 | + | |
2552 | 2566 | | |
2553 | 2567 | | |
2554 | 2568 | | |
| |||
2779 | 2793 | | |
2780 | 2794 | | |
2781 | 2795 | | |
2782 | | - | |
2783 | | - | |
2784 | | - | |
2785 | | - | |
2786 | | - | |
2787 | | - | |
2788 | | - | |
2789 | | - | |
2790 | | - | |
2791 | | - | |
2792 | | - | |
2793 | | - | |
2794 | | - | |
2795 | | - | |
| 2796 | + | |
| 2797 | + | |
| 2798 | + | |
| 2799 | + | |
| 2800 | + | |
| 2801 | + | |
| 2802 | + | |
| 2803 | + | |
| 2804 | + | |
| 2805 | + | |
| 2806 | + | |
| 2807 | + | |
| 2808 | + | |
| 2809 | + | |
| 2810 | + | |
| 2811 | + | |
| 2812 | + | |
2796 | 2813 | | |
2797 | 2814 | | |
2798 | 2815 | | |
| |||
| 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 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
0 commit comments