Repository navigation
fix(plugin-approvals): the data door serves an approval request's flow and step labels in the reader's language - #27092
Conversation
…in the reader's locale (red) Claude-Session: https://claude.ai/code/session_01FEkQ5kcTaxH7yNuUvHxaPR Co-authored-by: Claude <noreply@anthropic.com>
…erves the flow and step labels in the reader's language Engine middleware on sys_approval_request, beside the snapshot redaction, overlays process_label / current_step_label by the approvals door's own readerLabelsFor + localizeRequestLabels. A projected label borrows its key columns for the read and the rows are served without them. Storage and system reads are untouched. Claude-Session: https://claude.ai/code/session_01FEkQ5kcTaxH7yNuUvHxaPR Co-authored-by: Claude <noreply@anthropic.com>
…er-locale label seam Claude-Session: https://claude.ai/code/session_01FEkQ5kcTaxH7yNuUvHxaPR Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 14 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 7 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 6 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin d465e6f51c340381d3fb4ea0ef88f412b2cf7f57 && git checkout d465e6f51c340381d3fb4ea0ef88f412b2cf7f57
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin fbc16563a65f0352527ea97aaf55c540e89ae4da ee26b793a926d341327e5d846da1eb141efb4003 && git checkout -B drift-repro fbc16563a65f0352527ea97aaf55c540e89ae4da && git merge --no-ff ee26b793a926d341327e5d846da1eb141efb4003
node scripts/docs-audit/affected-docs.mjs --json fbc16563a65f0352527ea97aaf55c540e89ae4da
|
席位核对ACCEPT · The maintainer's standing authorisation for landing reviewed PRs, verbatim: 「按照 pm-dispatch 规则复核过的都授权」.
Generated by Claude Code |
Requested by Leehom · project thread
Fixes #27041
Clause-②: no
Metadata-protocol: none
维护者速读
sys_approval_request(Setup › 审批申请列表、申请的记录页、查找字段的标题、导出)时,流程名process_label和步骤名current_step_label按读者语言返回,用的就是审批接口(/api/v1/approvals/requests)已有的那一套查找;语言包没有的条目照旧返回存储文本。$select时会临时多取process_name/current_step用来拼键,返回前删掉,调用方拿到的列不变。回滚即 revert。packages/plugins/plugin-approvals/src/reader-locale-labels-middleware.ts(借列与剥列、系统读跳过);approvals-plugin.ts的注册位置(与读门同处,不在disableAutoHooks后面);content/docs/permissions/system-context.mdx第 17 行。pnpm --filter @objectstack/plugin-approvals exec vitest run src/reader-locale-labels-data-door.integration.test.ts,预期 10/10 通过;或启动 showcase 后用Accept-Language: zh-CN请求GET /api/v1/data/sys_approval_request?$select=process_label,current_step_label,看到「发票双重签批(并行审批)」等中文。What changes
@objectstack/plugin-approvalsregisters one more engine middleware onsys_approval_request,bindReaderLocaleLabelsMiddleware(new filereader-locale-labels-middleware.ts), beside the snapshot redaction (payload-redaction-middleware.ts) and for its reason: one registration at the engine covers the whole generic-read family (REST data routes, ObjectQL callers, the CSV/XLSX export, the MCP data tool, the AI-context interceptor), and middleware carries the door's realExecutionContext, whoselocaleis the one the approvals door reads (Accept-Language, else the workspacelocalizationsettings).readerLabelsForand are placed bylocalizeRequestLabels(reader-locale-labels.ts), the approvals door's own pair. No second translation table, no new key spelling: same keys (flows.FLOW.label,flows.FLOW.approvals.NODE.label), same locale negotiation (resolveBundleLocale), same fallback to the stored text on a miss.process_labelandcurrent_step_labelare overlaid;step_labelandobject_labelare approvals-door fields, not columns, and this door does not add them.all_requestsview selects the labels and not the machine columns. When a read selects a label without the column its key is spelled from (process_name,current_step), the middleware borrows that column intoast.fieldsfor the read and deletes it from every row before the rows go back, so the caller is served exactly the columns it asked for.isSystem) is served as stored even when its context carries a locale, so nothing the platform reads back and writes again holds a reader's language. No locale, noi18nservice, or a missing pack entry: the stored text.bindRequestReadGate), not behinddisableAutoHooks, because the approvals door localizes whenever the service runs.isSystemread is named oncontent/docs/permissions/system-context.mdxrow 17 (the plugin-approvals generic-read row) and the generated register is regenerated withnode scripts/check-system-context-census.mjs --write(claim amendment6461039298).reader-locale-labels.tsno longer says the data door serves the stored text;sys-approval-request.object.tsnotes the overlay beside the display-column comment.Tests
New
reader-locale-labels-data-door.integration.test.ts: the rig ofreader-locale-display-labels.integration.test.ts(realObjectQLoverSqlDriverbetter-sqlite3, the realAutomationEngineopening the request through the real approval node, the realApprovalsServicePluginover the real in-memoryi18nservice with a zh-CN pack parsed byTranslationDataSchema), read throughObjectStackProtocolImplementation.findData/getData, the calls the REST data routes make.all_requests' columns, the full-column list, the by-id read, a barezh: the zh-CN labels.svc.getRequestand through the data door (list and by-id) carries equal label text.step_label/object_labelcolumn is added; the stored row keeps the authored text.Package:
pnpm --filter @objectstack/plugin-approvals test105 files / 1331 tests passed;typecheckexit 0;buildexit 0 (onf7d8e486; the only later commit,ee26b793, touchessystem-context.mdxalone).Acceptance notes
display_title(a formula,process_labelelseprocess_name) is computed inside the engine before middleware runs, so it stays the stored text. It is not the title pointer (nameField: process_label) and no list view shows it.process_label/current_step_labelcompare the stored text, so a grid grouped byprocess_labelheads its groups in the authoring language. Not filed: no reproduction on a shipped view (none groups by these columns).count/aggregateare untouched; they serve no label text.Verification
Red first, in-package (base f708cf2 + the test only, commit 36c5405)
Green on the fix: the new file plus
reader-locale-display-labels.integration.test.tsandrequest-read-gate.integration.test.ts: 3 files, 36/36 passed.Live red/green through the real REST data door (showcase, `pnpm dev -- --fresh`)
Signed in as the seeded dev admin; the showcase boot opens three pending requests whose flows its zh-CN pack translates. Red = the base blob of
approvals-plugin.tswritten over the file and the package rebuilt (bind count indist/index.js0); green = HEAD (count 2). Restored bygit checkout HEAD --, blob869363efequal to HEAD,git diff HEADempty.GET /api/v1/data/sys_approval_request?$select=process_label,record_id,status,current_step_label,pending_approver_labels,submitter_id,updated_at,Accept-Language: zh-CN:On head,
process_name/current_stepabsent from those rows;ja-JPandenserve the English text on both sides.By id,
zh-CN: baseGET /data/sys_approval_request/IDserved "Invoice Dual Sign-off (parallel approval)" whileGET /approvals/requests/IDserved "发票双重签批(并行审批)"; head serves "发票双重签批(并行审批)" / "财务 + 法务签批" on both doors. The data door row carries nostep_label/object_label.Ablations (src-resolved suite, `scripts/ablation-replace.mjs`, each restored to the HEAD blob with `git diff HEAD` empty)
bindReaderLocaleLabelsMiddleware(...)call inapprovals-plugin.tsreplaced: 6 failed / 4 passed, the six zh-CN pins.borrowLabelKeyColumns: 3 failed (the three projected-list pins).process_name/current_step).Gates (head ee26b79)
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: 92 families, all run, all exit 0;--ranreconciliation: 92 derived, 92 run, 0 NOT-MEASURED, 0 UNRUN. First pass reds re-run after the full build settled:check:dts-closure,check:dual-build-cjs-loads,check:i18n(each ran against adist/mid-rebuild),check-plugin-teardown-shape --self-test(shallow clone; fixture commit fetched), all exit 0 on re-run.check:system-context-censuswas a real red (the newisSystemread had no row) fixed by the row-17 edit.pnpm exec eslint --no-inline-config packages/plugins/plugin-approvalsexit 0;check-nul-bytesexit 0.Not run locally:
test:repo(CI Test Core); full dogfood (no!, no(narrowing)arm).Human Minimum
packages/specholds no runtime logic. (spec untouched)pnpm lintpasses (scoped to the package).main, one pull request.packages/spectouched: n/a.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.🤖 Generated with Claude Code
Generated by Claude Code