Repository navigation
Commit 1a23054
docs(skills): name the complete public-form opt-in the anonymous form endpoints read (#21650)
Fixes #21567
Clause-②: no
## What
The published `objectstack-api` skill's public-form section named two of
the three `sharing` keys the anonymous form endpoints read, and the
`objectstack-ui` skill's UI-assembly row repeated the omission. An AI
following either authors a form that both `GET /api/v1/forms/:slug` and
`POST /api/v1/forms/:slug/submit` answer `404 FORM_NOT_FOUND`. Both now
state the complete opt-in as the merged rule reads it, plus the
walled-posture condition and its remedy.
Skill text only (`skills/**`, Tier H). Nothing under `packages/**` is
touched; the shipped migration prose in
`packages/spec/src/migrations/**` stays as written (triage ruling
5967394091, "Not here").
### The rule the text now describes (read on `origin/main` 15fe567)
- `packages/spec/src/ui/sharing.zod.ts:95` — `enabled:
z.boolean().default(false).describe('Enable public sharing')`; `:102` —
`allowAnonymous: z.boolean().optional().default(false)`.
- `packages/metadata-core/src/anonymous-form-intake.ts:66-68` — the
three checks (`s.enabled !== true`, `s.allowAnonymous !== true`,
`publicLink` a non-empty string); `:57-59` — `publicFormSlug` folds
`/forms/x`, `forms/x` and `x` into one slug.
- `packages/rest/src/rest-server.ts:10807` and `:10977` — both doors
answer `404 FORM_NOT_FOUND` whenever `resolveFormBySlug` returns null,
which it also does for a form the posture withholds (`:10781-10789`).
- `packages/metadata-core/src/anonymous-form-intake.ts:212` — a wall is
in force only on a posture `postureEnforcesWall` admits (`group` /
`isolated`); `:223-225` — the remedy text: declare `tenancy: { enabled:
false }` on an object whose rows belong to no organization.
- `packages/metadata-protocol/src/runtime-authoring-gate.ts:404` —
`PUBLIC_FORM_INTAKE_UNAVAILABLE = 'public-form-intake-unavailable'`, a
`warning` the authoring gate raises for a `view` write (save and
publish).
### Every `skills/**` site that describes the opt-in
Sweep at 15fe567: `git grep -n -i` over `skills/` for `allowAnonymous`,
`publicLink`, `anonymous form`, `public form`, `forms/:slug`,
`Web-to-Lead`, `web-to-case`, `guest_portal`, `walled`.
| Site (line numbers at 15fe567) | Verdict |
|:--|:--|
| `skills/objectstack-api/SKILL.md:77-78` — "Any `FormView` declared
with `sharing.allowAnonymous: true` and a `publicLink` slug is
auto-mounted at:" | **changed** — names all three keys, the `enabled`
default, and the `404 FORM_NOT_FOUND` answer when one is missing |
| `skills/objectstack-api/SKILL.md:94` — "with `allowAnonymous` /
`publicLink`" | **changed** — now `enabled` / `allowAnonymous` /
`publicLink` |
| `skills/objectstack-api/SKILL.md:85-94` — the paragraph after the
route block | **changed** — one sentence names the walled-posture
condition, the `public-form-intake-unavailable` warning on save and
publish, and the `tenancy: { enabled: false }` remedy |
| `skills/objectstack-ui/SKILL.md:208` — the UI-assembly table's
public-form row | **changed** — the row now shows `sharing: { enabled:
true, allowAnonymous: true, publicLink: 'slug' }` |
| `skills/objectstack-data/SKILL.md:188` — "public forms" in the list of
surfaces a field's conditional rule applies to | already correct — names
the surface, not the opt-in |
| `skills/objectstack-data/references/_index.md:57`,
`skills/objectstack-ui/references/_index.md:48` | already correct — file
pointers to `sharing.zod.ts`, no opt-in prose |
No other hit; `guest_portal` and `Web-to-Lead` occur only inside the
edited section.
### Readings
| File | Lines before → after | Tokens before → after (ceiling) |
|:--|:--|:--|
| `skills/objectstack-api/SKILL.md` | 428 → 434 (+6, the +6 net-line
budget) | 4634 → 4758 (6319; headroom 1561) |
| `skills/objectstack-ui/SKILL.md` | 310 → 310 | 3854 → 3854 (3856;
headroom 2) — bytes 15415 → 15415; the edited row is 179 bytes before
and after |
| Bundle: sum of every `skills/*/SKILL.md` | 4397 → 4403 | — |
Tokens are the ratchet's own convention, `ceil(bytes / 4)`; the gate's
lines at 4adec02: "skills/objectstack-api/SKILL.md is 4758 tokens
(ceiling 6319; headroom 1561)" and "skills/objectstack-ui/SKILL.md is
3854 tokens (ceiling 3856; headroom 2)". The `objectstack-ui` row paid
for its three keys inside the same line: the label "Public / anonymous
form" is now "Public form" (the cell still carries `allowAnonymous`),
and "/ Web-to-Case" and "Auto-exposed" are dropped (the API skill's
section keeps "Web-to-Lead / Web-to-Case"). No other line of that file
moved; the sibling card #21537 holds the subforms example at :72-85.
`origin/main` was still 15fe567 when this PR was opened, so no merge
was owed.
## Tests
All 24 gate families that `node scripts/pm/dispatch-gates.mjs
--commands` derives for this diff were run locally at `4adec025`, each
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)". Verdict lines:
- `node scripts/check-skills-token-ratchet.mjs` exit 0 — "✓
check-skills-token-ratchet: 54 authored bundle file(s) within their
ceilings; 10 generator-owned file(s) measured, not ratcheted.";
`--self-test` exit 0 — "65 cases pass".
- `node scripts/check-doc-route-spelling.mjs --advisory` exit 0 — "✓
route-spelling guard (advisory): population clean — every shape-matched
literal spells its ledger row."; `--self-test` exit 0.
- `pnpm check:skill-identifier-liveness` exit 0 — "Leg 1: 457
citation(s) over 53 published file(s) checked against 118365
implementation word tokens (0 ledgered exemption(s)); Leg 2: 8
registered exhaustive section(s), 0 ledgered gap(s)."
- `pnpm --filter @objectstack/spec run check:skill-docs` exit 0 — "✅
Skill docs in sync" (after `pnpm --filter @objectstack/spec build` under
the verify lock, `VERDICT command-exit 0`).
- `pnpm --filter @objectstack/lint run check:doc-formula-expressions` —
first run exit 3, `PREREQUISITE NOT MET` (`@objectstack/formula` and
`@objectstack/lint` not built; "Nothing was measured"); after `turbo run
build --filter=@objectstack/formula --filter=@objectstack/lint` under
the lock, exit 0.
- `pnpm check:corpus-claim-drift`, `check:doc-authoring`,
`check:role-word`, `check:skill-compatibility`,
`check:skill-frame-sync`, `check:nul-bytes`,
`check:agent-test-spelling`, `check:cross-package-test-inputs`,
`check:driver-memory-census`, `check:gitlink-declared`,
`check:pm-governed-merges`, `check:refd-timer-probe`,
`check:watch-hint-literal`, `node scripts/check-ci-filter-parity.mjs`,
`node scripts/check-closing-keyword-parity.mjs` (and `--self-test`),
`node scripts/check-comment-mask-corpus.mjs` — all exit 0.
- Control-character self-scan over both files (the `grep -naP` spelling
from the agent rules): clean.
Not run locally, CI owns them: the repo-wide `pnpm lint`, the type-check
lanes and the package test suites — no package source changed.
## 维护者速读(草稿)
**改了什么:**
两份对外发布的技能页(`objectstack-api`、`objectstack-ui`)里描述「匿名公开表单」开关的句子,原来只写了
`allowAnonymous: true` 和 `publicLink` 两个键。现在补齐第三个键 `enabled:
true`(schema 默认是 `false`),写明三者缺一则两个匿名端点都答 `404 FORM_NOT_FOUND`,并加一句:在
`group` / `isolated` 这类带租户墙的部署姿态下,目标对象若按组织列隔离,表单同样不对外提供,保存与发布时会收到
`public-form-intake-unavailable` 警告,补救是对不归属任何组织的对象声明 `tenancy: {
enabled: false }`。
**为什么改:** 运行时规则已在 PR #21566 落地到 `main`:三个键齐全才服务。技能文本是 AI
写元数据的直接依据,按旧文本写出来的表单会被两个端点同时拒绝,而作者不知道为什么。本 PR 让文本与已合并的规则、与
`SharingConfigSchema` 的默认值完全一致。
**风险与代价(含回滚):** 纯文本改动,不碰 `packages/**`,无
changeset(`skip-changeset`)。`objectstack-ui/SKILL.md` 的 token 棘轮只剩 2
的余量,所以那一行用同一行内的删字付账(行标签「Public / anonymous form」改为「Public form」,去掉「/
Web-to-Case」与「Auto-exposed」);`objectstack-api/SKILL.md` 净增 6 行,在 PM 给的
+6 预算内。回滚:revert 本 PR 即可,没有派生产物。
**席位意见:**
**你要做的:** 这是 Tier H 受管面(`skills/**`),需要你的 APPROVED
review;批准后由席位落地。请顺带看一眼 `objectstack-ui` 那一行的措辞取舍是否接受(标签缩短、去掉
Web-to-Case)。
## Acceptance notes
- Noted, not filed (code comments, not authoring guidance; carrier:
none): `examples/app-showcase/src/ui/views/inquiry.view.ts:10` and
`examples/app-showcase/src/data/objects/inquiry.object.ts:10`, and the
header comments of
`packages/qa/dogfood/test/showcase-public-form.dogfood.test.ts:5` and
`showcase-public-form-withdrawal.dogfood.test.ts:7`, narrate the opt-in
with the two-key wording; the example view itself declares all three
keys (`inquiry.view.ts:70-73`), as does
`examples/app-crm/src/views/lead.view.ts:124-126`.
- `CHANGELOG.md:607` carries the pre-rule wording — release-owned
history, never edited in a code PR.
- `content/docs/ui/forms.mdx:23` and `:234` already name
`sharing.enabled: true` + `sharing.allowAnonymous: true` + `publicLink`;
nothing owed there.
- The slug-normalisation fact (`/forms/x`, `forms/x` and `x` are one
slug) is not in the skill text — it did not fit the +6 line budget; both
example apps spell `publicLink: '/forms/contact-us'`, which the UI row's
`publicLink: 'slug'` placeholder admits.
- The commit's author/committer name is `objectstack-fleet[bot]` (set
with `-c user.name` on this one commit; the container default is
`Claude`); the trailer pair is the model-free form the pre-push hook
accepted.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01CB6W87z22K2yjUCDyVrJRk)_
Co-authored-by: objectstack-fleet[bot] <noreply@anthropic.com>1 parent eea82af commit 1a23054
2 files changed
Lines changed: 11 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
74 | 74 | | |
75 | 75 | | |
76 | 76 | | |
77 | | - | |
78 | | - | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
79 | 81 | | |
80 | 82 | | |
81 | 83 | | |
| |||
88 | 90 | | |
89 | 91 | | |
90 | 92 | | |
91 | | - | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
92 | 98 | | |
93 | 99 | | |
94 | | - | |
| 100 | + | |
95 | 101 | | |
96 | 102 | | |
97 | 103 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
205 | 205 | | |
206 | 206 | | |
207 | 207 | | |
208 | | - | |
| 208 | + | |
209 | 209 | | |
210 | 210 | | |
211 | 211 | | |
| |||
0 commit comments