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
server: the public form submit answer carries the record fields its thank-you panel names (#28005 server half) #28443
Filing gate: ③ maintainer-ruled split. #28005 was ruled B by the maintainer at 2026-10-31 15:10Z (ruling record 6545210989): spec first, then server, then ui. This is the server step.
Reach: web-to-case and any public form whose visitor needs a reference (a case number) on the thank-you panel (#27398 row 3).
Duplicate search: open domain:server cards with "form" or "thank" in the title. None covers the submit answer.
Blocked-by: #28440 (spec half: the slot, thankYouRecordFieldNames, PublicFormSubmitResponseSchema). Names are pending the maintainer's approval, so read the merged names.
Wanted
POST /api/v1/forms/SLUG/submit (packages/rest/src/form-routes.ts) answers with PublicFormSubmitResponseSchema. That is id always, plus fields holding exactly the stored values of the names thankYouRecordFieldNames(form.submitBehavior) returns, and only when it returns at least one.
⛔ No other field. The route's own comment stays true: the stored row can carry values an elevated hook derived from records the anonymous grant may never read. The spec's lint rule already admits only RUNTIME_OWNED_FIELD_TYPES (today autonumber). The server still re-checks each named field's type against that set at answer time, and drops a name that does not pass. That covers an object retyped after publish.
Name the schema as the route's responseSchema in rest-route-ledger.ts.
Tests
A form whose message names an autonumber field answers { id, fields: { that_field } }.
A form with no token answers { id } only.
A name whose field was retyped to text after publish is dropped.
Ablation: answering the whole stored row reds the test.
Then
The ui half (FormPage.tsx fills the tokens) is filed beside this card and is blocked by it.
The maintainer said 「同意」 at 2026-10-31T20:29Z. That approves the four spec names as proposed, and this half reuses them as written: PublicFormSubmitResponseSchema / PublicFormSubmitResponse (@objectstack/spec/api, with fields beside id), thankYouRecordFieldNames (@objectstack/spec/ui), and lint rule thank-you-record-field.
Claim: maintainer-ruled split, server step (filing gate ③), unblocked by #28440 · card thread · 2026-10-31T21:30Z
Session: session_01L9qibz3ZUbZ8Qcn1rDw9yc (the seat); the card thread's session is named in its first report
Account: os-tesla (the seat's linked user; the card's assignee)
Branch: the card thread's harness-pinned claude/project-thread-* branch, named in an amendment
Worktree: the card thread's own container checkout
Domain: domain:server
Seat: domain:server#1
Ruling-ref: 6548758413 (names A, Tesla 「同意」 2026-10-31T20:29Z), under #28005 ruling B 6545210989
File surface: packages/rest/src/form-routes.ts, rest-route-ledger.ts, their tests, docs lines that state the submit answer, and a .changeset/28443-*.md. ⛔ No packages/spec, no metadata-protocol/src/protocol.ts.
Container & model: S, mode:thread, model: opus, effort high; contract-review tier before the queue
Clause-②: yes (widening: the submit answer may carry the panel-named runtime-owned values; the dev confirms from the diff)
Metadata-protocol: declared from the diff
Thread-read: 6548758413
Premise: the spec half #28440 is merged; the submit route answers { id } only today. The dev measures this first.
Serial constraints cleared: no in-flight PR of this seat touches form-routes.ts
Resume-from: none (fresh from origin/main)
Order: /mnt/project-files/server-seat-1/r2026-10-31/dispatch-28443.md (project file)
State: pm:queue → pm:dispatched, assigned to os-tesla, recorded by this claim.
Claim amendment to 6549394777 · 2026-10-31T21:32Z · branch named
Branch: claude/project-thread-c1oruc (the card thread's harness-pinned branch)
Session: the card thread is session_01L9qibzzJHmF6J8Rdez8TWu
Everything else stands as claimed.
{
"issue": 28443,
"status": "done",
"branch": "claude/project-thread-c1oruc",
"pr": "https://github.com/objectstack-ai/objectstack/pull/28479",
"session": "session_01L9qibzzJHmF6J8Rdez8TWu",
"premise_still_valid": true,
"summary": "POST /forms/:slug/submit now answers PublicFormSubmitResponse: id, plus fields holding the stored values of the names thankYouRecordFieldNames(form.submitBehavior) returns. thankYouAnswerFields (form-routes.ts, not exported) keeps a name only when the object's current declaration types it in RUNTIME_OWNED_FIELD_TYPES and createData's stripped and masked row carries it as a string or a number; fields is omitted when none survives. The object read is memoised and shared with the required/file/option judgements. Ledger row names responseSchema PublicFormSubmitResponseSchema; the tripwire disposition moves to protocol-ingress; forms.mdx and public-data-collection.mdx state the answer; changeset patch @objectstack/rest. Premise measured live on 9b1dc992: a form naming {{record.case_number}} answered {id} only while the stored row held CASE-0001.",
"tests": "head ab25d2a7: public-form-submit-answer.test.ts 10/10, with a new [#28005] block (autonumber answered, title+message once, no token gives {id}, retyped-to-text dropped, system column/lookup/constructor dropped, absent and null dropped, ledger row pin). Every answer is parsed with the strict PublicFormSubmitResponseSchema. Full rest: Test Files 363 passed (363), Tests 7166 passed 352 skipped. rest typecheck exit 0. client route-ledger-response-schema + client-url-conformance 10/10. Ablations through ablation-replace on src (no dist), anchor 1->0, restored blob == HEAD bd027a8f4c2a: whole-row answer 3/10 red; type rule removed 2/10 red; value rule removed 2/10 red. A first own-key check stayed green under ablation (redundant with the value rule) and was folded into it (ba54dc43). Live on ab25d2a7 (showcase --fresh): token form gave {id, fields:{case_number:CASE-0001}} 201; contact-us gave {id} 201; after a forced retype to text the answer was {id} 201.",
"gates": "dispatch-gates --commands derived 91 families on ab25d2a7, each run with stdin from /dev/null, exit captured by redirect: 91 exit 0. Four were first non-zero on build state: check:plugin-teardown-shape --self-test (exit 3, shallow clone, re-run after fetching its fixture commit); check:skill-examples (exit 3, re-run after building client and client-react with dts); check:dts-closure and check:dual-build-cjs-loads (exit 1, OS_SKIP_DTS build, re-run after a forced full non-ui build). --ran: 91 accounted, 0 NOT-MEASURED, exit 0. Scoped lint (repo eslint --no-inline-config packages/rest/src): exit 0. CI check-runs on PR: in_progress at report time.",
"line_budget": "8 files, +241 / -19",
"files_changed": [
".changeset/28443-public-form-submit-thank-you-fields.md",
"content/docs/ui/forms.mdx",
"content/docs/ui/public-data-collection.mdx",
"packages/rest/src/form-routes.ts",
"packages/rest/src/public-form-submit-answer.test.ts",
"packages/rest/src/rest-route-ledger.ts",
"packages/rest/src/rest-server.ts",
"packages/rest/src/rest-write-response-internal-fields.tripwire.test.ts"
],
"deviations": [
"Live measure booted examples/app-showcase's own dev script (objectstack dev --fresh -p 38443) rather than root pnpm dev, because root dev's check-dev-prereqs refused on 33 unbuilt @object-ui packages that the API backend does not load. Server killed by recorded PID afterwards.",
"The first dispatch-gates --commands capture was cut at 44 lines by a head pipe on tee. Re-derived to a file and the remaining 47 run; the reconciliation above is over the full 91.",
"No PR assignee or reviewer written (frame rule; the harness default to assign os-tesla was not followed). The PR body's first line is the harness attribution comment, kept as required."
],
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "0 — card and comments read through gh api REST GETs; 0 writes",
"api_writes": "2 — relay pr_create (run 41248523716, -> #28479, read-back identical 10064 bytes); post-stamped comment on #28443 (this report)",
"open_questions": [
{ "question": "When every named field is dropped, should the answer omit fields or carry fields: {}?", "options": ["A: omit (this PR; never an empty map)", "B: carry {} whenever the panel names at least one field"], "recommendation": "A, because the schema describes fields as holding values and a renderer reading fields?.[name] sees no difference" }
],
"out_of_scope_findings": [
"carrier: ui half #28444 · documenting that a thank-you panel may name an autonumber field (forms.mdx thank-you row, skills) waits for the console to fill the tokens; this PR documents only the wire answer",
"carrier: none · packages/verify/src/handle.ts run() docblock still says the public form route answers { id }; true for every form whose panel names no field; outside this card's file surface"
]
}
git grep -c thankYouAnswerFields in rest/src/form-routes.ts on origin/main
present
Landed: this is the server half of Public form thank-you text cannot name the record it created: no template slot, and the submit answer carries the id only #28005 ruling B, using the names approved under ruling A (6548758413). A public form submit now returns id plus the values of fields that the thank-you text names, but only system-generated ones (today autonumber). A field whose type has changed since publish is left out. A form that names no fields still answers { id }. @objectstack/rest ships a changeset. The card closed via Fixes.
Activity
objectstack-fleet commentedon Oct 31, 2026
domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm
Ruling-ref: 6548758413 (#28440) · 2026-10-31T20:32Z
The maintainer said 「同意」 at 2026-10-31T20:29Z. That approves the four spec names as proposed, and this half reuses them as written:
PublicFormSubmitResponseSchema/PublicFormSubmitResponse(@objectstack/spec/api, withfieldsbesideid),thankYouRecordFieldNames(@objectstack/spec/ui), and lint rulethank-you-record-field.objectstack-fleet commentedon Oct 31, 2026
domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc
Claim: maintainer-ruled split, server step (filing gate ③), unblocked by #28440 · card thread · 2026-10-31T21:30Z
Session:
session_01L9qibz3ZUbZ8Qcn1rDw9yc(the seat); the card thread's session is named in its first reportAccount:
os-tesla(the seat's linked user; the card's assignee)Branch: the card thread's harness-pinned
claude/project-thread-*branch, named in an amendmentWorktree: the card thread's own container checkout
Domain:
domain:serverSeat:
domain:server#1Ruling-ref:
6548758413(names A, Tesla 「同意」 2026-10-31T20:29Z), under #28005 ruling B6545210989File surface:
packages/rest/src/form-routes.ts,rest-route-ledger.ts, their tests, docs lines that state the submit answer, and a.changeset/28443-*.md. ⛔ Nopackages/spec, nometadata-protocol/src/protocol.ts.Container & model:
S,mode:thread,model: opus, efforthigh; contract-review tier before the queueClause-②: yes (widening: the submit answer may carry the panel-named runtime-owned values; the dev confirms from the diff)
Metadata-protocol: declared from the diff
Thread-read: 6548758413
Premise: the spec half #28440 is merged; the submit route answers
{ id }only today. The dev measures this first.Serial constraints cleared: no in-flight PR of this seat touches
form-routes.tsResume-from: none (fresh from
origin/main)Order:
/mnt/project-files/server-seat-1/r2026-10-31/dispatch-28443.md(project file)State:
pm:queue→pm:dispatched, assigned toos-tesla, recorded by this claim.objectstack-fleet commentedon Oct 31, 2026
domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc
Claim amendment to
6549394777· 2026-10-31T21:32Z · branch namedBranch:
claude/project-thread-c1oruc(the card thread's harness-pinned branch)Session: the card thread is
session_01L9qibzzJHmF6J8Rdez8TWuEverything else stands as claimed.
objectstack-fleet commentedon Oct 31, 2026
domain:server#1 · os-tesla · session_01L9qibzzJHmF6J8Rdez8TWu
os-dev-report
{ "issue": 28443, "status": "done", "branch": "claude/project-thread-c1oruc", "pr": "https://github.com/objectstack-ai/objectstack/pull/28479", "session": "session_01L9qibzzJHmF6J8Rdez8TWu", "premise_still_valid": true, "summary": "POST /forms/:slug/submit now answers PublicFormSubmitResponse: id, plus fields holding the stored values of the names thankYouRecordFieldNames(form.submitBehavior) returns. thankYouAnswerFields (form-routes.ts, not exported) keeps a name only when the object's current declaration types it in RUNTIME_OWNED_FIELD_TYPES and createData's stripped and masked row carries it as a string or a number; fields is omitted when none survives. The object read is memoised and shared with the required/file/option judgements. Ledger row names responseSchema PublicFormSubmitResponseSchema; the tripwire disposition moves to protocol-ingress; forms.mdx and public-data-collection.mdx state the answer; changeset patch @objectstack/rest. Premise measured live on 9b1dc992: a form naming {{record.case_number}} answered {id} only while the stored row held CASE-0001.", "tests": "head ab25d2a7: public-form-submit-answer.test.ts 10/10, with a new [#28005] block (autonumber answered, title+message once, no token gives {id}, retyped-to-text dropped, system column/lookup/constructor dropped, absent and null dropped, ledger row pin). Every answer is parsed with the strict PublicFormSubmitResponseSchema. Full rest: Test Files 363 passed (363), Tests 7166 passed 352 skipped. rest typecheck exit 0. client route-ledger-response-schema + client-url-conformance 10/10. Ablations through ablation-replace on src (no dist), anchor 1->0, restored blob == HEAD bd027a8f4c2a: whole-row answer 3/10 red; type rule removed 2/10 red; value rule removed 2/10 red. A first own-key check stayed green under ablation (redundant with the value rule) and was folded into it (ba54dc43). Live on ab25d2a7 (showcase --fresh): token form gave {id, fields:{case_number:CASE-0001}} 201; contact-us gave {id} 201; after a forced retype to text the answer was {id} 201.", "gates": "dispatch-gates --commands derived 91 families on ab25d2a7, each run with stdin from /dev/null, exit captured by redirect: 91 exit 0. Four were first non-zero on build state: check:plugin-teardown-shape --self-test (exit 3, shallow clone, re-run after fetching its fixture commit); check:skill-examples (exit 3, re-run after building client and client-react with dts); check:dts-closure and check:dual-build-cjs-loads (exit 1, OS_SKIP_DTS build, re-run after a forced full non-ui build). --ran: 91 accounted, 0 NOT-MEASURED, exit 0. Scoped lint (repo eslint --no-inline-config packages/rest/src): exit 0. CI check-runs on PR: in_progress at report time.", "line_budget": "8 files, +241 / -19", "files_changed": [ ".changeset/28443-public-form-submit-thank-you-fields.md", "content/docs/ui/forms.mdx", "content/docs/ui/public-data-collection.mdx", "packages/rest/src/form-routes.ts", "packages/rest/src/public-form-submit-answer.test.ts", "packages/rest/src/rest-route-ledger.ts", "packages/rest/src/rest-server.ts", "packages/rest/src/rest-write-response-internal-fields.tripwire.test.ts" ], "deviations": [ "Live measure booted examples/app-showcase's own dev script (objectstack dev --fresh -p 38443) rather than root pnpm dev, because root dev's check-dev-prereqs refused on 33 unbuilt @object-ui packages that the API backend does not load. Server killed by recorded PID afterwards.", "The first dispatch-gates --commands capture was cut at 44 lines by a head pipe on tee. Re-derived to a file and the remaining 47 run; the reconciliation above is over the full 91.", "No PR assignee or reviewer written (frame rule; the harness default to assign os-tesla was not followed). The PR body's first line is the harness attribution comment, kept as required." ], "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "0 — card and comments read through gh api REST GETs; 0 writes", "api_writes": "2 — relay pr_create (run 41248523716, -> #28479, read-back identical 10064 bytes); post-stamped comment on #28443 (this report)", "open_questions": [ { "question": "When every named field is dropped, should the answer omit fields or carry fields: {}?", "options": ["A: omit (this PR; never an empty map)", "B: carry {} whenever the panel names at least one field"], "recommendation": "A, because the schema describes fields as holding values and a renderer reading fields?.[name] sees no difference" } ], "out_of_scope_findings": [ "carrier: ui half #28444 · documenting that a thank-you panel may name an autonumber field (forms.mdx thank-you row, skills) waits for the console to fill the tokens; this PR documents only the wire answer", "carrier: none · packages/verify/src/handle.ts run() docblock still says the public form route answers { id }; true for every form whose panel names no field; outside this card's file surface" ] }objectstack-fleet commentedon Oct 31, 2026
domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc
Landing record · #28443 · PR #28479
domain:serverseat 1 ·session_01L9qibz3ZUbZ8Qcn1rDw9yc· 2026-10-31T23:14ZGET pulls/2847993c0a639git merge-base --is-ancestor 93c0a639 origin/maingit grep -c thankYouAnswerFieldsinrest/src/form-routes.tsonorigin/main6548758413). A public form submit now returnsidplus the values of fields that the thank-you text names, but only system-generated ones (todayautonumber). A field whose type has changed since publish is left out. A form that names no fields still answers{ id }.@objectstack/restships a changeset. The card closed viaFixes.Release: claim
6549394777(session_01L9qibz3ZUbZ8Qcn1rDw9yc, branchclaude/project-thread-c1oruc) · landed, card closed.pm:dispatchedremoved, assignee cleared.