You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
showcase: the "Recalculate Estimate" / "Recalculate Selection" api actions answer 500 — recalc-endpoint.ts calls ctx.ql.update with no execution context, which the security layer refuses as a principal-less write #23128
Reader who acts: the seat that owns examples/app-showcase (lane per triage). Dedupe: semantic issue search on this repo, closed included, "showcase recalc endpoint 500 ql.update no principal security access denied execution context" — 5 hits, none this shape (nearest #7673, closed: a different 500 on member create).
Environment
objectstack 36b2889c with the console built from objectui 1fb1ced36243 (the pin hop of #23104, since landed as f451a5964), stock examples/app-showcase, --seed-admin, admin persona. Reproduced twice on fresh loads by the runner; mechanism confirmed in source by the PM seat; not a regression of the pin hop (no hop commit touches the implicated files).
Reproduction
Open any task record: /_console/apps/showcase_app/showcase_task/record/ID.
Captured POST /api/v1/showcase/recalc with body {"recordId":"ID"} → 500{success:false, error:"[Security] Access denied: operation 'update' on object 'showcase_task' was called with a context that carries no principal (no user, no position, no permission set) and is not a system context…"}.
GET /api/v1/data/showcase_task/ID → estimate_hours unchanged (40 → 40). The aggregate body {_selectedIds:[…]} from the bulk-actions view answers the same 500.
Expected: 200 and the estimate recomputed — the api leg of the action-location matrix round-trips like the flow, modal, script, form and url legs (all of which pass on the same boot).
Mechanism (objectstack main)
examples/app-showcase/src/system/server/recalc-endpoint.ts writes with ctx.ql.update('showcase_task', {...}, { where: { id } }) (the single-record path) and the same call per id on the _selectedIds path — neither passes an execution context, so the write carries no principal and the security layer refuses it. The endpoint has the caller's request in hand; whether it should write as that caller or as a declared system context is the fixing seat's call.
Triage: first grade, bug · priority:p3 · domain:cli · area:records, into pm:queue. The endpoint writes as its caller. ⛔ Not as a system context
Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-13T04:03Z. ⛔ Not a claim, ⛔ not a dispatch.
Why p3: a showcase action fails loudly (500), and nothing is written. It is a reference app, though, and an example is what authors and AI copy, so the fix must teach the right pattern.
Lane:examples/* goes to the subsystem it exercises. Here that is a custom server endpoint writing through ctx.ql, the runtime's endpoint API, so domain:cli.
Direction (the card left it to the fixing seat; triage decides):
recalc-endpoint.ts passes the caller's execution context, from the request it already holds, on both the single and the _selectedIds paths. The security layer then judges the write as that user.
⛔ Not a system context. That would let anyone who can reach the endpoint update rows they may not edit, which loosens a boundary, and it is the wrong lesson for an example.
Pins:
an admin's recalc answers 200 and updates the estimate;
a caller without edit rights on that row is refused by the security layer, not by a 500;
the bulk path is the same.
Triage: lands in examples/app-showcase/src/system/server/recalc-endpoint.ts (domain:cli); rationale: write as the caller.
The same browser pass hit this 500 from the i18n side: the only zh successMessage specimens in the showcase (showcase_recalc_estimate "工时已重算。" and showcase_recalc_selection) both target POST /api/v1/showcase/recalc, so no zh success toast can attach to a 2xx round-trip — the raw security error text is toasted instead (2 UI reproductions on zh-CN, 2 direct API reproductions). Fixing the endpoint unblocks that clause too; no separate card.
Claim: PM loop round 10 · 2026-10-13T05:07Z
Session: session_01VoSxBQujKLZKPwK2u5ehQ6
Account: os-steve (the seat's linked user as GET /user answers it; always the card's assignee)
Branch: claude/issue-23128-recalc-writes-as-caller
Worktree: objectstack-issue-23128
Domain: domain:cli
Seat: domain:cli#2 (seat post #22648)
File surface (read on origin/maindc93781c19; stop on a breach and explain it in the report):
examples/app-showcase/src/system/server/recalc-endpoint.ts: both writes (the single-record path about :99, the _selectedIds path about :83) pass the caller's execution context, derived from the request the endpoint already holds, through the platform's own published route for a custom endpoint. The security layer then judges each write as that user (triage 6137971940).
⛔ Not a system context, and ⛔ no auth or session resolution written into the example. If no published route turns a raw http.server request into an execution context, the dev stops and reports.
Tests: the three pins triage named. An admin's recalc answers 200 and updates the estimate; a caller without edit rights on that row is refused by the security layer (its envelope), not a 500; the bulk path is the same. They go in the showcase's or dogfood's test home, wherever the endpoint's existing tests live.
One .changeset/23128-*.md, if the showcase package publishes; otherwise none, stated.
⛔ Not touched: packages/plugins/plugin-security, packages/objectql, packages/runtime (read only), and the showcase's action metadata (the api actions stay as authored).
Container & model: S, mode:subagent, model: default tier (dispatch-gates --tier --repo objectstack-ai/objectstack: "no path-derived mandate"). No contract-review face: Clause-②: no. An example endpoint writes as its caller, and no accept set or export moves. check-governed-merges --test over the claimed path: not governed.
Clause-②: no
Responsibility: examples/app-showcase recalc-endpoint.ts (this lane: a custom server endpoint writing through ctx.ql) calls ctx.ql.update with no execution context, so the security layer refuses the write as principal-less | the endpoint holds the caller's request, and every other leg of the action-location matrix round-trips on the same boot | POST /api/v1/showcase/recalc answers 500 and writes nothing, single and bulk, reproduced twice by the #23104 browser pass (records-forms A2, i18n A5)
Thread-read: 6138299012
Serial constraints cleared:
Of the open PRs (file lists read in this act), none touches examples/app-showcase/src/system/server/.
{
"issue": 23128,
"status": "needs_decision",
"branch": "claude/issue-23128-recalc-writes-as-caller",
"pr": null,
"session": "session_01VoSxBQujKLZKPwK2u5ehQ6 (mode:subagent, the dispatching PM session)",
"premise_still_valid": true,
"summary": "Stopped at the dispatch's own stop condition: there is no PUBLISHED route by which a code-mounted http.server handler turns its request into an ExecutionContext, so writing the recalc as its caller would mean composing session/authz resolution inside the example, which the claim forbids. No code edited, no PR. Measured on dc93781c19: (1) the one-call resolver exists but is INTERNAL: resolveExecutionContext, packages/runtime/src/security/resolve-execution-context.ts:118 (the dispatcher face; @objectstack/runtime has one \".\" export and src/index.ts names it 0 times). (2) HttpDispatcher.resolveRequestScope / registerDomainHandler are public methods on an exported class, but the instance built at dispatcher-plugin.ts:906 is not registered as a kernel service, and registerDomainHandler has 0 callers outside the class. (3) makeExecutionContextResolver is exported from @objectstack/plugin-hono-server only through export * (current-user-endpoints.ts:443): it takes a Hono context c (reads c.req.raw.headers), not an IHttpRequest, resolves the better-auth session only (no API key, no tenancy posture), is documented for the three /auth/me routes, and the showcase does not depend on that package. (4) The published building blocks are resolveAuthzContext, classifyAdmissionTenancyPosture and assembleExecutionContext / assembleExecutionContextOrGuest (@objectstack/core, which @objectstack/runtime re-exports via export * at src/index.ts:283), plus inProcessSessionReadInput (@objectstack/types, not a showcase dependency). Every door hand-rolls the session plumbing around them: rest-server.ts:3060, runtime resolve-execution-context.ts:150, service-settings settings-service-plugin.ts:285, service-storage storage-service-plugin.ts:862 and :1247, plugin-hono-server current-user-endpoints.ts:443. That makes five copies today. Reach was reproduced on stock showcase (see tests). The PM assumption 1 holds: the two writes are ctx.ql.update at :83 (_selectedIds) and :99 (single), and neither passes a context. Assumption 3 was read from source and NOT MEASURED live: the security layer refuses with PermissionDeniedError (plugin-security errors.ts:41, code PERMISSION_DENIED, status 403; principal-less form at security-plugin.ts:390). The hono direct-mount wrap() renders a thrown declared ADR-0112 envelope (adapter.ts:284 declaredEnvelopeForThrow, renderDeclaredEnvelope: true at :484). So the eventual fix maps the refusal by letting it escape the handler instead of the current catch-all to 500. The empty branch was pushed at dc93781c19 as the write probe and landing marker, and it has no commits.",
"tests": "HEAD dc93781c19 (no commits on the branch). Builds, both inside scripts/pm/os-verify-lock.sh: turbo build of the closure filtered as example-showcase-caret-dots, concurrency 2: \"VERDICT command-exit 0 · held the lock 184s\", Tasks 61/61, 30 cached. Then turbo build of everything except docs, concurrency 2, because check-dev-prereqs refused dev:showcase with 8 dists missing: \"VERDICT command-exit 0 · held the lock 67s\", Tasks 74/74, 62 cached. REACH, on stock showcase, pnpm dev:showcase -- --fresh -p 43494, signed in as admin@objectos.ai through the cookie session (sign-in 200). Single POST /api/v1/showcase/recalc with body {\"recordId\":\"Lb0KVAiUEzkaQxIT\",\"start_date\":\"2026-10-07\",\"end_date\":\"2026-10-23\"} answered HTTP 500 {\"success\":false,\"error\":\"[Security] Access denied: operation 'update' on object 'showcase_task' was called with a context that carries no principal (no user, no position, no permission set) and is not a system context. ...\"}. GET /api/v1/data/showcase_task/Lb0KVAiUEzkaQxIT?select=id,estimate_hours then read estimate_hours 40, unchanged. The expected value was 136 (17 days x 8h). Bulk body {\"_selectedIds\":[\"1ZEufP8nabwr6fr_\",\"3FgjCY66QReBC15v\"]} answered HTTP 500 with the same body. The rows read 16 and 20, unchanged; the expected values were 8 and 8. Anonymous, with no cookie, the same single body answered HTTP 500 with the same body. The raw route has no authentication gate of its own, so the ADR-0096 strict-mode principal-less refusal is the only thing between an anonymous caller and this write today. A system context would have opened an anonymous write door, which confirms the triage ruling against one. Pins and before/after for admin vs non-editor (single and bulk): NOT MEASURED, reason: no fix was written (stop condition). Ablation: NOT MEASURED, same reason. Gates: dispatch-gates --commands --repo objectstack-ai/objectstack with no paths printed \"this branch changes nothing against origin/main (merge base dc93781c1) — nothing to derive\" (exit 2, the tool refusing an empty change set). Over the claim paths (recalc-endpoint.ts and test/recalc-endpoint.test.ts) it derives 42 commands, which were NOT run because there is no diff. Lint was NOT run: no files changed. The dev server process group I started was stopped by its own session id (12699): the port is free and the --fresh tempdir is gone.",
"mcp_calls": "0",
"api_writes": "1 — POST /repos/objectstack-ai/objectstack/issues/23128/comments (this os-dev-report, via scripts/pm/post-stamped.mjs on the fleet relay). Not counted as REST: git push of the empty branch. No pr_create, no label-write.",
"open_questions": [
{
"question": "How does a code-mounted http.server route (the showcase recalc endpoint) obtain its caller's ExecutionContext, given that no published one-call route exists? Triage has already decided the endpoint writes as its caller and not as a system context. Open: where the request-to-context resolution lives.",
"options": [
"A. Platform helper first. Export ONE request-to-ExecutionContext resolver for code-mounted http.server routes from @objectstack/runtime, promoting the internal resolveExecutionContext behind a plugin-context-shaped signature (getService/getServiceAsync + objectql + the IHttpRequest). The helper card must decide (i) which entry the helper takes for an anonymous request: core's own doc makes the fail-closed assembleExecutionContext the default (\"unless serving anonymous principals is part of its product semantics\"), but the runtime face uses the guest entry; and (ii) whether it carries the ADR-0069 auth gate, which today only the dispatcher (enforceAuthGate) and REST (envelope authGate) enforce, so a raw route bypasses it. #23128 then resumes, Blocked-by that card, as a ~5-line example change: pass the resolved context on both writes, let the refusal escape to the transport, plus its pins. Cost: a packages/runtime card (export, doc, minor changeset for @objectstack/runtime, a pin), S-M; the example, S.",
"B. Compose in the example from today's published pieces: resolveAuthzContext + classifyAdmissionTenancyPosture + assembleExecutionContext (via @objectstack/runtime) + a getSession wired to the auth service (api, else await getApi()) + inProcessSessionReadInput. Measured as a scratch sketch, NOT committed: 27 lines of door plumbing in the example. It needs @objectstack/types added to examples/app-showcase/package.json (outside this claim's file surface), or a copy of the session-cookie rule (a re-implementation). It still has no ADR-0069 gate and no localization. It would be the sixth hand-rolled copy. Cost: S now, plus drift later.",
"C. Re-home the recalc onto a declarative apis: endpoint (flow target) under /api/v1/apps/showcase/, which already runs as the caller through the dispatcher fallback's resolveRequestScope. This changes the two api actions' target (action metadata, out of this claim) and moves the estimate into a flow. It also removes the showcase's only code-mounted endpoint specimen (src/system/apis/index.ts names recalc-endpoint.ts as the code-mounted counterpart). It contradicts triage's landing point. Cost: M."
],
"recommendation": "A. The four axes, in order. ACTUAL BUSINESS NEED (measured): the need to resolve a raw route's caller is real and current. This endpoint backs two showcase actions and two QA clauses (records-forms A2, i18n A5), and five platform doors already hand-roll the same composition, so the pull for one helper is measured, not speculative. C removes the specimen instead of serving the need. LONG-TERM SOUNDNESS: A leaves one copy of a security seam. B adds a sixth copy with three inputs that can be omitted silently: the tenancy posture (the settings/storage omissions #15351/#15352 were this class), the in-process session read (#22258), and the auth gate. Each copy was fixed separately. C only moves the problem. AI-PROOFING: the showcase is what AI copies. A teaches one call. B teaches hand-rolling a 27-line auth door in which every omission compiles and passes. C teaches \"avoid code endpoints\". STARTUP FOCUS: A exports an already-built function (no new capability, no new gate). Adding one export to @objectstack/runtime's published surface is the tension, accepted because six consumers (five doors and this endpoint) pull for it. B adds no platform surface but adds a dependency and a copy. No option adds a gate."
}
],
"out_of_scope_findings": [
"carrier: the option-A helper card if ruled; otherwise the maintainer · noted, not filed (read-only inference, not reproduced as a defect). Code-mounted http.server routes receive no request identity and no ADR-0069 auth gate from the transport: IHttpRequest carries headers only, and adapter.ts runHandler builds no context. Five hand-rolled request-to-context compositions: rest-server.ts:3060, runtime security/resolve-execution-context.ts:150, service-settings settings-service-plugin.ts:285, service-storage storage-service-plugin.ts:862, plugin-hono-server current-user-endpoints.ts:443 · dedupe words: custom route execution context helper; http.server request identity; resolveExecutionContext export; raw route auth gate"
],
"gates": "none run, no diff at dc93781c19. dispatch-gates no-path derivation: exit 2, \"nothing to derive\". Claim-path derivation: 42 commands, not run.",
"line_budget": "n/a: no skills/** or ledger file touched",
"deviations": [
"Stopped at the dispatch's stop condition (assumption 2 falsified for a one-call published route). No PR, no label-write, no pr_create.",
"Ran a turbo build of every package except docs (inside the lock) because check-dev-prereqs refuses pnpm dev:showcase while any workspace dist is missing. 62 of 74 tasks were cached."
],
"files_changed": []
}
ADR-0096(docs/adr/0096-execution-surface-identity-admission.md)标题原文:"no data-engine call without an explicit principal or an explicit, audited elevation"。系统上下文就是那个「显式提权」,triage 已排除。
公开文档(content/docs/references/api/metadata.mdx、package-api.mdx、kernel/manifest.mdx 同句):"A route that needs real handler CODE is mounted imperatively: resolve the http.server service from the plugin context and register the handler on kernel:ready."文档教作者这样挂路由,却没告诉他怎样让这个路由以调用者身份写数据,也就是声明了一条路,却没兑现。
席位意见 · director seat (summon #37, session_01LqNgdPZB2Jnr5HpGbaqLeB), on the maintainer's question in chat 「我们是元数据定义的应用,代码挂载的自定义路由是否应该作废?」, 2026-10-13T09:01Z
Read on origin/main150da61aa before writing (every line below has its probe):
Who mounts code routes today.git grep -l "'http.server'" over packages apps examples plugins, tests and docs excluded: 18 files, 17 of them platform packages (cli serve/console, cloud-connection ×3, metadata, approvals, hono-server, sharing, webhooks, http-conformance, rest, runtime ×2, spec contracts, trigger-api) and exactly one app-author specimen: examples/app-showcase/src/system/server/recalc-endpoint.ts. The imperative mount is the platform's own door-building primitive; as an app surface it has one user, and that user is the one answering 500.
The declarative surface already exists and runs as the caller.defineStack({ apis }) (ADR-0121, restored in v17 by 17.x 立项:建设声明式 ApiEndpoint 执行器(挂载 + matchEndpoint + authRequired/cacheTtl/inputMapping/outputMapping 逐键接线) #5040): type: 'object_operation' | 'flow' execute ('script' and 'proxy' are frozen vocabulary, endpoint.zod.ts:174), authRequired defaults to true, rateLimit for the anonymous case (D6), the /api/v1/apps/<namespace>/… carve-out (D1/D2), OpenAPI enrichment, and the dispatcher's resolveRequestScope: the caller's identity, the ADR-0069 auth gate and ADR-0096's admission all come for free. The showcase itself declares two (showcase_task_feed, showcase_inquiry_purge_api).
The recalc needs no handler code. It is "days between two dates × 8, written to estimate_hours": a flow with an assignment node and an update_record node (both in the spec's node vocabulary, schemaless-node-config.zod.ts), triggered by an apis:flow endpoint, exactly the shape showcase_inquiry_purge already uses. The bulk (_selectedIds) path is the same flow over each id.
The declarative routes manifest key was already retired (spec 17, ADR-0049, manifest.zod.ts:884) because nothing read it; its retire text, repeated in three published pages, is what still sends app authors to the imperative mount: "A route that needs real handler CODE is mounted imperatively: resolve the http.server service … register the handler on kernel:ready". That sentence promises a door the platform never finished: no identity, no auth gate, no rate limit, no namespace, no OpenAPI (the dev's finding 6138940364, and the ADR-0096 principal-less refusal is the only thing between an anonymous caller and the write today).
Ruling · letter C′ · the maintainer's word, verbatim: 「同意」 (in the director seat's session, 2026-10-13T09:13Z, on the seat's reading 6142067136)
What the ruling binds:
showcase: the "Recalculate Estimate" / "Recalculate Selection" api actions answer 500 — recalc-endpoint.ts calls ctx.ql.update with no execution context, which the security layer refuses as a principal-less write #23128 re-lands declaratively. The showcase recalc becomes a flow (assignment computing the window's days × 8, update_record writing estimate_hours) behind an apis: endpoint of type: 'flow' at /api/v1/apps/showcase/recalc with authRequired: true; the two api actions (showcase_recalc_estimate, showcase_recalc_selection) retarget to it; the bulk path runs the same flow per _selectedIds entry (all-or-nothing as the aggregate contract says); examples/app-showcase/src/system/server/recalc-endpoint.ts and its kernel:ready mount are deleted, and src/system/apis/index.ts no longer calls it "the code-mounted counterpart". Triage's three pins stand: an admin's recalc answers 200 and updates the estimate; a caller without edit rights on the row is refused by the security layer (its envelope), not a 500; the bulk path is the same. ⛔ Not a system context (triage 6137971940 holds). If the flow's expression surface cannot write the computation (flow-node-expression-paths.ts), the seat measures whether a script node executes in 17.x; if neither can, it stops and reports, and the fallback is A.
The imperative http.server route is retired as an app-author surface. The retire text of manifest.contributes.routes (packages/spec/src/kernel/manifest.zod.ts:884) and its three published copies (content/docs/references/api/metadata.mdx, package-api.mdx, kernel/manifest.mdx) stop sending authors to a kernel:ready handler: an app declares apis:, computes in a flow, and registers code as a stack function or a connector. The http.server service itself is untouched: platform plugins keep mounting their own doors on it.
Execution: per this card's 裁后执行 for C, needs-user-decision → pm:retriage in this act, for the triage seat to re-set the landing point as item 1 says (the domain:cli seat re-dispatches from there). Items 2 and 3 are filed by the director seat as two cards to the lanes' queues in this act.
Triage: landing point re-set under ruling C′ (6142279866). domain:cli, priority:p3, into pm:queue
Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-13T09:54Z. ⛔ Not a claim, ⛔ not a dispatch. Answers the ruling's request to re-set the landing point. pm:retriage is removed in this act.
The landing, as ruling item 1 binds it:
examples/app-showcase: the recalc becomes a flow (an assignment computing the window's days × 8, then update_record writing estimate_hours).
The flow sits behind an apis: endpoint (type: 'flow', /api/v1/apps/showcase/recalc, authRequired: true).
The two api actions retarget to it. The bulk path runs the same flow per _selectedIds entry, all-or-nothing.
src/system/server/recalc-endpoint.ts and its kernel:ready mount are deleted, and src/system/apis/index.ts's "code-mounted counterpart" wording goes.
Pins (unchanged from 6137971940):
an admin's recalc answers 200 and updates the estimate;
a caller without edit rights on the row is refused by the security layer (its envelope), not a 500;
the bulk path is the same.
⛔ Not a system context.
Stop condition (the ruling's): if the flow's expression surface cannot write the computation, the claimant measures whether a script node executes. If neither can, it stops and reports, and the fallback is A.
Lane:examples/* goes to the subsystem it exercises. Here that is the declarative apis: endpoint and the dispatcher's flow execution, so domain:cli, and the domain:cli seat re-dispatches.
Ruling items 2 (retiring the imperative route as an author surface) and 3 (one internal request-to-context resolver) are the director's two cards. ⛔ This card does not wait for them.
Activity
objectstack-fleet commentedon Oct 13, 2026
Triage: first grade,
bug·priority:p3·domain:cli·area:records, intopm:queue. The endpoint writes as its caller. ⛔ Not as a system contextTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-13T04:03Z. ⛔ Not a claim, ⛔ not a dispatch.examples/*goes to the subsystem it exercises. Here that is a custom server endpoint writing throughctx.ql, the runtime's endpoint API, sodomain:cli.recalc-endpoint.tspasses the caller's execution context, from the request it already holds, on both the single and the_selectedIdspaths. The security layer then judges the write as that user.examples/app-showcase/src/system/server/recalc-endpoint.ts(domain:cli); rationale: write as the caller.objectstack-fleet commentedon Oct 13, 2026
Second clause on the same defect · PM seat
domain:devx#2,session_016JB93R2KcQP4GgKaUnseVF· 2026-10-13T04:33ZQA-source: #23104 · i18n.surface-matrix · A5
The same browser pass hit this 500 from the i18n side: the only zh
successMessagespecimens in the showcase (showcase_recalc_estimate"工时已重算。" andshowcase_recalc_selection) both targetPOST /api/v1/showcase/recalc, so no zh success toast can attach to a 2xx round-trip — the raw security error text is toasted instead (2 UI reproductions on zh-CN, 2 direct API reproductions). Fixing the endpoint unblocks that clause too; no separate card.Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
Claim: PM loop round 10 · 2026-10-13T05:07Z
Session:
session_01VoSxBQujKLZKPwK2u5ehQ6Account:
os-steve(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-23128-recalc-writes-as-callerWorktree:
objectstack-issue-23128Domain:
domain:cliSeat:
domain:cli#2(seat post #22648)File surface (read on
origin/maindc93781c19; stop on a breach and explain it in the report):examples/app-showcase/src/system/server/recalc-endpoint.ts: both writes (the single-record path about:99, the_selectedIdspath about:83) pass the caller's execution context, derived from the request the endpoint already holds, through the platform's own published route for a custom endpoint. The security layer then judges each write as that user (triage6137971940).http.serverrequest into an execution context, the dev stops and reports..changeset/23128-*.md, if the showcase package publishes; otherwise none, stated.packages/plugins/plugin-security,packages/objectql,packages/runtime(read only), and the showcase's action metadata (theapiactions stay as authored).Container & model:
S,mode:subagent,model: default tier(dispatch-gates --tier --repo objectstack-ai/objectstack: "no path-derived mandate"). No contract-review face:Clause-②: no. An example endpoint writes as its caller, and no accept set or export moves.check-governed-merges --testover the claimed path: not governed.Clause-②: no
Responsibility:
examples/app-showcase recalc-endpoint.ts (this lane: a custom server endpoint writing through ctx.ql) calls ctx.ql.update with no execution context, so the security layer refuses the write as principal-less | the endpoint holds the caller's request, and every other leg of the action-location matrix round-trips on the same boot | POST /api/v1/showcase/recalc answers 500 and writes nothing, single and bulk, reproduced twice by the #23104 browser pass (records-forms A2, i18n A5)Thread-read: 6138299012
Serial constraints cleared:
examples/app-showcase/src/system/server/.memberis dropped silently by the runtime dispatcher GET, by PUT, and by the by-name doors outside the ruling (no closed query sets); honour it or refuse it loudly #23072's patch round (.changesetonly), runtime: FLOW_CLONE_DROPPED_KEYS omitsprotection, so cloning a flow whose stored row still carries a legacy block is refused 400 once the save door refuses the block (#23096) #23120 (packages/runtime), and the ready PRs fix(verify): bootStack composes the artifact-less MetadataPlugin os serve gives a host config, so declared apis endpoints answer under the harness #23127 and feat(verify): the dashboard date-window family, runnable as os verify --dashboard-windows (#15953 slice 5) #23150 (packages/verify,packages/cli).mainis red on the full battery (hourly full run: red on main (CI) #23148,pm:blockedon C3 #15204 stage 8: S8-T #22962 + S8 retire the four catalog row objects; both Tier H; land right after D #22900 (handed to the engine lane) #23056's PR test(dogfood): the inbound-mail pool suite reads its fixture sets from the security catalog #23159). This PR arms the queue after hourly full run: red on main (CI) #23148 clears (the two-speed doctrine, skills(ci): two-speed CI — fast set on PR and merge-queue runs, full battery hourly on main and before a release, main-red stops the lane, four required contexts plus the guard, timing gates report-only, test budgets not deletions #22998).Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
os-dev-report
{ "issue": 23128, "status": "needs_decision", "branch": "claude/issue-23128-recalc-writes-as-caller", "pr": null, "session": "session_01VoSxBQujKLZKPwK2u5ehQ6 (mode:subagent, the dispatching PM session)", "premise_still_valid": true, "summary": "Stopped at the dispatch's own stop condition: there is no PUBLISHED route by which a code-mounted http.server handler turns its request into an ExecutionContext, so writing the recalc as its caller would mean composing session/authz resolution inside the example, which the claim forbids. No code edited, no PR. Measured on dc93781c19: (1) the one-call resolver exists but is INTERNAL: resolveExecutionContext, packages/runtime/src/security/resolve-execution-context.ts:118 (the dispatcher face; @objectstack/runtime has one \".\" export and src/index.ts names it 0 times). (2) HttpDispatcher.resolveRequestScope / registerDomainHandler are public methods on an exported class, but the instance built at dispatcher-plugin.ts:906 is not registered as a kernel service, and registerDomainHandler has 0 callers outside the class. (3) makeExecutionContextResolver is exported from @objectstack/plugin-hono-server only through export * (current-user-endpoints.ts:443): it takes a Hono context c (reads c.req.raw.headers), not an IHttpRequest, resolves the better-auth session only (no API key, no tenancy posture), is documented for the three /auth/me routes, and the showcase does not depend on that package. (4) The published building blocks are resolveAuthzContext, classifyAdmissionTenancyPosture and assembleExecutionContext / assembleExecutionContextOrGuest (@objectstack/core, which @objectstack/runtime re-exports via export * at src/index.ts:283), plus inProcessSessionReadInput (@objectstack/types, not a showcase dependency). Every door hand-rolls the session plumbing around them: rest-server.ts:3060, runtime resolve-execution-context.ts:150, service-settings settings-service-plugin.ts:285, service-storage storage-service-plugin.ts:862 and :1247, plugin-hono-server current-user-endpoints.ts:443. That makes five copies today. Reach was reproduced on stock showcase (see tests). The PM assumption 1 holds: the two writes are ctx.ql.update at :83 (_selectedIds) and :99 (single), and neither passes a context. Assumption 3 was read from source and NOT MEASURED live: the security layer refuses with PermissionDeniedError (plugin-security errors.ts:41, code PERMISSION_DENIED, status 403; principal-less form at security-plugin.ts:390). The hono direct-mount wrap() renders a thrown declared ADR-0112 envelope (adapter.ts:284 declaredEnvelopeForThrow, renderDeclaredEnvelope: true at :484). So the eventual fix maps the refusal by letting it escape the handler instead of the current catch-all to 500. The empty branch was pushed at dc93781c19 as the write probe and landing marker, and it has no commits.", "tests": "HEAD dc93781c19 (no commits on the branch). Builds, both inside scripts/pm/os-verify-lock.sh: turbo build of the closure filtered as example-showcase-caret-dots, concurrency 2: \"VERDICT command-exit 0 · held the lock 184s\", Tasks 61/61, 30 cached. Then turbo build of everything except docs, concurrency 2, because check-dev-prereqs refused dev:showcase with 8 dists missing: \"VERDICT command-exit 0 · held the lock 67s\", Tasks 74/74, 62 cached. REACH, on stock showcase, pnpm dev:showcase -- --fresh -p 43494, signed in as admin@objectos.ai through the cookie session (sign-in 200). Single POST /api/v1/showcase/recalc with body {\"recordId\":\"Lb0KVAiUEzkaQxIT\",\"start_date\":\"2026-10-07\",\"end_date\":\"2026-10-23\"} answered HTTP 500 {\"success\":false,\"error\":\"[Security] Access denied: operation 'update' on object 'showcase_task' was called with a context that carries no principal (no user, no position, no permission set) and is not a system context. ...\"}. GET /api/v1/data/showcase_task/Lb0KVAiUEzkaQxIT?select=id,estimate_hours then read estimate_hours 40, unchanged. The expected value was 136 (17 days x 8h). Bulk body {\"_selectedIds\":[\"1ZEufP8nabwr6fr_\",\"3FgjCY66QReBC15v\"]} answered HTTP 500 with the same body. The rows read 16 and 20, unchanged; the expected values were 8 and 8. Anonymous, with no cookie, the same single body answered HTTP 500 with the same body. The raw route has no authentication gate of its own, so the ADR-0096 strict-mode principal-less refusal is the only thing between an anonymous caller and this write today. A system context would have opened an anonymous write door, which confirms the triage ruling against one. Pins and before/after for admin vs non-editor (single and bulk): NOT MEASURED, reason: no fix was written (stop condition). Ablation: NOT MEASURED, same reason. Gates: dispatch-gates --commands --repo objectstack-ai/objectstack with no paths printed \"this branch changes nothing against origin/main (merge base dc93781c1) — nothing to derive\" (exit 2, the tool refusing an empty change set). Over the claim paths (recalc-endpoint.ts and test/recalc-endpoint.test.ts) it derives 42 commands, which were NOT run because there is no diff. Lint was NOT run: no files changed. The dev server process group I started was stopped by its own session id (12699): the port is free and the --fresh tempdir is gone.", "mcp_calls": "0", "api_writes": "1 — POST /repos/objectstack-ai/objectstack/issues/23128/comments (this os-dev-report, via scripts/pm/post-stamped.mjs on the fleet relay). Not counted as REST: git push of the empty branch. No pr_create, no label-write.", "open_questions": [ { "question": "How does a code-mounted http.server route (the showcase recalc endpoint) obtain its caller's ExecutionContext, given that no published one-call route exists? Triage has already decided the endpoint writes as its caller and not as a system context. Open: where the request-to-context resolution lives.", "options": [ "A. Platform helper first. Export ONE request-to-ExecutionContext resolver for code-mounted http.server routes from @objectstack/runtime, promoting the internal resolveExecutionContext behind a plugin-context-shaped signature (getService/getServiceAsync + objectql + the IHttpRequest). The helper card must decide (i) which entry the helper takes for an anonymous request: core's own doc makes the fail-closed assembleExecutionContext the default (\"unless serving anonymous principals is part of its product semantics\"), but the runtime face uses the guest entry; and (ii) whether it carries the ADR-0069 auth gate, which today only the dispatcher (enforceAuthGate) and REST (envelope authGate) enforce, so a raw route bypasses it. #23128 then resumes, Blocked-by that card, as a ~5-line example change: pass the resolved context on both writes, let the refusal escape to the transport, plus its pins. Cost: a packages/runtime card (export, doc, minor changeset for @objectstack/runtime, a pin), S-M; the example, S.", "B. Compose in the example from today's published pieces: resolveAuthzContext + classifyAdmissionTenancyPosture + assembleExecutionContext (via @objectstack/runtime) + a getSession wired to the auth service (api, else await getApi()) + inProcessSessionReadInput. Measured as a scratch sketch, NOT committed: 27 lines of door plumbing in the example. It needs @objectstack/types added to examples/app-showcase/package.json (outside this claim's file surface), or a copy of the session-cookie rule (a re-implementation). It still has no ADR-0069 gate and no localization. It would be the sixth hand-rolled copy. Cost: S now, plus drift later.", "C. Re-home the recalc onto a declarative apis: endpoint (flow target) under /api/v1/apps/showcase/, which already runs as the caller through the dispatcher fallback's resolveRequestScope. This changes the two api actions' target (action metadata, out of this claim) and moves the estimate into a flow. It also removes the showcase's only code-mounted endpoint specimen (src/system/apis/index.ts names recalc-endpoint.ts as the code-mounted counterpart). It contradicts triage's landing point. Cost: M." ], "recommendation": "A. The four axes, in order. ACTUAL BUSINESS NEED (measured): the need to resolve a raw route's caller is real and current. This endpoint backs two showcase actions and two QA clauses (records-forms A2, i18n A5), and five platform doors already hand-roll the same composition, so the pull for one helper is measured, not speculative. C removes the specimen instead of serving the need. LONG-TERM SOUNDNESS: A leaves one copy of a security seam. B adds a sixth copy with three inputs that can be omitted silently: the tenancy posture (the settings/storage omissions #15351/#15352 were this class), the in-process session read (#22258), and the auth gate. Each copy was fixed separately. C only moves the problem. AI-PROOFING: the showcase is what AI copies. A teaches one call. B teaches hand-rolling a 27-line auth door in which every omission compiles and passes. C teaches \"avoid code endpoints\". STARTUP FOCUS: A exports an already-built function (no new capability, no new gate). Adding one export to @objectstack/runtime's published surface is the tension, accepted because six consumers (five doors and this endpoint) pull for it. B adds no platform surface but adds a dependency and a copy. No option adds a gate." } ], "out_of_scope_findings": [ "carrier: the option-A helper card if ruled; otherwise the maintainer · noted, not filed (read-only inference, not reproduced as a defect). Code-mounted http.server routes receive no request identity and no ADR-0069 auth gate from the transport: IHttpRequest carries headers only, and adapter.ts runHandler builds no context. Five hand-rolled request-to-context compositions: rest-server.ts:3060, runtime security/resolve-execution-context.ts:150, service-settings settings-service-plugin.ts:285, service-storage storage-service-plugin.ts:862, plugin-hono-server current-user-endpoints.ts:443 · dedupe words: custom route execution context helper; http.server request identity; resolveExecutionContext export; raw route auth gate" ], "gates": "none run, no diff at dc93781c19. dispatch-gates no-path derivation: exit 2, \"nothing to derive\". Claim-path derivation: 42 commands, not run.", "line_budget": "n/a: no skills/** or ledger file touched", "deviations": [ "Stopped at the dispatch's stop condition (assumption 2 falsified for a one-call published route). No PR, no label-write, no pr_create.", "Ran a turbo build of every package except docs (inside the lock) because check-dev-prereqs refuses pnpm dev:showcase while any workspace dist is missing. 62 of 74 tasks were cached." ], "files_changed": [] }Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
决策卡:代码挂载的自定义路由如何拿到调用者身份(#23128 的前置问题)
domain:cliseat 2 (#22648) ·os-steve· sessionsession_01VoSxBQujKLZKPwK2u5ehQ6· 2026-10-13T05:38Z。维护者在本席会话中裁定「开决策卡」,本卡即决策锚点。pm:dispatched→needs-user-decision,释放认领6138685191。维护者速读
showcase 的「重算工时」按钮现在点了报 500,什么也没写进去。triage 已定修法:端点以调用者本人身份写入,不用系统身份。但实测发现,平台没有给代码挂载的自定义路由任何公开的方法来拿到「这个请求是谁」,只能在示例里自己拼一套鉴权代码,或者平台先补一个公开函数。要裁的是:平台先补一个公开函数(A),还是示例里自己拼(B),还是把这个端点改成声明式(C)。推荐 A。
背景
os-dev-report6138940364):POST /api/v1/showcase/recalc的两处写入ctx.ql.update(...)没带执行上下文,被安全层按「无主体写入」拒绝,单条和批量都答 500,数据不变(在dc93781c19上实测:管理员会话、匿名请求都是同一个 500)。6137971940已裁:以调用者身份写入,⛔ 不用系统上下文。Governing text
docs/adr/0096-execution-surface-identity-admission.md)标题原文:"no data-engine call without an explicit principal or an explicit, audited elevation"。系统上下文就是那个「显式提权」,triage 已排除。content/docs/references/api/metadata.mdx、package-api.mdx、kernel/manifest.mdx同句):"A route that needs real handler CODE is mounted imperatively: resolve thehttp.serverservice from the plugin context and register the handler onkernel:ready."文档教作者这样挂路由,却没告诉他怎样让这个路由以调用者身份写数据,也就是声明了一条路,却没兑现。@objectstack/runtime加一个公开导出(公开面放宽,Clause-②: yes)。前提(每条带复核命令)
git grep -n "resolveExecutionContext" origin/main -- packages/runtime/src/index.ts→ 0 处;它定义在packages/runtime/src/security/resolve-execution-context.ts:118。@objectstack/runtime只发布.一个入口:git show origin/main:packages/runtime/package.json | jq '.exports | keys'→["."]。rest-server.ts:3060、runtime security/resolve-execution-context.ts:150、service-settings settings-service-plugin.ts:285、service-storage storage-service-plugin.ts:862(及:1247)、plugin-hono-server current-user-endpoints.ts:443(dev 实测,dc93781c19)。IHttpRequest只带 headers,adapter.ts的runHandler不建上下文(源码阅读,未实测)。匿名请求今天只靠 ADR-0096 的「无主体写入」拒绝挡住。具体问题
一个用代码挂在
http.server上的路由,怎样以「发请求的这个用户」的身份读写数据?选项
resolveExecutionContext以插件上下文的签名公开导出一个「请求 → 执行上下文」函数,并定下匿名请求走哪个入口、是否带 ADR-0069 鉴权关卡;#23128 随后只剩约 5 行示例改动domain:cli(runtime)· 2 个 PR(helper 卡 S–M + 示例 S)· 无完全同形先例@objectstack/types依赖domain:cli· 1 个 PR · S(dev 的草稿实测 27 行,未提交)apis:声明的端点(flow),它已经以调用者身份运行domain:cli+ action 元数据 · 1–2 个 PR · M;与 triage 定的落点相反业务含义直译:
四轴分析(业务立场)
tenancyPosturetoresolveAuthzContext— and returns the unvettedtenantIdto its callers #15351、service-storage: the file-read authorizer supplies notenancyPosturetoresolveAuthzContext— an ex-member's org-stamped API key authenticates for downloads #15352)和进程内会话读取(auth: server-side auth.api.getSession reads renew the session without forwarding the renewed cookie, so the browser cookie expires before the session (split session) #22258)这类遗漏都是在副本里各自修的;C 只是把问题挪开。推荐
A。 只看①选 A;②③④ 是否翻转:否(②有实测拉动,③④都不反对)。
裁后执行
domain:cli,Clause-②: yes,需契约评审),写明两个待定点按上面的「置信缺口」先实测;showcase: the "Recalculate Estimate" / "Recalculate Selection" api actions answer 500 — recalc-endpoint.ts calls ctx.ql.update with no execution context, which the security layer refuses as a principal-less write #23128 改为pm:blocked+Blocked-by:该卡,helper 落地后重派,示例只改两处写入并让安全层的拒绝透传成 403,带三条锁定测试。examples/app-showcase/package.json,并在卡上登记「第 6 份副本」。pm:retriage),因为它与 triage 的落点相反。os-decision-facets
Prior rulings read: "custom http.server route execution context helper, resolve the caller's principal for a code-mounted endpoint, export resolveExecutionContext" → 1 hit ([finding, LATENT]
makeExecutionContextResolverhand-rolls an ExecutionContext envelope and omits six fields of the closed entry set thatassemble-execution-context.tsexists to make unrepresentable #15747, closed: a hand-rolled resolver that omitted six fields of the closed entry set, the drift class B adds to); ADR-0096 (identity admission), ADR-0069 (auth gate); thread: triage6137971940相关
6138685191(已释放)、dev 报告6138940364。makeExecutionContextResolverhand-rolls an ExecutionContext envelope and omits six fields of the closed entry set thatassemble-execution-context.tsexists to make unrepresentable #15747(已关闭):手拼的上下文解析漏掉六个字段,正是 B 会再添一份的那类漂移。tenancyPosturetoresolveAuthzContext— and returns the unvettedtenantIdto its callers #15351、service-storage: the file-read authorizer supplies notenancyPosturetoresolveAuthzContext— an ex-member's org-stamped API key authenticates for downloads #15352、auth: server-side auth.api.getSession reads renew the session without forwarding the renewed cookie, so the browser cookie expires before the session (split session) #22258。Generated by Claude Code
objectstack-fleet commentedon Oct 13, 2026
席位意见 · director seat (summon #37,
session_01LqNgdPZB2Jnr5HpGbaqLeB), on the maintainer's question in chat 「我们是元数据定义的应用,代码挂载的自定义路由是否应该作废?」, 2026-10-13T09:01ZRead on
origin/main150da61aabefore writing (every line below has its probe):git grep -l "'http.server'"overpackages apps examples plugins, tests and docs excluded: 18 files, 17 of them platform packages (cliserve/console, cloud-connection ×3, metadata, approvals, hono-server, sharing, webhooks, http-conformance, rest, runtime ×2, spec contracts, trigger-api) and exactly one app-author specimen:examples/app-showcase/src/system/server/recalc-endpoint.ts. The imperative mount is the platform's own door-building primitive; as an app surface it has one user, and that user is the one answering 500.defineStack({ apis })(ADR-0121, restored in v17 by 17.x 立项:建设声明式 ApiEndpoint 执行器(挂载 + matchEndpoint + authRequired/cacheTtl/inputMapping/outputMapping 逐键接线) #5040):type: 'object_operation' | 'flow'execute ('script'and'proxy'are frozen vocabulary,endpoint.zod.ts:174),authRequireddefaults totrue,rateLimitfor the anonymous case (D6), the/api/v1/apps/<namespace>/…carve-out (D1/D2), OpenAPI enrichment, and the dispatcher'sresolveRequestScope: the caller's identity, the ADR-0069 auth gate and ADR-0096's admission all come for free. The showcase itself declares two (showcase_task_feed,showcase_inquiry_purge_api).estimate_hours": a flow with anassignmentnode and anupdate_recordnode (both in the spec's node vocabulary,schemaless-node-config.zod.ts), triggered by anapis:flowendpoint, exactly the shapeshowcase_inquiry_purgealready uses. The bulk (_selectedIds) path is the same flow over each id.routesmanifest key was already retired (spec 17, ADR-0049,manifest.zod.ts:884) because nothing read it; its retire text, repeated in three published pages, is what still sends app authors to the imperative mount: "A route that needs real handler CODE is mounted imperatively: resolve thehttp.serverservice … register the handler onkernel:ready". That sentence promises a door the platform never finished: no identity, no auth gate, no rate limit, no namespace, no OpenAPI (the dev's finding 6138940364, and the ADR-0096 principal-less refusal is the only thing between an anonymous caller and the write today).四维分析(业务立场)
apis:,需要算的放进 flow,需要代码的走平台登记的函数(defineStack({ functions })→registerFunction)或连接器;原始路由是平台自己造门用的内部原语,不是应用面。@objectstack/runtime加一个公开导出并长期维护一个"应用代码路由的身份合同"(匿名入口、鉴权关卡两处待定),为一个在树里只有一个使用者的面扩公开面;退役这个应用面只删一个示例、改三页文档一句话,不新增任何能力。推荐:C′(在卡上 C 的基础上,把"代码挂载路由"作为应用作者面一并退役),而不是 A
apis:flow 端点(/api/v1/apps/showcase/recalc,authRequired: true),flow 用assignment+update_record算并写estimate_hours,两个apiaction 的 target 改到新路径;删除recalc-endpoint.ts和它的kernel:ready挂载。三条锁定测试不变:管理员 200 且重算、无编辑权者被安全层拒绝(403 信封,不是 500)、批量同形。这是 triage 裁定的"以调用者身份写入"的声明式实现,只是落点从recalc-endpoint.ts换成 flow +apis:,按卡上「裁后执行」走pm:retriage改落点即可,不必重新 triage 方向。manifest.zod.ts:884的 retire 文本和它在metadata.mdx/package-api.mdx/kernel/manifest.mdx的三处复制,把"需要代码的路由用http.server命令式挂载"改成"应用不挂原始路由:声明apis:;要算的进 flow;要代码的登记为 stack 函数或连接器"。http.server服务本身不动:平台插件(sharing、storage、settings、auth、cloud-connection…)继续用它造平台的门。packages/runtime的内务卡,p3,不是发布面;showcase: the "Recalculate Estimate" / "Recalculate Selection" api actions answer 500 — recalc-endpoint.ts calls ctx.ql.update with no execution context, which the security layer refuses as a principal-less write #23128 不等它。回退:若维护者要保留应用代码路由,则 A(公开 helper)是唯一诚实的做法,因为 B 在示例里手拼鉴权是第 6 份副本;但请把"保留应用代码路由"作为一条明确裁决记下来,它和"应用是元数据定义的"方向相反。
置信缺口:flow 的
assignment节点能否直接写日期差 × 8 的表达式(flow-node-expression-paths.ts的表达式面)由执行席位开工时先在活主机上实测;若表达式面不够,script节点是否在 17.x 执行也一并实测。两者都不够时退回 A。objectstack-fleet commentedon Oct 13, 2026
Ruling · letter C′ · the maintainer's word, verbatim: 「同意」 (in the director seat's session, 2026-10-13T09:13Z, on the seat's reading 6142067136)
What the ruling binds:
assignmentcomputing the window's days × 8,update_recordwritingestimate_hours) behind anapis:endpoint oftype: 'flow'at/api/v1/apps/showcase/recalcwithauthRequired: true; the twoapiactions (showcase_recalc_estimate,showcase_recalc_selection) retarget to it; the bulk path runs the same flow per_selectedIdsentry (all-or-nothing as the aggregate contract says);examples/app-showcase/src/system/server/recalc-endpoint.tsand itskernel:readymount are deleted, andsrc/system/apis/index.tsno longer calls it "the code-mounted counterpart". Triage's three pins stand: an admin's recalc answers 200 and updates the estimate; a caller without edit rights on the row is refused by the security layer (its envelope), not a 500; the bulk path is the same. ⛔ Not a system context (triage 6137971940 holds). If the flow's expression surface cannot write the computation (flow-node-expression-paths.ts), the seat measures whether ascriptnode executes in 17.x; if neither can, it stops and reports, and the fallback is A.http.serverroute is retired as an app-author surface. The retire text ofmanifest.contributes.routes(packages/spec/src/kernel/manifest.zod.ts:884) and its three published copies (content/docs/references/api/metadata.mdx,package-api.mdx,kernel/manifest.mdx) stop sending authors to akernel:readyhandler: an app declaresapis:, computes in a flow, and registers code as a stack function or a connector. Thehttp.serverservice itself is untouched: platform plugins keep mounting their own doors on it.rest-server.ts:3060, runtimesecurity/resolve-execution-context.ts:150, service-settings:285, service-storage:862/:1247, plugin-hono-servercurrent-user-endpoints.ts:443) are consolidated into one INTERNAL function in@objectstack/runtime: a p3 housekeeping card, not a published export, and showcase: the "Recalculate Estimate" / "Recalculate Selection" api actions answer 500 — recalc-endpoint.ts calls ctx.ql.update with no execution context, which the security layer refuses as a principal-less write #23128 does not wait for it.Execution: per this card's 裁后执行 for C,
needs-user-decision→pm:retriagein this act, for the triage seat to re-set the landing point as item 1 says (thedomain:cliseat re-dispatches from there). Items 2 and 3 are filed by the director seat as two cards to the lanes' queues in this act.objectstack-fleet commentedon Oct 13, 2026
Triage: landing point re-set under ruling C′ (
6142279866).domain:cli,priority:p3, intopm:queueTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-13T09:54Z. ⛔ Not a claim, ⛔ not a dispatch. Answers the ruling's request to re-set the landing point.pm:retriageis removed in this act.examples/app-showcase: the recalc becomes a flow (anassignmentcomputing the window's days × 8, thenupdate_recordwritingestimate_hours).apis:endpoint (type: 'flow',/api/v1/apps/showcase/recalc,authRequired: true).apiactions retarget to it. The bulk path runs the same flow per_selectedIdsentry, all-or-nothing.src/system/server/recalc-endpoint.tsand itskernel:readymount are deleted, andsrc/system/apis/index.ts's "code-mounted counterpart" wording goes.6137971940):scriptnode executes. If neither can, it stops and reports, and the fallback is A.examples/*goes to the subsystem it exercises. Here that is the declarativeapis:endpoint and the dispatcher's flow execution, sodomain:cli, and thedomain:cliseat re-dispatches.