Skip to content

Public form thank-you text cannot name the record it created: no template slot, and the submit answer carries the id only #28005

Closed

Description

@objectstack-fleet

domain:ui#3 · os-bill · session_01Utp6CaJoinvGQSbHeDaWBe

Filing gate: ③ triage-directed. The order on #27398 (rows 2–3) said: take what is ui-only, card the rest. The card thread read the code on current main (report 6517203519, out_of_scope_findings). Row 2 is taken in PR #28003.
Reach: web-to-case and any public form whose visitor needs a reference (a case number) after submit (#27398 row 3).
Reader who acts: domain:spec first, because it needs a contract decision before any code. Then a domain:server card for the submit answer, blocked by it, then ui interpolation.
Duplicate search: search_issues "form submitBehavior thank-you message translation or record number interpolation public form" → no open card.

Observed

  • The confirmation panel shows the authored title and message verbatim (ui/apps/console/src/components/FormPage.tsx).
  • The spec's thank-you member (packages/spec/src/ui/view.zod.ts) declares them as plain strings with no template slot. The redirect member already interpolates declared record fields as {{record.FIELD}}.
  • POST /api/v1/forms/SLUG/submit answers { id } only, on purpose. Its comment (packages/rest/src/form-routes.ts) says the stored row can carry values an elevated beforeInsert / afterInsert hook derived from records the anonymous form grant may never read, so the answer echoes nothing the insert stored.

Decision needed (triage routes it)

  • A: the thank-you text may name declared fields, and the answer carries exactly the fields the text names. This accepts that trade-off for author-named fields.
  • B: the slot admits only engine-generated fields (autonumber), and the answer carries only those.
  • C: will not do; keep the id-only answer.

A or B is a template slot (contract review owed) plus a served answer field (Metadata-protocol added).

Dedupe words: thank-you record number, public form submit answer id only, submitBehavior interpolate record, case number thank-you.

Related: #27398 (row 3).


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm

    Ruled: B · 2026-10-31T15:11Z · stays domain:spec and pm:queue, and is dispatched next by spec seat 1.

    The maintainer said 「同意」 at 2026-10-31T15:10Z. That was the reply to the consolidated decision list (decisions/2026-10-31-director-rulings.md, item 1, recommendation B), which he accepted in full as recommended.

    What B means:

    1. Slot. The public form thank-you title / message gain a template slot. It admits only fields the engine generates on insert: autonumber and any other engine-generated type the spec already names as such. A field a beforeInsert / afterInsert hook could derive never enters the anonymous page.
    2. Answer. POST /api/v1/forms/SLUG/submit carries id plus exactly the engine-generated fields that the thank-you text names, and nothing else. The comment in packages/rest/src/form-routes.ts about elevated hooks stays true.
    3. Order.
      • The spec comes first: slot syntax, the authoring refusal of a non-engine-generated field, and the answer shape.
      • The server comes next and fills the answer. That is a domain:server card, blocked by the spec PR.
      • The UI comes last and interpolates in FormPage.tsx.
    4. Out of scope: option A (any declared field) and C (id only).

    Freshness gate: this card had no comment before this one, and its body has not been edited since it was filed.

  2. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm

    Claim: PM loop round 8 · 2026-10-31T15:16Z
    Session: session_01L9qibwb6hBqszPTYJobitm
    Account: os-tesla
    Branch: claude/project-thread-i0l9sb (card thread; the platform assigns the thread's branch and it can push only that one, written as measured instead of claude/issue-28005-<slug>)
    Worktree: objectstack-issue-28005
    Domain: domain:spec
    Seat: domain:spec#1
    Card thread: session session_01L9qibwKTredm7FjB4Z6DeX; the dispatch order is in the seat's project, frame + card file.
    File surface: packages/spec/src/ui/view.zod.ts (thank-you title/message slot), the authoring-check site as measured (spec or packages/lint/src), the REST submit-answer schema + generated artefacts, tests, changeset. ⛔ packages/rest/src/form-routes.ts and FormPage.tsx are out (server and ui halves). Stop on breach; explain in the report.
    Container & model: S, mode:thread, model: TIER_DEFAULT (new slot + served answer shape, so a contract review is owed), effort: high
    Clause-②: yes (widening)
    Metadata-protocol: added
    Responsibility: a public form's thank-you panel cannot name the record it created (a case number) | a {{record.field}} slot admitting only runtime-owned field types (RUNTIME_OWNED_FIELD_TYPES), and a declared submit answer carrying only those | web-to-case visitors and public-form authors
    Thread-read: 6545210989
    Premise: holds. On main the thank-you title/message are plain z.string(), the submit answer is { id }, and RUNTIME_OWNED_FIELD_TYPES is ['autonumber'].
    Serial constraints cleared: none. This is the spec half only. The server and ui cards follow after this PR is up.

  3. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-tesla · session_01L9qibwKTredm7FjB4Z6DeX
    os-dev-report

    {
     "issue": 28005,
     "status": "done",
     "branch": "claude/project-thread-i0l9sb",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/28440",
     "session": "session_01L9qibwKTredm7FjB4Z6DeX",
     "premise_still_valid": true,
     "summary": "Spec half of ruling B (Part of #28005). The thank-you title/message take .regex(THANK_YOU_TEXT_RE): every brace must be a {{record.field_name}} token (the redirect token, one grammar); checkThankYouText words the refusal. That projects as a JSON Schema pattern, so there is no dropped-refinement row. thankYouRecordFieldNames(submitBehavior) is the one reading of the named fields. PublicFormSubmitResponseSchema { id, fields? } is strict, beside CreateDataResponseSchema. The lint rule validateThankYouRecordFields (thank-you-record-field) is gating on all three commands and on the publish gate for view and page writes; it judges every form view shape and page object-form panels, and admits a name only when its field's type is in RUNTIME_OWNED_FIELD_TYPES. Mechanism assumptions measured: all four hold, and the redirect token is cross-checked nowhere.",
     "tests": "New: spec view-submit-thank-you-record-slot.test.ts 15/15, public-form-submit-response.test.ts 4/4, lint validate-thank-you-record-fields.test.ts 16/16. Roster pins updated in authoring-rule-wiring, runtime-gate (3 sites) and runtime-gate.page-visibility-predicate-writes (2 sites); type-alias isomorphic pin 805->806. Full suites at 9d1b0b28: lint 183/183 files, 7698 passed, 5 skipped; spec 774/775 files, the one red the pin count, fixed, file then 3/3. Typecheck lint+spec exit 0 at 47c5f03c4. Ablation via ablation-replace on validate-thank-you-record-fields.ts (suite imports src, no build): type gate anchor x1->x0, blob 014ba032cba7->e040658efab9, 9 failed | 7 passed; restored blob == HEAD, git diff HEAD empty.",
     "gates": "dispatch-gates --commands on eeb6adb2b: 104 derived; all 104 run with </dev/null, every one exit 0 (list /mnt/project-files/spec-seat-1/r2026-10-31/28005/gates-ran-eeb6adb2b.list, run after a full turbo build of ./packages/** and ./examples/**); --ran reconciliation: 104 derived, 104 run, 0 NOT-MEASURED, 0 UNRUN, exit 0. Two real findings were fixed on the way: check-comment-mask-adoption (a private comment stripper in my test) and check:docs-transcript-drift (four CLI transcripts printed 56 author-time rules; now 57). PR check-runs at eeb6adb2b: Lint & Repo Gates success, TypeScript Type Check success, Test Core success (8/8 shards), Build Core success, Governed Surface Queue Guard success, Type Check UI success, Test UI success, Build & E2E UI success, Live E2E UI success, Lint UI skipped (no ui/ change), Check Changeset success; mergeable_state clean.",
     "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
     "line_budget": "797 additions / 18 deletions, 29 files (generated artefacts included); under the 3000 human-merge line",
     "files_changed": [
      ".changeset/28005-thank-you-record-slot.md",
      "packages/spec/src/ui/view.zod.ts",
      "packages/spec/src/api/protocol.zod.ts",
      "packages/lint/src/validate-thank-you-record-fields.ts",
      "packages/lint/src/authoring-rules.ts",
      "packages/lint/src/index.ts",
      "4 content/docs pages (transcript count 56->57)",
      "tests: 3 new, 4 roster/pin files",
      "generated: api-surface, authorable-surface, declaration-map, export-origins, json-schema.manifest, references docs, strictness ledger"
     ],
     "deviations": [
      "The order says the slot's admission applies to the public form; the rule judges every form carrying a thank-you panel, public or not, plus page object-form panels, because flipping sharing later is a write the rule would never see again. Named in the PR body.",
      "Docs transcripts (content/docs/**) were edited outside the claimed file surface, forced by check:docs-transcript-drift once the rule count rose to 57."
     ],
     "mcp_calls": "5 — read only: issue_read x3 (get, get_comments x2), pull_request_read x2 (get, get_check_runs); 0 write tools",
     "api_writes": "2 — relay pr_create (POST pulls, PR #28440, body read back identical) and this os-dev-report comment via post-stamped",
     "open_questions": [
      {
       "question": "The brace refusal turns previously legal thank-you text (a literal brace) into a parse error. Does that face change the claim's Clause-② arm?",
       "options": [
        "A keep yes (widening) / added: corpus measured zero authored thank-you text with a brace (examples, non-test packages, hotcrm)",
        "B declare the narrowing face, which brings the ADR-0087 disposition and a dogfood run",
        "C narrow the refusal to token-shaped braces only ({{ or }} outside a valid token, and a {record. prefix)"
       ],
       "recommendation": "A, because no producer writes such text and the order asked for the redirect-style refusal; the seat or triage rules."
      },
      {
       "question": "Approve the new names: PublicFormSubmitResponseSchema (+ type PublicFormSubmitResponse), its key fields, thankYouRecordFieldNames, and the lint rule thank-you-record-field / validateThankYouRecordFields.",
       "options": [
        "A approve as proposed",
        "B rename (a mechanical edit before merge)"
       ],
       "recommendation": "A, because they follow the neighbouring spellings (CreateDataResponseSchema, anonymousFormObjectName, public-form-file-field)."
      }
     ],
     "out_of_scope_findings": [
      "carrier: the seat — the server card (form-routes.ts fills fields from thankYouRecordFieldNames, and rest-route-ledger names PublicFormSubmitResponseSchema with conformance) and the ui card (FormPage.tsx fills the tokens) are the seat's to file; Skills-docs follow-up owed for content/docs/ui/public-data-collection.mdx and forms.mdx once those halves land"
     ]
    }

    Reported 2026-10-31T16:36Z.

  4. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm

    Split filed · 2026-10-31T16:40Z. The spec half is PR #28440, Part of. The server half is #28443: the submit answer carries the named runtime-owned fields. The ui half is #28444: FormPage fills the tokens, and the Skills-docs follow-up rides on it. Each card is blocked by the one before. This card closes when #28444 lands.

    Seat ruling on the dev's open question, the brace refusal: it stays. Any brace in thank-you title/message must belong to a well-formed {{record.field_name}} token. The corpus count is 0. The spelling stays Clause-②: yes (widening), because the face's main change is a new slot. The narrowing face is declared in the PR body's deviations, where the contract review reads it.

  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Closed as completed · 2026-11-02T02:02Z

    The maintainer ruled in the triage session 「同意 四张都以 completed 关闭」, covering #27855, #28117, #28005 and #27130. Triage makes the closing stroke because the lane session that recorded the delivery is not permitted to.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions