Repository navigation
Commit 42ff86f
feat(runtime): flow and permission-set clone answers name their notice by a stable noticeCode (#29823)
<!-- claude-projects-attribution: {"github_login":"os-warren"} -->
_Requested by **Warren** · [project
thread](https://claude.ai/code/project/chan_01U5RdnAAmkSQmZbqh6FtqZ8?thread=cmsg_01U5RdnAAmkSQmZbqh6FtqZ8NAQdrjsKCddXcRgHBvC8Yg)_
Refs #29727 (leg 1, server. Leg 2, the Console mapping, belongs to the
ui lane, so this PR does not close the card.)
Clause-②: no
Metadata-protocol: none
## 维护者速读
- 改了什么:流程与权限集的"新建类似"克隆应答在原有英文 `notice` 旁新增
`noticeCode`;流程固定一个码,权限集按落点三种变体各一个码。
- 为什么改:控制台此前只能原样显示英文句子,中文界面看到英文;有了码,控制台可映射成自己的翻译,未知码仍回退 `notice`。
- 风险与回滚:只加键,`notice` 字节不变(测试逐字钉住);回滚即撤销本 PR,旧控制台忽略新键。
-
先看:`packages/runtime/src/domains/permission-set-clone.ts`(码与句子共用同一落点分类)、`packages/runtime/src/flow-clone.ts`、`packages/runtime/src/domains/automation.ts`(克隆应答那一行)。
- 两分钟验证:`pnpm --filter @objectstack/runtime exec vitest run
src/domains/permission-set-clone.test.ts`,预期全绿,含三个变体的码与原句逐字比对。
- 需要你做的:无,席位落地。
## Why
Both "New similar" clone answers carried only an English `notice`, which
the Console prints verbatim, so a zh-CN screen showed English (#29727,
from #29706 row 1). A server sentence reaches the Console translated by
code: the Console maps a known code to its own key and keeps the wire
text for an unknown one. This PR gives both sentences that code.
## What changes
- **Flow clone door** (`POST /api/v1/automation/:name/clone`). The
answer carries `data.noticeCode: 'FLOW_CLONE_DISABLED_COPY'` beside the
unchanged `FLOW_CLONE_NOTICE`. The code is exported as
`FLOW_CLONE_NOTICE_CODE` next to the sentence in `flow-clone.ts`. The
key is the optional one `CloneFlowResponseSchema` already declares
(#29758 / #29779), so no spec file moves, and the client's
`CloneFlowResponse` type already carries it.
- **Permission-set clone door** (`POST
/api/v1/security/permission-sets/:name/clone`, server-only, no spec
schema). `permissionSetCloneNotice` composes three sentences, so there
is one code per variant: `PERMISSION_SET_CLONE_ENVIRONMENT_WIDE`,
`PERMISSION_SET_CLONE_IN_PACKAGE` and
`PERMISSION_SET_CLONE_IN_CREATED_PACKAGE`. No parameter key is needed,
because the one value the sentence carries, the package, is already on
the answer as `data.package`. A single
`permissionSetCloneLandingKind(landing)` sorts a landing into its
variant, and both the sentence and
`permissionSetCloneNoticeCode(landing)` (through the exported
`PERMISSION_SET_CLONE_NOTICE_CODES` table, keyed by that kind) are
chosen from that one answer, so code and sentence cannot drift.
- **`notice` is unchanged** on both doors, byte for byte, and stays the
English fallback.
- **Route ledger.** The two clone rows in `route-ledger.ts` now spell
their `data` as `{ flow, packageId, notice, noticeCode }` and `{
permissionSet, package, notice, noticeCode }`.
- **Docs.** `content/docs/permissions/permission-sets.mdx` names
`noticeCode` in the permission-set clone answer, with one clause saying
what it is for (claim amendment on #29727, after the docs drift check).
Nothing else on that page changed.
- **Changeset.** `@objectstack/runtime` patch.
## Tests
- `domains/automation-flow-clone.test.ts`: a new case asserts the
answer's `noticeCode` is `FLOW_CLONE_DISABLED_COPY`, and as a CONTROL
asserts `notice` equals the English sentence spelled out literally (not
read off the constant), plus the answer's exact key set.
- `domains/automation-flow-clone-custom-package.test.ts` (real protocol,
registry and store): the answer carries the code, and
`CloneFlowResponseSchema.parse` keeps it.
- `domains/permission-set-clone.test.ts`: each of the door's landing
cases asserts its code (created pair, reused pair, writable package, and
the environment-wide CONTROL, which also keeps its notice). A new table
pins every variant's code and its full sentence literally, so a change
to `notice` while touching codes reds.
- Dogfood over HTTP: `automation-flow-clone-door.dogfood.test.ts` and
`permission-set-clone-door.dogfood.test.ts` assert the codes on the
served answers (created pair, then reused pair).
## Acceptance notes
- The order asked to add the optional field to the Console's type for
the permission-set answer if one exists. One does
(`ui/packages/app-shell/src/views/metadata-admin/permission-set-clone.ts`,
`PermissionSetCloned`), but `ui/**` is outside this card's claimed file
surface, so it is left for leg 2, which reads the code there anyway.
- The flow notice's Console type needs nothing: the client's
`automation.clone()` returns `CloneFlowResponse['data']`, which already
declares `noticeCode`.
## Verification
Head `db94ab0b`. All code readings were taken at `ecac38e6`, which has
the same tree as `da10eb94` (only the commit message was reworded, to
drop a card trailer the pre-push hook refuses). `db94ab0b` adds the one
docs line on top of that. For the docs line, `check:doc-authoring`,
`check:doc-anchors`, `docs-audit/check-affected-docs`,
`check-drift-comment` and `check:nul-bytes` each exit 0 at `db94ab0b`.
The lychee lane is CI's.
<details><summary>Unit tests: the three door suites 78/78, and the full
runtime suite</summary>
- `pnpm --filter @objectstack/runtime exec vitest run --maxWorkers=2
src/domains/automation-flow-clone.test.ts
src/domains/automation-flow-clone-custom-package.test.ts
src/domains/permission-set-clone.test.ts`: `Test Files 3 passed (3)`,
`Tests 78 passed (78)`.
- `pnpm --filter @objectstack/runtime test`: `Test Files 534 passed
(534)`, `Tests 8559 passed | 19 skipped (8578)`.
- `pnpm --filter @objectstack/runtime typecheck` and `build`: exit 0.
</details>
<details><summary>Dogfood over HTTP: both door files 16/16</summary>
After `pnpm --filter '@objectstack/dogfood^...' build`: `pnpm --filter
@objectstack/dogfood exec vitest run
test/automation-flow-clone-door.dogfood.test.ts
test/permission-set-clone-door.dogfood.test.ts` gave `Test Files 2
passed (2)`, `Tests 16 passed (16)`. The full dogfood battery was not
owed: the title has no `!` and the change has no narrowing arm.
</details>
<details><summary>Ablation: five mutations through
scripts/ablation-replace.mjs, each landed on disk, each red, each
restored</summary>
The unit suites import the runtime from `src`, so no `dist` step is
involved. After each leg `git diff HEAD` was empty.
| # | Mutation | Result |
|---|---|---|
| A1 | flow door drops `noticeCode` (`automation.ts`) | 2 failed / 76
passed: the new unit case and the real-stack answer case |
| A2 | permission-set door drops `noticeCode` | 4 failed / 74 passed:
created pair, reused pair, writable package, environment-wide CONTROL |
| A3 | the code collapses "created" into "in package" | 2 failed / 76
passed: the created-pair door case and its table row |
| A4 | CONTROL: the flow sentence drifts by one word | 2 failed / 76
passed: the existing sentence case and the new byte-identity case |
| A5 | CONTROL: the permission-set package sentence drifts | 2 failed /
37 passed: the in-package and created-package table rows |
</details>
<details><summary>Derived gates: 67 derived, 66 run, 1 NOT
MEASURED</summary>
`node scripts/pm/dispatch-gates.mjs --commands` derived 67 families;
every one ran and `--ran` reconciled: `67 derived famil(ies) accounted
for, 66 run, 1 NOT-MEASURED`. 65 exited 0 on the first run.
`check-plugin-teardown-shape.mjs --self-test` exited 3 on the shallow
clone, then 0 after `git fetch --unshallow`. `pnpm
check:dual-build-cjs-loads` exits 3 because not every package has a
`dist` in this tree: NOT MEASURED, left to CI.
</details>
## Human Minimum
- [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic.
(No spec change here.)
- [x] 2. Every name I added uses the casing for its kind.
- [x] 3. No formatter ran; `pnpm lint` is CI's run.
- [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` 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, except the maintainer
brief, which the os-dev order writes in Chinese.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01JQwxbWvgXNaTVoBWSiMCCC)_
<!-- signed: domain:server#3 · os-warren ·
session_01JQwxbYyp6wSRcywGFK2L4A -->
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 1d16d64 commit 42ff86f
11 files changed
Lines changed: 168 additions & 14 deletions
File tree
- .changeset
- content/docs/permissions
- packages
- qa/dogfood/test
- runtime/src
- domains
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
460 | 460 | | |
461 | 461 | | |
462 | 462 | | |
463 | | - | |
464 | | - | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
465 | 466 | | |
466 | 467 | | |
467 | 468 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
41 | | - | |
| 41 | + | |
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
| |||
92 | 92 | | |
93 | 93 | | |
94 | 94 | | |
95 | | - | |
| 95 | + | |
96 | 96 | | |
97 | 97 | | |
98 | 98 | | |
| 99 | + | |
| 100 | + | |
99 | 101 | | |
100 | 102 | | |
101 | 103 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
104 | 104 | | |
105 | 105 | | |
106 | 106 | | |
107 | | - | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
108 | 110 | | |
109 | 111 | | |
110 | 112 | | |
| |||
113 | 115 | | |
114 | 116 | | |
115 | 117 | | |
| 118 | + | |
| 119 | + | |
116 | 120 | | |
117 | 121 | | |
118 | 122 | | |
| |||
139 | 143 | | |
140 | 144 | | |
141 | 145 | | |
142 | | - | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
143 | 150 | | |
144 | 151 | | |
145 | 152 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
49 | | - | |
| 49 | + | |
50 | 50 | | |
51 | 51 | | |
52 | 52 | | |
| |||
214 | 214 | | |
215 | 215 | | |
216 | 216 | | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
217 | 220 | | |
218 | 221 | | |
219 | 222 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
50 | 50 | | |
51 | 51 | | |
52 | 52 | | |
| 53 | + | |
53 | 54 | | |
54 | 55 | | |
55 | 56 | | |
| |||
502 | 503 | | |
503 | 504 | | |
504 | 505 | | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
505 | 527 | | |
506 | 528 | | |
507 | 529 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
81 | 81 | | |
82 | 82 | | |
83 | 83 | | |
| 84 | + | |
84 | 85 | | |
85 | 86 | | |
86 | 87 | | |
| |||
3964 | 3965 | | |
3965 | 3966 | | |
3966 | 3967 | | |
| 3968 | + | |
| 3969 | + | |
3967 | 3970 | | |
3968 | 3971 | | |
3969 | | - | |
| 3972 | + | |
| 3973 | + | |
| 3974 | + | |
| 3975 | + | |
| 3976 | + | |
| 3977 | + | |
3970 | 3978 | | |
3971 | 3979 | | |
3972 | 3980 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| 34 | + | |
34 | 35 | | |
| 36 | + | |
35 | 37 | | |
36 | 38 | | |
37 | 39 | | |
| |||
197 | 199 | | |
198 | 200 | | |
199 | 201 | | |
| 202 | + | |
200 | 203 | | |
201 | 204 | | |
202 | 205 | | |
| |||
212 | 215 | | |
213 | 216 | | |
214 | 217 | | |
| 218 | + | |
| 219 | + | |
215 | 220 | | |
216 | 221 | | |
217 | 222 | | |
| |||
224 | 229 | | |
225 | 230 | | |
226 | 231 | | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
227 | 235 | | |
228 | 236 | | |
229 | 237 | | |
| |||
235 | 243 | | |
236 | 244 | | |
237 | 245 | | |
| 246 | + | |
| 247 | + | |
238 | 248 | | |
239 | 249 | | |
240 | 250 | | |
| |||
316 | 326 | | |
317 | 327 | | |
318 | 328 | | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
319 | 368 | | |
320 | 369 | | |
321 | 370 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
86 | 86 | | |
87 | 87 | | |
88 | 88 | | |
89 | | - | |
| 89 | + | |
| 90 | + | |
90 | 91 | | |
91 | 92 | | |
92 | 93 | | |
| |||
159 | 160 | | |
160 | 161 | | |
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 | + | |
162 | 189 | | |
163 | 190 | | |
164 | 191 | | |
165 | 192 | | |
166 | 193 | | |
167 | | - | |
| 194 | + | |
| 195 | + | |
168 | 196 | | |
169 | 197 | | |
170 | 198 | | |
171 | 199 | | |
172 | | - | |
| 200 | + | |
173 | 201 | | |
174 | 202 | | |
175 | 203 | | |
176 | 204 | | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
177 | 210 | | |
178 | 211 | | |
179 | 212 | | |
| |||
529 | 562 | | |
530 | 563 | | |
531 | 564 | | |
| 565 | + | |
| 566 | + | |
532 | 567 | | |
533 | 568 | | |
534 | 569 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
207 | 207 | | |
208 | 208 | | |
209 | 209 | | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
210 | 222 | | |
211 | 223 | | |
212 | 224 | | |
| |||
0 commit comments