Repository navigation
Commit 74fd4bf
fix(cloud-connection): unmanaged install-local writes the log line its fallback names, at any status (#29857)
<!-- claude-projects-attribution: {"github_login":"os-warren"} -->
_Requested by **Warren** · [project
thread](https://claude.ai/code/project/chan_01U5RdnAAmkSQmZbqh6FtqZ8?thread=cmsg_01U5RdnAAmkSQmZbqh6FtqZ8Bjniy1KUKzykb69Rgkafke)_
Fixes #29822
Clause-②: no
Metadata-protocol: none
## 维护者速读
- 改了什么:`POST /api/v1/marketplace/install-local` 的 unmanaged
分支,导入被拒时,只要回答用的是兜底句「the reason is in the server log」,就写那条 `warn` 日志,不再只在
5xx 时写;能原样带回原因的拒绝不写。状态码、错误码、响应形状都不变。
- 为什么改:用 `statusCode` 或校验形状(无数字 `status`)声明 4xx
的拒绝,消息不会回给客户端,回答却让运维去看日志,而日志里什么都没有(#29342 的 dev 经 HTTP 门实测:400、无日志)。
- 风险与回滚:只多写一条 `warn`,不改任何对外字段;回滚即还原一个 commit。
- 先看:`packages/cloud-connection/src/marketplace-install-local-plugin.ts`
的 unmanaged catch(`message === fallback` 那一行),其次
`marketplace-install-local-install-modes.test.ts` 新增的三个用例。
- 两分钟验证:`pnpm --filter @objectstack/cloud-connection exec vitest run
--maxWorkers=2 src/marketplace-install-local-install-modes.test.ts`,预期
26/26 通过。
- 需要你做的:无,席位落地。
## What changes
The unmanaged branch of `POST /api/v1/marketplace/install-local` catches
the import's throw and answers `clientFacingFailureText(err, fallback)`,
where the fallback says "the reason is in the server log". It used to
write that log line only when the throw resolved to 5xx.
`clientFacingFailureText` quotes a message only when the throw declared
a numeric 4xx `status`, so a 4xx this door resolves through `statusCode`
or the validation shape got the fallback and no log line.
Now there is one rule at every status: the door computes the answer
first, and writes the `warn` line exactly when the answer is the
fallback sentence. The fallback sentence is spelled once. The log line
also names the resolved status and code. A refusal whose reason reaches
the body writes no line, as before.
## Why
The operator who moves a package between environments with `os package
install --unmanaged` or the Console was told where the reason is, and
the reason was not there.
## Tests
`packages/cloud-connection/src/marketplace-install-local-install-modes.test.ts`,
beside the existing 5xx case:
- Two cases, a 4xx declared by `statusCode: 409` and one declared by the
validation shape: the body carries the reason, or the `warn` log carries
the import's message.
- One control: a refusal with a numeric 409 `status` is quoted in the
body and writes no log line.
Ablation (fix committed first at 4ac6248, mutation through
`scripts/ablation-replace.mjs`, `if (message === fallback) {` back to
`if (resolved.status >= 500) {`, anchor 1 → 0, blob `ec8cba1e` →
`1a44e3bf`): both 4xx cases go red (`expected '[MarketplaceInstallLocal]
[protocol] …' to contain 'Record is locked by approval apv_7'`, and the
same for the validation sentence), 2 failed / 24 passed. Restored: `git
diff HEAD` empty, blob back to `ec8cba1e` = the HEAD blob. The test
imports the plugin from `src` by a relative path, so no `dist/` leg is
involved.
## Acceptance notes
How the other doors that use a "reason is in the server log" fallback
pair it with a log line, read on `origin/main` 42ff86f:
- `protocol.ts` `migrateStoredMetadata` and the publish side-effects
collector, `protocol-publish-backfill.ts`, and
`runtime/src/domains/packages.ts` `applyPublishedSeeds` log
unconditionally beside the fallback, at any status.
- Batch rows (`toRowApiError` → `clientFacingRowFailureText`) and the
external-driver read floor (`external-driver-floor.ts` `readRefusal`)
log at the point they withhold, which is the rule this PR applies.
- `seed-loader.ts` logs the cause beside each withheld row through its
`seedCauseLabel` lines.
- `packagePersistFailureError` always answers 5xx, so the boundary logs
it.
No exported helper couples "fallback text ⇔ log line" today. The
batch-row one is private to `metadata-protocol`, so this door applies
the rule inline. No other door showed the same 4xx gap.
## Verification
All local readings are on head `4ac62487` (the only commit).
<details><summary>Package test, typecheck, lint</summary>
- `pnpm --filter @objectstack/cloud-connection test` :: exit 0 — Test
Files 68 passed (68), Tests 823 passed (823)
- `pnpm --filter @objectstack/cloud-connection typecheck` (`tsc
--noEmit` and `tsconfig.test.json`) :: exit 0
- `pnpm lint` (`eslint . --no-inline-config`, whole repo) :: exit 0
- The pin file alone: 26 passed (26); ablated: 2 failed, 24 passed.
</details>
<details><summary>Derived gates (dispatch-gates --commands, reconciled
with --ran)</summary>
`dispatch-gates --ran`: 59 derived families accounted for, 57 run with
exit 0, 2 NOT MEASURED (exit 3, prerequisite not met), 0 unrun.
- `node scripts/check-plugin-teardown-shape.mjs --self-test`: NOT
MEASURED, its positive control is pinned to a commit outside this
shallow clone. CI runs it.
- `pnpm check:dual-build-cjs-loads`: NOT MEASURED, it reads every
package's `dist/` and only the cloud-connection closure was built here.
CI runs it.
</details>
## Human Minimum
- [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic.
- [x] 2. Every name I added uses the casing for its kind.
- [x] 3. No formatter ran; `pnpm lint` passes.
- [x] 4. One issue, one branch off an up-to-date `main`, one pull
request.
- [x] 5. A change that publishes carries a changeset, and both
declaration lines are filled in here and in the changeset.
- [x] 6. `packages/spec` touched: its generated artifacts are
regenerated and committed. (not touched)
- [x] 7. No hand edits to `content/docs/references/`,
`packages/*/CHANGELOG.md` or `content/docs/releases/`.
- [x] 8. Title, body and comments are in English.
- [x] The *Before Submitting* list in CONTRIBUTING.md is done.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01JQwxbZcVyAXy4Gm9UakRew)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 592845b commit 74fd4bf
3 files changed
Lines changed: 58 additions & 7 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
389 | 389 | | |
390 | 390 | | |
391 | 391 | | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
392 | 423 | | |
393 | 424 | | |
394 | 425 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3598 | 3598 | | |
3599 | 3599 | | |
3600 | 3600 | | |
3601 | | - | |
| 3601 | + | |
| 3602 | + | |
3602 | 3603 | | |
3603 | 3604 | | |
3604 | 3605 | | |
| |||
3651 | 3652 | | |
3652 | 3653 | | |
3653 | 3654 | | |
3654 | | - | |
| 3655 | + | |
| 3656 | + | |
| 3657 | + | |
| 3658 | + | |
| 3659 | + | |
| 3660 | + | |
| 3661 | + | |
| 3662 | + | |
| 3663 | + | |
| 3664 | + | |
3655 | 3665 | | |
3656 | | - | |
| 3666 | + | |
| 3667 | + | |
3657 | 3668 | | |
3658 | 3669 | | |
3659 | 3670 | | |
3660 | 3671 | | |
3661 | 3672 | | |
3662 | 3673 | | |
3663 | 3674 | | |
3664 | | - | |
3665 | | - | |
3666 | | - | |
3667 | | - | |
| 3675 | + | |
3668 | 3676 | | |
3669 | 3677 | | |
3670 | 3678 | | |
| |||
0 commit comments