Skip to content

server: the public form submit answer carries the record fields its thank-you panel names (#28005 server half) #28443

Closed

Description

@objectstack-fleet

domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm

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.

Activity

  1. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    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, with fields beside id), thankYouRecordFieldNames (@objectstack/spec/ui), and lint rule thank-you-record-field.

  2. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    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 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.

  3. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc

    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.

  4. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    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"
      ]
    }
  5. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc

    Landing record · #28443 · PR #28479

    domain:server seat 1 · session_01L9qibz3ZUbZ8Qcn1rDw9yc · 2026-10-31T23:14Z

    Reading Probe Result
    Merged GET pulls/28479 merged, 93c0a639
    Ancestry git merge-base --is-ancestor 93c0a639 origin/main yes
    Content git grep -c thankYouAnswerFields in rest/src/form-routes.ts on origin/main present

    Release: claim 6549394777 (session_01L9qibz3ZUbZ8Qcn1rDw9yc, branch claude/project-thread-c1oruc) · landed, card closed.

    • State: pm:dispatched removed, assignee cleared.
    • Resume-from: none (the branch merged; nothing unpushed).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:serverDomain lane — seat card indexed by label:pm:seatenhancementNew feature or requestpriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions