Repository navigation
feat(showcase): stamp real submitters on the seeded approval requests - #3411
Merged
Merged
Conversation
Every seeded request had a null submitter, because the demo launches flows as
SYS and the approval node stamps the requester from the flow context
(`submitterId: context?.userId ?? null`, approval-node.ts). Consequences, all
invisible until you go looking:
* 申请人 rendered as `—` on every row and in the drawer;
* the "我发起的" inbox tab was empty for every user, so that whole surface
was dead; and
* the submitter-only affordances never rendered anywhere — `Send reminder`
and `Recall` are gated on `submitter_id == ctx.user.id`, so with no
submitter they were unreachable and only 5 of the 7 declared approval
actions could ever appear.
Pass `userId` on the engine context and route it deliberately:
* Invoice Dual Sign-off → submitted by the **admin**, so the logged-in dev
admin owns one request and "我发起的" is non-empty with the submitter-only
actions visible;
* Committee Quorum and Expense Sign-off → submitted by **Mei Phone (demo)**,
who holds no approval position and is therefore a clean requester who is
never one of her own approvers.
Verified in the running console: 申请人 now shows real names, "我发起的" holds
the admin's request, and the same viewer sees `Approve / Reject / Reassign /
Send back / Request info` on Mei's requests but those **plus** `Send reminder`
and `Recall` on his own — i.e. all 7 declared actions render, gated by role.
`tsc --noEmit` passes; boot log stays at 0 ERROR.
From the #3358 §1 evidence pass; follow-up to #3409.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
26 of 54 tasks
os-project-manager
pushed a commit
that referenced
this pull request
Aug 18, 2026
…ot run without (#9308) Three platform capabilities had no fixture anywhere in the reference app, so the checklist items covering them were not failing — they were unrunnable. 1. A second, actually LOGINABLE member. The demo personas have been sys_user rows since #3409/#3411 and neither could sign in, blocking every item that needs two acting identities. The non-obvious half: better-auth 1.7 keys accounts on (issuer, providerAccountId), so a credential row carrying any other issuer is invisible to sign-in and fails INVALID_EMAIL_OR_PASSWORD behind a "User not found" warn that points at the user row instead of the account. seed-approval-demo.ts now provisions the credential account through better-auth's own $context and READS the issuer off the dev admin's own credential row rather than re-spelling a constant plugin-auth owns. Dev-only by construction. 2. showcase_client_brief — the first object to opt into publicSharing. Carries redactFields, an expiry cap and an eligibility predicate; the seed holds a published brief (mint-eligible) and a draft one (refused RECORD_NOT_ELIGIBLE) so the predicate is falsifiable. Every other object still declines the opt-in, which is what keeps the per-object 422 a real control. 3. showcase_client_liaison — the app's first readable:false FLS grant, on the same three showcase_project budget figures showcase_contributor governs with readable:true/editable:false. All three move together because budget_remaining is a formula over budget - spent. Downstream reconciliations, each deliberate and none a re-baseline: access-matrix.json gains two rows and moves none; the persona x CRUD census follows the matrix (50/50 -> 54/54, arithmetic recorded at the assertion) and its fixture maps learn the new object; the position count pin follows the new position. Five checklist items are revised in the same change — gap text kept, marked closed-by-fixture, revision bumped, history appended (#7670 pattern). Not landed: the writable-package summary field for automation.rollup-summary-filter. It is not seed data and cannot be made into seed data — see FOLLOW-UPS.md section 6. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y26DJEHSBhhAQ6wwfsHNza
This was referenced Aug 18, 2026
Merged
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Aug 23, 2026
…ot run without (objectstack-ai#9308) (objectstack-ai#9789) * test(showcase): land the seed fixtures the platform checklist could not run without (objectstack-ai#9308) Three platform capabilities had no fixture anywhere in the reference app, so the checklist items covering them were not failing — they were unrunnable. 1. A second, actually LOGINABLE member. The demo personas have been sys_user rows since objectstack-ai#3409/objectstack-ai#3411 and neither could sign in, blocking every item that needs two acting identities. The non-obvious half: better-auth 1.7 keys accounts on (issuer, providerAccountId), so a credential row carrying any other issuer is invisible to sign-in and fails INVALID_EMAIL_OR_PASSWORD behind a "User not found" warn that points at the user row instead of the account. seed-approval-demo.ts now provisions the credential account through better-auth's own $context and READS the issuer off the dev admin's own credential row rather than re-spelling a constant plugin-auth owns. Dev-only by construction. 2. showcase_client_brief — the first object to opt into publicSharing. Carries redactFields, an expiry cap and an eligibility predicate; the seed holds a published brief (mint-eligible) and a draft one (refused RECORD_NOT_ELIGIBLE) so the predicate is falsifiable. Every other object still declines the opt-in, which is what keeps the per-object 422 a real control. 3. showcase_client_liaison — the app's first readable:false FLS grant, on the same three showcase_project budget figures showcase_contributor governs with readable:true/editable:false. All three move together because budget_remaining is a formula over budget - spent. Downstream reconciliations, each deliberate and none a re-baseline: access-matrix.json gains two rows and moves none; the persona x CRUD census follows the matrix (50/50 -> 54/54, arithmetic recorded at the assertion) and its fixture maps learn the new object; the position count pin follows the new position. Five checklist items are revised in the same change — gap text kept, marked closed-by-fixture, revision bumped, history appended (objectstack-ai#7670 pattern). Not landed: the writable-package summary field for automation.rollup-summary-filter. It is not seed data and cannot be made into seed data — see FOLLOW-UPS.md section 6. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y26DJEHSBhhAQ6wwfsHNza * i18n(showcase): translate the client-brief fixture into zh-CN (objectstack-ai#9308) `check:i18n-coverage` went red on PR objectstack-ai#9789: untranslated declared strings for examples/app-showcase grew 393 -> 405. The showcase declares supportedLocales ['en', 'zh-CN'], so every label the new `showcase_client_brief` object declares owed a zh-CN rendering. Measured: all 12 are that object — label, pluralLabel, description, seven field labels and both `status` options. The new position and permission set are NOT counted by this rule, which counts object/field/option strings only. Both locales are written key for key. `check-i18n-coverage` is a two-sided ratchet, so an `en` entry landing without its zh-CN mirror is what widens the gap rather than closing it. Renderings follow the ones this bundle already established rather than being coined fresh — 标题 / 项目 / 状态 / 备注 / 负责人 are the words showcase_task and showcase_invoice already use for the same concepts, which is the whole point of the file: a list must not mix a translated 状态 with an English Owner beside it. 草稿 / 已发布 are new (nothing here rendered a draft state before); 已发布 follows the 已完成 pattern the bundle uses for a state that has been reached. The description is mirrored byte-for-byte from the object declaration on the en side and translated in full on the zh side, ADR reference included. A bundle entry overrides the schema label for its locale, so a "tidied" English description would silently rewrite product copy under the guise of translating it, and a half-dropped Chinese one is the locale degradation the bundle exists to prevent. Count back to 393 exactly, not merely stopped growing. The baseline in scripts/i18n-coverage-baseline.json is untouched (no --update anywhere). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y26DJEHSBhhAQ6wwfsHNza --------- Co-authored-by: Claude <noreply@anthropic.com>
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The gap
Every seeded approval request had a null submitter: the demo launches flows as SYS, and the approval node stamps the requester from the flow context (
submitterId: context?.userId ?? null). Three consequences, all invisible until you look:—on every row and in the drawer;Send reminderandRecallare gated onsubmitter_id == ctx.user.id, so with no submitter only 5 of the 7 declared approval actions could ever appear.The fix
Pass
userIdon the engine context, routed deliberately:Verified in the running console
申请人 now shows real names; 我发起的 holds the admin's request; and the same viewer sees
ApproveRejectReassignSend backRequest infoSend reminderandRecallso all 7 declared actions render, gated by the viewer's role.
tsc --noEmit✓, boot log 0 ERROR.Follow-up to #3409, from the #3358 §1 evidence pass. Private example → no changeset.
🤖 Generated with Claude Code