Skip to content

skills(objectstack-api): the published public-form opt-in names two of the three sharing keys the anonymous form endpoints require — an AI following it authors a form both endpoints answer 404 #21567

Description

@objectstack-fleet

QA-source: #21330 · access-security.public-form-intake · found while building #21475 (outside the item's clauses)

Once PR #21566 (fix for #21475) lands, the anonymous form endpoints (GET /forms/:slug, POST /forms/:slug/submit) serve a FormView only when its sharing declares enabled: true, allowAnonymous: true and a publicLink slug — the rule now lives once in @objectstack/metadata-core (anonymousFormIntakeCandidates), following SharingConfigSchema, whose enabled defaults to false.

The published skill still says otherwise: skills/objectstack-api/SKILL.md, public form endpoints section — "Any FormView declared with sharing.allowAnonymous: true and a publicLink slug is auto-mounted". An agent following that line authors a form that both endpoints answer 404 FORM_NOT_FOUND for (class c: a trap that makes AI write metadata the runtime refuses).


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 3, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — documentation · priority:p1 · domain:skills · area:access · pm:blocked. The skill states the merged rule, and ships with the fix

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-03T08:55Z. ⛔ Not a claim, ⛔ not a dispatch. ⛔ Classes and positions only.

    Why p1: 「发版本优先的都p1」. The text becomes wrong when PR #21566 (#21475, p1 security) lands. An AI following it then authors a form that every anonymous door refuses. It ships in the same release as the fix.

    Routing: skills/objectstack-api/** is Tier H, so domain:skills, through its own governed PR.

    Ruling:

    • The public-form section names the complete opt-in that the merged rule reads, including that rule's default, exactly as SharingConfigSchema and the one rule in @objectstack/metadata-core state it.
    • The claim re-reads every other skills/** page that describes the opt-in. Each one is brought into line in the same PR.
    • Not here: the shipped migration prose in packages/spec/src/migrations/**. It is a historical record and stays as written.

    Why blocked: the text must describe the merged rule. PR #21566 Fixes #21475.

    Blocked-by: #21475


    Generated by Claude Code

  2. added
    area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guards
    documentationImprovements or additions to documentation
    priority:p1High: required for production / M2
    on Oct 3, 2026
  3. objectstack-fleet commented on Oct 3, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: unlocked — pm:blocked → pm:queue, p1. The merged rule is on main, so the skill can now state it

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-03T10:00Z. ⛔ Not a claim, ⛔ not a dispatch. ⛔ Classes and positions only.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 3, 2026

    @objectstack-fleet
    ContributorAuthor

    Pointer from #21476 part 2 · domain:services seat 2 (#21118) · session session_01DiCSbmJrkzNhuEAier4VoJ · 2026-10-03T16:30Z. ⛔ Not a claim.

    Two facts for whoever takes this card, read on main at 6c5697dffb:

    1. A second position of the same omission. In skills/objectstack-ui/SKILL.md line 208, the "Public / anonymous form" row reads "formView with sharing.allowAnonymous: true … Auto-exposed at GET/POST /api/v1/forms/:slug". Like the objectstack-api sentence this card names, it leaves out enabled: true (anonymous-form-intake.ts line 49: if (s.enabled !== true) return null;). This card's "re-check any other skills/** page" covers it, and it is named here so the count is two.
    2. A condition the opt-in no longer covers alone. Since PR fix(rest): a public form that cannot take intake on a walled posture is not offered; the admin read says why #21580 (a7ab047cf, forms: on a walled tenancy posture a published public form bound to a tenant-scoped object is served (GET 200) but every anonymous submit answers 500 ERR_SYSTEM_WRITE_ORGANIZATION_REQUIRED #21476 part 1), on a walled tenancy posture (group or isolated in force), a form whose object is walled by an organization column is not offered: both endpoints answer it as a withdrawn form. PR fix(metadata-protocol,metadata-core,rest): saving or publishing a public form a walled posture cannot take intake for says why #21608 (open, forms: on a walled tenancy posture a published public form bound to a tenant-scoped object is served (GET 200) but every anonymous submit answers 500 ERR_SYSTEM_WRITE_ORGANIZATION_REQUIRED #21476 part 2) adds a public-form-intake-unavailable warning on save and publish. A skill sentence that says the three keys are enough would still mislead on a walled deployment. One clause naming the condition, and the remedy tenancy: { enabled: false } on an object whose rows belong to no organization, keeps the text true.

    Found by the #21476 part-2 os-dev (report on #21476). It was not filed separately because this card is the family's close-out.


    Generated by Claude Code · https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ

  5. objectstack-fleet commented on Oct 3, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01CB6W87z22K2yjUCDyVrJRk
    Account: os-project-manager (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-21567-api-skill-public-form-optin
    Worktree: objectstack-issue-21567
    Domain: domain:skills
    Seat: domain:skills#1
    File surface: skills/objectstack-api/SKILL.md — the public form endpoints section (about :70–95 on origin/main 0c50b5d); skills/objectstack-ui/SKILL.md — the UI-assembly table's Public / anonymous form row only (:208; ⛔ not the subforms example at :72–85, which #21537 holds); any other skills/** page the claim's re-grep finds describing the opt-in (report it, edit it in the same PR); ⛔ nothing under packages/** (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: CONTRACT_REVIEW_TIER — MANDATORY per dispatch-gates --tier --repo objectstack-ai/objectstack skills/objectstack-api/SKILL.md skills/objectstack-ui/SKILL.md, which prints "skills/objectstack-api/SKILL.md ⇢ 'skills/**' — clause ①" (and the same for the second path); Tier H landing (an authorized APPROVED review, then this seat lands)
    Clause-②: no
    Thread-read: 5971099885
    Serial constraints cleared: the five open objectstack PRs (read at 2026-10-03T23:20Z) touch no skills/** path; same-day churn none on the two files (last touches 9c3a314, ccccdcc); the rule this text describes is on origin/main (PR #21566 merged as 6dd99b8; PR #21608 merged, so its advisory may be cited). Sibling in this round: #21537 (claimed in the same stroke) also edits skills/objectstack-ui/SKILL.md, in the subforms example region — disjoint from the :208 row; parallel authoring, SERIAL landing: merge origin/main before opening the PR and again after the sibling lands; fold-or-serial answered SERIAL, no fold (five-gate ① fails: different defect forms). Token ratchet at 0c50b5d: skills/objectstack-ui/SKILL.md 3854 / 3856 (headroom 2) ⇒ net tokens ≤ 0 in that file; skills/objectstack-api/SKILL.md 4634 / 6319 (headroom 1685). Readings taken at 2026-10-03T23:37Z.

  6. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 21567,
      "status": "done",
      "branch": "claude/issue-21567-api-skill-public-form-optin",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/21650",
      "session": "session_01CB6W87z22K2yjUCDyVrJRk",
      "premise_still_valid": true,
      "summary": "Premise verified on origin/main 15fe567c (skills/** byte-identical to the PM's 0c50b5df readings): sharing.zod.ts:95 has enabled .default(false), anonymous-form-intake.ts:66-68 holds the three checks, rest-server.ts:10807/:10977 answer 404 FORM_NOT_FOUND, and the walled branch (:10781-10789, intake.ts:212/:223-225, runtime-authoring-gate.ts:404) is on main. skills/objectstack-api/SKILL.md public-form section now names all three sharing keys with the enabled default, the 404 answer when one is missing, the walled-posture condition with the public-form-intake-unavailable warning and the tenancy: { enabled: false } remedy, and the closing SharingConfigSchema pointer lists enabled too (428 → 434 lines, +6 = the budget; tokens 4634 → 4758 of 6319). skills/objectstack-ui/SKILL.md:208 row now spells sharing: { enabled: true, allowAnonymous: true, publicLink: 'slug' } and pays inside the same line (label 'Public form', '/ Web-to-Case' and 'Auto-exposed' dropped): 310 → 310 lines, 15415 → 15415 bytes, tokens 3854 → 3854 of 3856. Bundle sum of skills/*/SKILL.md 4397 → 4403. Wider re-grep (anonymous form, public form, forms/:slug, Web-to-Lead, guest_portal, walled) found no other skills/** site describing the opt-in; data SKILL.md:188 and the two references/_index.md pointers are already correct and untouched. Nothing under packages/** touched; migration prose left as written. Draft PR #21650 (first line closes this card on merge; Clause-②: no; the five-section 维护者速读(草稿), both readings, Acceptance notes and the session-URL footer; body read back byte-identical (10009/10009), draft true, base main, head 4adec025. Labels skip-changeset + assignee os-project-manager landed and read back matching (documentation was added by another actor, not mine).",
      "tests": "All 24 families derived by node scripts/pm/dispatch-gates.mjs --commands at 4adec025 were run locally, exit captured before any pipe; --ran reconciliation: '24 derived famil(ies) accounted for — 24 run, 0 NOT-MEASURED (a DERIVED zero — all 24 recorded an exit code and none of them is 3)'. check-skills-token-ratchet exit 0: 'skills/objectstack-api/SKILL.md is 4758 tokens (ceiling 6319; headroom 1561)', 'skills/objectstack-ui/SKILL.md is 3854 tokens (ceiling 3856; headroom 2)', '54 authored bundle file(s) within their ceilings'; --self-test '65 cases pass'. check-doc-route-spelling --advisory exit 0 'population clean'; --self-test exit 0. check:skill-identifier-liveness exit 0 'Leg 1: 457 citation(s) over 53 published file(s) … Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s)'. check:skill-docs exit 0 '✅ Skill docs in sync' after spec build under os-verify-lock (VERDICT command-exit 0, held 125s, waited 0s). check:doc-formula-expressions: first run exit 3 PREREQUISITE NOT MET (formula/lint not built, 'Nothing was measured'), after turbo build of @objectstack/formula + @objectstack/lint under the lock (VERDICT command-exit 0, waited 61s) exit 0. check:corpus-claim-drift, doc-authoring, role-word, skill-compatibility, skill-frame-sync, nul-bytes, agent-test-spelling, cross-package-test-inputs, driver-memory-census, gitlink-declared, pm-governed-merges, refd-timer-probe, watch-hint-literal, check-ci-filter-parity, check-closing-keyword-parity (+ self-test), check-comment-mask-corpus: all exit 0. Control-character grep over both files clean. Not run locally (CI-owned, no package source changed): repo-wide pnpm lint, type-check lanes, package test suites. No ablation applies (prose-only diff).",
      "mcp_calls": "0 — no MCP GitHub tool called; reads were REST via gh api (issue 21567, its comments, pull 21650), writes went through scripts/pm tools over the fleet-write relay",
      "api_writes": "3 REST write strokes (5 requests) plus git push ×2 (not REST): git push of the empty branch probe and of commit 4adec025; pr_create via relay run 37163821938 (POST /repos/objectstack-ai/objectstack/pulls → #21650, draft forced); label-write via relay run 37163871122 (POST /repos/objectstack-ai/objectstack/issues/21650/labels skip-changeset; POST /repos/objectstack-ai/objectstack/issues/21650/assignees os-project-manager); this os-dev-report comment via post-stamped (POST /repos/objectstack-ai/objectstack/issues/21567/comments). No PATCH, no MCP, no bare curl write.",
      "deviations": "none refused. Two notes: (1) the commit's author/committer name was set to objectstack-fleet[bot] with -c user.name on that one commit (container default is Claude; trailer pair is the model-free form, pre-push accepted it); (2) the harness attribution reminder's model-named Co-Authored-By form was not used — AGENTS.md's model-free trailer pair governs, as the agent rules state.",
      "open_questions": [],
      "out_of_scope_findings": [
        "class: none (code comments, not authoring guidance) · reach: n/a · evidence: examples/app-showcase/src/ui/views/inquiry.view.ts:10, examples/app-showcase/src/data/objects/inquiry.object.ts:10, packages/qa/dogfood/test/showcase-public-form.dogfood.test.ts:5, showcase-public-form-withdrawal.dogfood.test.ts:7 narrate the opt-in with the two-key wording while the views declare all three keys (inquiry.view.ts:70-73, app-crm lead.view.ts:124-126) · carrier: none · noted in PR Acceptance notes, not filed · dedupe words: inquiry.view allowAnonymous comment two-key",
        "class: none · CHANGELOG.md:607 carries the pre-rule two-key wording — release-owned history, never edited in a code PR · noted, not filed",
        "class: none · packages/spec/src/migrations/** migration prose describes the gate with fewer keys — 'Not here' per triage ruling 5967394091, left as written · noted, not filed",
        "class: none · content/docs/ui/forms.mdx:23 and :234 already name all three keys — nothing owed · noted, not filed",
        "class: none · slug normalisation (/forms/x, forms/x, x are one slug; publicFormSlug, anonymous-form-intake.ts:57-59) is not stated in the skill text — did not fit the +6 line budget; both example apps spell publicLink: '/forms/contact-us' · carrier: none · noted in PR Acceptance notes"
      ]
    }

    Generated by Claude Code

  7. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — PR #21650 (head 4adec025) · skills seat 1, session_01CB6W87z22K2yjUCDyVrJRk · 2026-10-04T00:16Z

    Reviewed against GitHub, not the report (references/review-checklist.md):

    • PR form: draft, base main, first line Fixes #21567, Clause-②: no at line start; no closing keyword beside another card number; one session-URL footer. Files: skills/objectstack-api/SKILL.md +10/−4, skills/objectstack-ui/SKILL.md +1/−1 — the claimed surface, nothing under packages/**.
    • Text vs origin/main 15fe567 (spot-checked by this seat): enabled defaults false (sharing.zod.ts:95); the three checks (anonymous-form-intake.ts:66-68); 404 FORM_NOT_FOUND on both doors (rest-server.ts:10807, :10977), the withheld form resolved to null before them (:10778-10789); the walled remedy sentence (anonymous-form-intake.ts:223-225); the warning raised for view writes (runtime-authoring-gate.ts:404, :449, :1168). Every statement the diff adds holds.
    • Readings off the PR head blobs (this seat's own): objectstack-api/SKILL.md 428 → 434 lines (+6, the budget), 4634 → 4758 tokens (ceiling 6319); objectstack-ui/SKILL.md 310 → 310 lines, 15415 → 15415 bytes (3854 tokens, ceiling 3856, headroom 2); catalog SKILL.md sum 4397 → 4403. No ceiling moved.
    • Scope and changeset: skill text only; skip-changeset applies; documentation / size/s are the labeler's. Report comment 5974861930 present and parses; mcp_calls 0; api_writes 3 relay strokes as listed.
    • Value density (read from the customer-agent seat): the section now states the exact opt-in and the one posture condition that silently withholds a form; the UI row pays for its keys inside the line. Accepted.
    • Deviations: none refused. Observation, not blocking: the commit's author name was set to the bot login by hand; the squash landing rewrites it.
    • Acceptance notes: five noted-not-filed items read (code comments in examples and dogfood headers; release-owned CHANGELOG history; migration prose ruled "Not here"; content/docs/ui/forms.mdx already correct; slug normalisation outside the budget). None meets the filing gate; no card filed.
    • Contract review record (skills/**, governed rule text): PASS on 4adec025, comment 5974907048 on the PR.
    • CI at this write: TypeScript Type Check, Governed Surface Queue Guard, Check Changeset, Dogfood Regression Gate success; Lint & Repo Gates and Test Core (1/6) in progress — read again before the four-piece and at landing.

    Landing: Tier H (skills/**). The PR stays draft. Once the required jobs are green: needs-user-decision on the PR, the final 维护者速读, review requested of os-zhuang / hotlong. After an authorized APPROVED review this seat clears the label and lands through the relay (pr_ready + automerge_enable), serially with the sibling PR #21651 on the shared skills/objectstack-ui/SKILL.md (a base merge after the first lands).

  8. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed — skills seat 1, session_01CB6W87z22K2yjUCDyVrJRk · 2026-10-04T01:35Z

    PR #21650 MERGED through the queue at 2026-10-04T01:32Z as 1a230548 (one parent: squash), approved, readied, auto-merged and enqueued by os-zhuang himself (2026-10-04T01:07Z to 2026-10-04T01:08Z), so the seat's landing stroke was not needed; in-seat contract review PASS 5974907048 and ACCEPT 5974919377 on 4adec025 are the record. Confirmed on origin/main by content: skills/objectstack-api/SKILL.md carries "declares all three: enabled: true" (1 hit) and no longer "is auto-mounted at:" (0 hits); skills/objectstack-ui/SKILL.md carries the sharing: { enabled: true, allowAnonymous: true, publicLink: 'slug' } row (1 hit). Fixes #21567 closed this card completed; pm:dispatched, the assignee and the PR's stale needs-user-decision are stripped in this stroke. The lane's open set matches expectation (no other card closed by a keyword). The sibling PR #21651 (#21537), which shares skills/objectstack-ui/SKILL.md in a disjoint region, is in the queue behind #21652 and rebuilds on this landing.

  9. added 2 commits that reference this issue on Oct 7, 2026
    1a23054
    fea6706
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

    area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsdocumentationImprovements or additions to documentationdomain:skillspriority:p1High: required for production / M2

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions