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
public forms: sharing.publicLink reads as the "Generated public share URL" but is only a slug — the authored path (/forms/contact-us) answers 404, and the real anonymous URL (/_console/f/<slug>) is shown to the author nowhere #22079
Filing gate: ① product defect with reach measured. Class (a). reach: public door, an anonymous visitor opening the link an app declares for its public form. Measured on @objectstack/* 17.7.0 by the repo:hotcrm seat (session_01ER8ntXZhYebyQ66aXWdjfT) during the hotcrm 17.7.0 upgrade (hotcrm PR #2008), on the maintainer's word: 「4. 公开表单地址对不上 … 以上立卡」.
Who acts on it: objectstack triage routes it. ⛔ Not a claim.
Measured (17.7.0 boots of hotcrm's 17.7.0 upgrade branch, merged as c9678036; requests sent with no session)
hotcrm declares its Web-to-Lead form as sharing: { enabled: true, allowAnonymous: true, publicLink: '/forms/contact-us' } (src/sales/views/lead.view.ts:933). That is the same spelling the platform's own conversion fixtures use (packages/spec/src/conversions/registry.ts:14001, publicLink: '/forms/contact').
redirect to /_console/login?redirect=%2Fforms%2Fcontact-us (the signed-in form route, keyed by form name)
GET /_console/f/contact-us
✅ the form, anonymously. A submission created its crm_lead
The working URL was found by trying paths. Nothing an author reads names it.
Code reading (origin/main8caa131e52)
packages/spec/src/ui/sharing.zod.ts:96: publicLink: z.string().optional().describe('Generated public share URL').
packages/metadata-core/src/anonymous-form-intake.ts:62–64: publicFormSlug() strips a leading / and forms/. So /forms/x, forms/x and x are one slug: the value is a slug, not a URL, and nothing generates it.
The console serves the slug at /f/:slug (packages/spec/src/ui/view.zod.ts:3414, "The console's public form route (/f/:slug)").
Why it matters
An app author writes what the describe invites, a URL, and gets one that 404s for every visitor.
The link that has to go on a website (Contact us, Support) cannot be read from the metadata, from Studio, or from the docs the author is likely to open.
A direction, for triage to rule on (⛔ not a ruling)
Answer the authored path. Redirect GET /forms/<slug> (and the bare /<slug> spelling, if it is the declared one) to /_console/f/<slug>, but only when an enabled public form declares that slug. Or say plainly in the describe that the value is a slug, and give the URL it is served at.
Show the real anonymous URL wherever the form's sharing is edited or listed (Studio, the form view's share panel).
publicLink describing itself as "Generated" while every first-party example hand-writes it is a declared≠enforced wording question for the spec lane.
Duplicate check
Semantic issue search on objectstack, public form publicLink URL not served 404 ENDPOINT_NOT_FOUND console /f/ route: 1 hit, #12233 (closed, the docs site's soft-404), a different surface. Positive control: publicLink appears in the code readings above.
Dedupe words: publicLink 404 · public form URL · /f/:slug · ENDPOINT_NOT_FOUND forms · publicLink is a slug
Path: ② the capabilities an end user meets in the app — public forms | 缺项 | P3
Triage: pm:retriage answer: re-route domain:cli → domain:spec, re-graded p2 → p3. Only the publicLink describe remains
Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-07T18:57Z. ⛔ Not a claim, ⛔ not a dispatch.
This answers the release 6044120961. The redirect half landed (PR #22098 → dd39171835), so the visitor-facing 404 that made this p2 is gone.
Triage: lands in packages/spec/src/ui/sharing.zod.ts:98 (publicLink: z.string().optional().describe('Generated public share URL'), read on maina543e244f0) ⇒ domain:spec; rationale: packages/spec always belongs to the spec seat (lanes/spec.md).
Why p3: what remains is describe text. The accept set does not change, and the authored /forms/<slug> spelling now answers.
Direction (unchanged from my first grade 6038401972, now on its own):
The describe says the value is a slug, not a generated URL.
It names where the slug is served: /forms/<slug> redirects (query string carried) to the console's /f/<slug>.
/forms/x, forms/x and x name one slug (publicFormSlug, packages/spec/src/ui/anonymous-form-intake.ts:69).
Claim: PM loop round 1 (the publicLink describe half; the redirect half landed as PR #22098 → dd39171835) · 2026-10-08T02:43Z
Session: session_01RPo7FUd6bSnAfkWMAKi848
Account: os-justin (the seat's linked user as GET /user answers it; the card's assignee from this act)
Branch: claude/issue-22079-publiclink-describe
Worktree: objectstack-issue-22079
Domain: domain:spec
Seat: domain:spec#3 (seat post #18883)
File surface (at origin/mainef1fcb26a2; stop on breach and explain in the report):
packages/spec/src/ui/sharing.zod.ts: the publicLink describe (:98, 'Generated public share URL').
The generated references it reaches (content/docs/references/**, merge=os-regen), any pin that asserts that describe, and .changeset/22079-*.md (patch, @objectstack/spec).
Container & model: S, mode:subagent, model: opus (--tier: no path-derived mandate; describe text only; the path limb owes the contract review at CONTRACT_REVIEW_TIER on the landing head)
Clause-②: no
Responsibility: packages/spec's describe calls a slug a "generated public share URL" | the redirect half (PR feat(cli): the authored public form path /forms/:slug redirects to the console form page when the anonymous door serves it #22098) answers the authored /forms/<slug>, but nothing an author reads says the value is a slug or where it is served | every author of a public form in Studio, REST or MCP (measured on hotcrm's publicLink: '/forms/contact-us')
Thread-read: 6044725872
Serial constraints cleared: no open PR touches sharing.zod.ts or its generated reference (all open PRs' file lists read at this stamp). area:access in flight elsewhere: Design: does approver routing imply record read visibility? (#7345 model half) #7497 (a read-only design round in the services packages), a disjoint file surface.
Clause-②: no per triage's re-grade 6044725872 (describe text only; the accept set does not change).
os-dev-report
{
"issue": 22079,
"status": "done",
"branch": "claude/issue-22079-publiclink-describe",
"pr": "#22159",
"session": "session_01RPo7FUd6bSnAfkWMAKi848",
"premise_still_valid": true,
"summary": "The publicLink describe in packages/spec/src/ui/sharing.zod.ts:98 now says the value is an author-chosen slug, not a generated URL; that /forms/x, forms/x and x are one slug; that it is served only while enabled and allowAnonymous are both true; and where: the REST form door GET /api/v1/forms/:slug (default API base) on every host, and on a host that serves the console the page /_console/f/:slug with /forms/:slug redirected there, query carried. Route params are spelled :slug (the spelling view.zod.ts already uses) so nothing angle-bracketed reaches MDX or the GitHub sanitizer. The two generated references (content/docs/references/ui/sharing.mdx, ui/view.mdx) were regenerated with gen:docs after check:generated named them stale; no pin of the old text existed. Draft PR #22159, body line 1 'Fixes #22079', line 2 'Clause-②: no'; changeset .changeset/22079-publiclink-describe.md '@objectstack/spec': patch with 'Clause-②: no'. Card assignee untouched; PR assignee os-justin.",
"describe_old": "Generated public share URL",
"describe_new": "Public slug of the form, chosen by the author: not a URL, and never generated. /forms/x, forms/x and x name one slug, x. It is served to anonymous visitors only while enabled and allowAnonymous are both true: the REST form door answers GET /api/v1/forms/:slug (default API base), and a host that serves the console shows the form at /_console/f/:slug and redirects /forms/:slug there, query string carried.",
"h1": "Holds at base ef1fcb2 (= PM read): sharing.zod.ts:98 publicLink: z.string().optional().describe('Generated public share URL'); publicFormSlug() at packages/spec/src/ui/anonymous-form-intake.ts:69-71 strips leading slashes then one 'forms/' prefix. SharingConfigSchema has one carrier, FormViewSchema.sharing (view.zod.ts:4386).",
"h2": [
"REST door: registerFormEndpoints registers GET {basePath}/forms/:slug (packages/rest/src/rest-server.ts:10842) and POST {basePath}/forms/:slug/submit (:11012), called for every base in registerForBase (:4519); default base = api.apiPath ?? basePath/version (getApiBasePath :4472-4475), /api/v1 by default, so the describe says '(default API base)'. The request slug is compared to the normalised candidate slug (c.slug !== slug, :10749).",
"Console page: CONSOLE_PATH = '/_console' is a constant (packages/cli/src/utils/console.ts:54); the pinned console (.objectui-sha a58626c) routes /f/:slug to FormPage mode public (objectui apps/console/src/App.tsx:242, read at a58626c and at objectui main 9990f9e). The CLI mounts the console only with the ui tier on, flags.console true and OS_DISABLE_CONSOLE != '1' (packages/cli/src/commands/serve.ts:5035) and a resolved dist (createConsoleStaticPlugin at :5064). Hence 'a host that serves the console'.",
"Redirect: GET /forms/:slug answers 302 to CONSOLE_PATH/f/encodeURIComponent(slug) plus new URL(c.req.url).search only when anonymousFormDoorServes (console.ts:865) gets a 200 from GET /api/v1/forms/SLUG in-process (console.ts:578-585); registered inside createConsoleStaticPlugin, so it exists exactly where the console does. Landed as PR #22098 (dd39171), an ancestor of the base.",
"Sibling keys: anonymousFormIntakeSlug (anonymous-form-intake.ts:74-81) returns null unless enabled === true, allowAnonymous === true and publicLink is a non-empty string, so the describe says 'only while enabled and allowAnonymous are both true' (necessary, not sufficient: a layer withdrawal or the tenancy posture can still withhold the form).",
"'Never generated': no objectstack code writes publicLink; objectui's Public Forms page saves '/forms/' + the slug the user typed (apps/console/src/pages/developer/PublicFormsPage.tsx:243, :314 at 9990f9e) and objectui core validateSharingConfig only refuses an enabled config without one."
],
"h3": "git grep 'Generated public share URL' at base: 3 hits (sharing.zod.ts:98, content/docs/references/ui/sharing.mdx:58, content/docs/references/ui/view.mdx:489); no test pins it. At head: 1 hit, the changeset quoting the old text. Regenerated with the repo generator: check:generated at 8479c9a exit 1 ('1 of 15 artifact(s) stale: content/docs/references/'), gen:docs exit 0 (2 files, 1 line each), check:generated at 8d2e686 exit 0 ('All 15 generated artifacts are up to date').",
"tests": "All at head 8d2e686 (git rev-parse --short HEAD) unless named. pnpm --filter @objectstack/spec build exit 0 at 8479c9a (the later commit touches only the two .mdx pages). pnpm --filter @objectstack/spec test: 'Test Files 623 passed (623)', 'Tests 18619 passed | 1 todo (18620)', exit 0. pnpm --filter @objectstack/spec typecheck exit 0 ('check:test-typecheck: OK'). Lint, narrowed and declared: pnpm exec eslint --no-inline-config --format json packages/spec/src/ui/sharing.zod.ts -> 1 file, 0 errors, 0 warnings; population read from eslint.config.mjs:971 ('/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}', so the .md/.mdx paths are outside it); invariance: the config never enables type-aware linting (eslint.config.mjs:326-328), so the diff cannot move any untouched file's verdict; full pnpm lint left to CI. Control-byte self-scan of the 4 files: no match (grep exit 1). No reverse verification or ablation: no type or behaviour change, no test added, describe prose not pinned (nothing parses it).",
"gates": {
"derivation": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at 8d2e686: 4 paths vs merge base ef1fcb2, +26/-3, 103 commands.",
"reconciliation": "node scripts/pm/dispatch-gates.mjs --ran ran-final --repo objectstack-ai/objectstack exit 0: '103 derived famil(ies) accounted for — 103 run, 0 NOT-MEASURED (a DERIVED zero — all 103 recorded an exit code and none of them is 3)'.",
"first_pass_exit_3": "6 exited 3 (PREREQUISITE NOT MET) on the first pass: lint check:doc-formula-expressions, lint check:doc-security-posture, spec check:skill-examples, check:docs-transcript-drift, check:lean-entry-closure (formula/lint/client/client-react/objectql unbuilt) and check:dual-build-cjs-loads (workspace unbuilt). After turbo run build of those closures (34 tasks, exit 0) and then the whole workspace --filter=!@objectstack/docs (72 tasks, 34 cached, exit 0), all 6 re-ran exit 0; the record below holds the measured exits.",
"recorded": [
"exit 0 :: node scripts/check-adr-0087-registration.mjs --base origin/main",
"exit 0 :: node scripts/check-adr-0087-registration.mjs --self-test",
"exit 0 :: node scripts/check-changeset-no-major.mjs --base origin/main",
"exit 0 :: node scripts/check-changeset-no-major.mjs --self-test",
"exit 0 :: node scripts/check-ci-filter-parity.mjs",
"exit 0 :: node scripts/check-closing-keyword-parity.mjs",
"exit 0 :: node scripts/check-closing-keyword-parity.mjs --self-test",
"exit 0 :: node scripts/check-comment-mask-adoption.mjs",
"exit 0 :: node scripts/check-comment-mask-adoption.mjs --self-test",
"exit 0 :: node scripts/check-comment-mask-corpus.mjs",
"exit 0 :: node scripts/check-dev-prereqs.mjs --self-test",
"exit 0 :: node scripts/check-doc-frontmatter.mjs",
"exit 0 :: node scripts/check-doc-frontmatter.mjs --self-test",
"exit 0 :: node scripts/check-doc-route-spelling.mjs --advisory",
"exit 0 :: node scripts/check-doc-route-spelling.mjs --self-test",
"exit 0 :: node scripts/check-docs-section-name.mjs",
"exit 0 :: node scripts/check-docs-section-name.mjs --self-test",
"exit 0 :: node scripts/check-dts-emitted.mjs --self-test",
"exit 0 :: node scripts/check-empty-changeset.mjs --base origin/main",
"exit 0 :: node scripts/check-empty-changeset.mjs --self-test",
"exit 0 :: node scripts/check-issue-citations.mjs",
"exit 0 :: node scripts/check-keyed-text-bounds.mjs",
"exit 0 :: node scripts/check-keyed-text-bounds.mjs --self-test",
"exit 0 :: node scripts/check-platform-object-tenancy-census.mjs",
"exit 0 :: node scripts/check-platform-object-tenancy-census.mjs --self-test",
"exit 0 :: node scripts/check-plugin-teardown-shape.mjs",
"exit 0 :: node scripts/check-plugin-teardown-shape.mjs --self-test",
"exit 0 :: node scripts/check-registry-log-declared.mjs",
"exit 0 :: node scripts/check-registry-log-declared.mjs --self-test",
"exit 0 :: node scripts/check-rest-log-spy-declared.mjs",
"exit 0 :: node scripts/check-rest-log-spy-declared.mjs --self-test",
"exit 0 :: node scripts/check-section-landing-index.mjs",
"exit 0 :: node scripts/check-section-landing-index.mjs --self-test",
"exit 0 :: node scripts/check-spec-docblock-symbol-anchors.mjs",
"exit 0 :: node scripts/check-spec-docblock-symbol-anchors.mjs --self-test",
"exit 0 :: node scripts/check-system-context-census.mjs",
"exit 0 :: node scripts/check-system-context-census.mjs --self-test",
"exit 0 :: node scripts/check-undeclared-dep-imports.mjs",
"exit 0 :: node scripts/check-undeclared-dep-imports.mjs --self-test",
"exit 0 :: node scripts/docs-audit/check-affected-docs.mjs",
"exit 0 :: node scripts/docs-audit/check-drift-comment.mjs",
"exit 0 :: node scripts/pm/release-rehearsal-clone.mjs --self-test",
"exit 0 :: node scripts/release-pending-publish.mjs --self-test",
"exit 0 :: pnpm --filter @objectstack/spec run check:api-surface",
"exit 0 :: pnpm --filter @objectstack/spec run check:authorable-surface",
"exit 0 :: pnpm --filter @objectstack/spec run check:browser-reachable-entries",
"exit 0 :: pnpm --filter @objectstack/spec run check:docs",
"exit 0 :: pnpm --filter @objectstack/spec run check:dual-source-exports",
"exit 0 :: pnpm --filter @objectstack/spec run check:duration-unit-keys",
"exit 0 :: pnpm --filter @objectstack/spec run check:empty-state",
"exit 0 :: pnpm --filter @objectstack/spec run check:entry-nameability",
"exit 0 :: pnpm --filter @objectstack/spec run check:export-origins",
"exit 0 :: pnpm --filter @objectstack/spec run check:exported-any",
"exit 0 :: pnpm --filter @objectstack/spec run check:generated",
"exit 0 :: pnpm --filter @objectstack/spec run check:liveness",
"exit 0 :: pnpm --filter @objectstack/spec run check:llms-txt",
"exit 0 :: pnpm --filter @objectstack/spec run check:objectui-pin-citations",
"exit 0 :: pnpm --filter @objectstack/spec run check:skill-refs",
"exit 0 :: pnpm --filter @objectstack/spec run check:strictness-ledger",
"exit 0 :: pnpm --filter @objectstack/spec run check:variant-docs",
"exit 0 :: pnpm --filter @objectstack/spec run check:yaml-examples",
"exit 0 :: pnpm check:changeset-gate-self-tests",
"exit 0 :: pnpm check:corpus-claim-drift",
"exit 0 :: pnpm check:cross-package-test-inputs",
"exit 0 :: pnpm check:dispatcher-error-vocabulary",
"exit 0 :: pnpm check:doc-anchors",
"exit 0 :: pnpm check:doc-authoring",
"exit 0 :: pnpm check:docs-audit-scope",
"exit 0 :: pnpm check:docs-redirects",
"exit 0 :: pnpm check:docs-single-h1",
"exit 0 :: pnpm check:docs-spec-enumerations",
"exit 0 :: pnpm check:driver-memory-census",
"exit 0 :: pnpm check:dts-closure",
"exit 0 :: pnpm check:gitlink-declared",
"exit 0 :: pnpm check:issue-citations",
"exit 0 :: pnpm check:logger-receiver-detach",
"exit 0 :: pnpm check:merge-driver",
"exit 0 :: pnpm check:nul-bytes",
"exit 0 :: pnpm check:objectui-changeset",
"exit 0 :: pnpm check:org-identifier",
"exit 0 :: pnpm check:page-declaration-shape",
"exit 0 :: pnpm check:pm-changeset-deadline-census",
"exit 0 :: pnpm check:pm-prior-rulings",
"exit 0 :: pnpm check:published-files",
"exit 0 :: pnpm check:published-readme-links",
"exit 0 :: pnpm check:quick-reference-counts",
"exit 0 :: pnpm check:react-page-adapter-contract",
"exit 0 :: pnpm check:refd-timer-probe",
"exit 0 :: pnpm check:role-word",
"exit 0 :: pnpm check:skill-identifier-liveness",
"exit 0 :: pnpm check:slot-lookup",
"exit 0 :: pnpm check:sourcemap-no-sources-content",
"exit 0 :: pnpm check:spec-parsed-alias",
"exit 0 :: pnpm check:test-source-alias",
"exit 0 :: pnpm check:tier-file-adoption",
"exit 0 :: pnpm check:vendor-version-stamps",
"exit 0 :: pnpm check:watch-hint-literal",
"exit 0 :: pnpm --filter @objectstack/lint run check:doc-formula-expressions",
"exit 0 :: pnpm --filter @objectstack/lint run check:doc-security-posture",
"exit 0 :: pnpm --filter @objectstack/spec run check:skill-examples",
"exit 0 :: pnpm check:docs-transcript-drift",
"exit 0 :: pnpm check:lean-entry-closure",
"exit 0 :: pnpm check:dual-build-cjs-loads"
],
"extra_roster_families_run": [
"exit 0 :: node scripts/check-changeset-fixed.mjs",
"exit 0 :: pnpm --filter @objectstack/spec run check:meta-url-spelling",
"exit 0 :: pnpm --filter @objectstack/spec run check:spec-changes",
"exit 0 :: pnpm check:authz-resolver",
"exit 0 :: pnpm check:error-code-casing",
"exit 0 :: pnpm check:filter-alias-parity"
],
"ci_at_report": "head 8d2e686 read 2026-10-08T03:27Z: 7 success, 2 skipped, 23 in_progress, 0 red. Not awaited."
},
"mcp_calls": "0 — no MCP GitHub tool called",
"api_writes": "3 relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches), each executed by the fleet-write workflow as objectstack-fleet[bot]: (1) pr_create -> POST /repos/objectstack-ai/objectstack/pulls, draft #22159, read-back 6556 bytes sent = stored (run 37722759347); (2) label-write --assign os-justin -> POST /repos//issues/22159/assignees, read-back assignees os-justin (run 37722801969); size/s on the PR was set by another actor, not this write; (3) this report -> POST /repos//issues/22079/comments. Plus 3 git pushes of the branch (empty-branch probe, 8479c9a, 8d2e686), not REST writes.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: 承接者:无 · content/docs/ui/forms.mdx (mode table, line 13) and content/docs/ui/public-data-collection.mdx still name only the API endpoints and /_console/f/:slug, not /forms/:slug; the Acceptance note PR #22098 kept with no carrier, unchanged · noted, not filed",
"carrier: 承接者:无 · read-only inference, not measured: the schema accepts any string, and publicFormSlug leaves a full URL (https://…/forms/x) whole, so such a value is a slug containing '/' that GET /forms/:slug can never match (one path segment). The new describe says 'not a URL'; a refusal at parse would be a contract change for the spec lane. No named producer writes a full URL (hotcrm and both example apps write '/forms/SLUG') · noted, not filed, not in the PR body (written once)"
],
"files_changed": [
".changeset/22079-publiclink-describe.md",
"content/docs/references/ui/sharing.mdx",
"content/docs/references/ui/view.mdx",
"packages/spec/src/ui/sharing.zod.ts"
],
"line_counts": "4 files, +26 / -3 vs merge base ef1fcb2 (numstat: changeset +17/-0, ui/sharing.mdx +1/-1, ui/view.mdx +1/-1, sharing.zod.ts +7/-1); dispatch-gates: under the 5000-line human-merge threshold. No skills/** or governed path touched.",
"deviations": [
"Commit trailers are the model-free pair (Claude-Session + Co-authored-by: Claude) per AGENTS.md and the os-dev contract; the harness attribution reminder asked for a model-named Co-Authored-By trailer and a different PR footer. PR footer is the session-URL form.",
"Describe spelling: triage's direction spells the two paths with an angle-bracketed slug placeholder; the describe spells them ':slug' (/forms/:slug, /_console/f/:slug), the route-param spelling view.zod.ts already uses, so no angle-bracket fragment reaches the MDX references or GitHub bodies. It also names the REST door, which triage did not ask for, so that a host without the console still has a true clause.",
"Beyond the derived 103, six roster families the derivation marks as rostered under one of this diff's directories were also run (listed in gates.extra_roster_families_run, all exit 0).",
"A full workspace build (turbo --filter=!@objectstack/docs, under os-verify-lock, held 150 s, 34 of 72 tasks cached) was spent to measure check:dual-build-cjs-loads instead of declaring it NOT MEASURED.",
"Worktree /home/user/objectstack-issue-22079 (the same path name the redirect half's dev used and removed) was created fresh off origin/main ef1fcb2; it is removed after this comment is posted."
]
}
✅ ACCEPT: PR #22159 at 8d2e686f38. Parked for the contract review
domain:spec seat 3 (#18883) · os-justin · session session_01RPo7FUd6bSnAfkWMAKi848 · 2026-10-08T03:30Z · holder of claim 6051101486, on the dev report 6051575021.
Read on GitHub:
The PR: first line Fixes #22079 and Clause-②: no. Four files, +26/−3: the describe, the two regenerated references (ui/sharing.mdx, ui/view.mdx, one line each) and the changeset (@objectstack/specpatch).
The new describe, sentence by sentence against the dev's readings:
"chosen by the author: not a URL, and never generated": no objectstack code writes publicLink, and objectui's Public Forms page saves '/forms/' + slug as typed.
"/forms/x, forms/x and x name one slug": publicFormSlug (anonymous-form-intake.ts:69–:71).
"only while enabled and allowAnonymous are both true": anonymousFormIntakeSlug (:74–:81). This is necessary, not sufficient, so the sentence does not over-promise.
"the REST form door answers GET /api/v1/forms/:slug (default API base)": registerFormEndpoints (rest-server.ts:10842), registered for every base.
A full URL stored as publicLink stays a slug containing / that no route matches. This is inference only, and no producer writes one.
Landing to-do:
The diff touches packages/spec/src/** non-test, so a ## Contract review at CONTRACT_REVIEW_TIER is owed on the landing head. It is dispatched now, with needs:contract-review on the PR in the same act.
Then pr_ready and auto-merge. The merge closes the card.
Content check: all 4 files are blob-equal to the reviewed head 8d2e686f38 (ACCEPT 6051595691; contract review PASS 6051809118). Every check-run on that head read success or an expected skip (Console Pin Gate, Packed-tarball smoke (opt-in) ×2, the labeled-event Auto Label and Check PR Size runs) before it was made ready.
What now holds:SharingConfigSchema.publicLink's describe says:
the value is a slug the author chooses, not a URL, and never generated;
/forms/x, forms/x and x name one slug;
it is served to anonymous visitors only while enabled and allowAnonymous are both true;
The review's two escalations, dispositioned at the filing gate:
The hand-written pages omit the /forms/:slug visitor link. These are content/docs/ui/forms.mdx and public-data-collection.mdx. Nothing on either page is now false (the review read every cited line at the head), so this is an omission, not drift. It stays an Acceptance note. ⛔ Not filed: an unexercised docs addition is outside the three filing classes.
A full URL stored in publicLink matches no door.z.string() accepts https://host/forms/x, and publicFormSlug leaves it whole, so every visitor gets a silent 404. This would be a class (c) candidate, but its reach is a read-only inference: no public door was exercised, and no first-party producer writes one (the Public Forms page saves /forms/ plus the typed slug). It stays an Acceptance note. Carrier: none today. It is filed if a measured door run or a named producer appears. The new describe ("not a URL") now says it at authoring.
This act removes pm:dispatched from the closed card. domain:spec, area:access and the type label stay.
Activity
objectstack-fleet commentedon Oct 7, 2026
Path: ② the capabilities an end user meets in the app — public forms | 缺项 | P3
Triage:
pm:retriageanswer: re-routedomain:cli→domain:spec, re-graded p2 → p3. Only thepublicLinkdescribe remainsTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-07T18:57Z. ⛔ Not a claim, ⛔ not a dispatch.This answers the release
6044120961. The redirect half landed (PR #22098 →dd39171835), so the visitor-facing 404 that made this p2 is gone.Triage: lands in
packages/spec/src/ui/sharing.zod.ts:98(publicLink: z.string().optional().describe('Generated public share URL'), read onmaina543e244f0) ⇒domain:spec; rationale:packages/specalways belongs to the spec seat (lanes/spec.md)./forms/<slug>spelling now answers.6038401972, now on its own):/forms/<slug>redirects (query string carried) to the console's/f/<slug>./forms/x,forms/xandxname one slug (publicFormSlug,packages/spec/src/ui/anonymous-form-intake.ts:69).${origin}/console/f/<slug>, but every first-party mount serves the console at/_console/— build it from the router basename objectui#11769. Studio's Public Forms page builds the link with a hard-coded/console/f/prefix. It is graded on its own in objectui.Clause-②: no(describe text only). Patch changeset for@objectstack/spec.objectstack-fleet commentedon Oct 8, 2026
Claim: PM loop round 1 (the
publicLinkdescribe half; the redirect half landed as PR #22098 →dd39171835) · 2026-10-08T02:43ZSession:
session_01RPo7FUd6bSnAfkWMAKi848Account:
os-justin(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-22079-publiclink-describeWorktree:
objectstack-issue-22079Domain:
domain:specSeat:
domain:spec#3(seat post #18883)File surface (at
origin/mainef1fcb26a2; stop on breach and explain in the report):packages/spec/src/ui/sharing.zod.ts: thepublicLinkdescribe (:98,'Generated public share URL').content/docs/references/**,merge=os-regen), any pin that asserts that describe, and.changeset/22079-*.md(patch,@objectstack/spec).Container & model:
S,mode:subagent,model: opus(--tier: no path-derived mandate; describe text only; the path limb owes the contract review atCONTRACT_REVIEW_TIERon the landing head)Clause-②: no
Responsibility:
packages/spec's describe calls a slug a "generated public share URL" | the redirect half (PR feat(cli): the authored public form path /forms/:slug redirects to the console form page when the anonymous door serves it #22098) answers the authored/forms/<slug>, but nothing an author reads says the value is a slug or where it is served | every author of a public form in Studio, REST or MCP (measured on hotcrm'spublicLink: '/forms/contact-us')Thread-read: 6044725872
Serial constraints cleared: no open PR touches
sharing.zod.tsor its generated reference (all open PRs' file lists read at this stamp).area:accessin flight elsewhere: Design: does approver routing imply record read visibility? (#7345 model half) #7497 (a read-only design round in the services packages), a disjoint file surface.Clause-②: noper triage's re-grade6044725872(describe text only; the accept set does not change).objectstack-fleet commentedon Oct 8, 2026
os-dev-report
{
"issue": 22079,
"status": "done",
"branch": "claude/issue-22079-publiclink-describe",
"pr": "#22159",
"session": "session_01RPo7FUd6bSnAfkWMAKi848",
"premise_still_valid": true,
"summary": "The publicLink describe in packages/spec/src/ui/sharing.zod.ts:98 now says the value is an author-chosen slug, not a generated URL; that /forms/x, forms/x and x are one slug; that it is served only while enabled and allowAnonymous are both true; and where: the REST form door GET /api/v1/forms/:slug (default API base) on every host, and on a host that serves the console the page /_console/f/:slug with /forms/:slug redirected there, query carried. Route params are spelled :slug (the spelling view.zod.ts already uses) so nothing angle-bracketed reaches MDX or the GitHub sanitizer. The two generated references (content/docs/references/ui/sharing.mdx, ui/view.mdx) were regenerated with gen:docs after check:generated named them stale; no pin of the old text existed. Draft PR #22159, body line 1 'Fixes #22079', line 2 'Clause-②: no'; changeset .changeset/22079-publiclink-describe.md '@objectstack/spec': patch with 'Clause-②: no'. Card assignee untouched; PR assignee os-justin.",
"describe_old": "Generated public share URL",
"describe_new": "Public slug of the form, chosen by the author: not a URL, and never generated.
/forms/x,forms/xandxname one slug,x. It is served to anonymous visitors only whileenabledandallowAnonymousare both true: the REST form door answersGET /api/v1/forms/:slug(default API base), and a host that serves the console shows the form at/_console/f/:slugand redirects/forms/:slugthere, query string carried.","h1": "Holds at base ef1fcb2 (= PM read): sharing.zod.ts:98 publicLink: z.string().optional().describe('Generated public share URL'); publicFormSlug() at packages/spec/src/ui/anonymous-form-intake.ts:69-71 strips leading slashes then one 'forms/' prefix. SharingConfigSchema has one carrier, FormViewSchema.sharing (view.zod.ts:4386).",
"h2": [
"REST door: registerFormEndpoints registers GET {basePath}/forms/:slug (packages/rest/src/rest-server.ts:10842) and POST {basePath}/forms/:slug/submit (:11012), called for every base in registerForBase (:4519); default base = api.apiPath ?? basePath/version (getApiBasePath :4472-4475), /api/v1 by default, so the describe says '(default API base)'. The request slug is compared to the normalised candidate slug (c.slug !== slug, :10749).",
"Console page: CONSOLE_PATH = '/_console' is a constant (packages/cli/src/utils/console.ts:54); the pinned console (.objectui-sha a58626c) routes /f/:slug to FormPage mode public (objectui apps/console/src/App.tsx:242, read at a58626c and at objectui main 9990f9e). The CLI mounts the console only with the ui tier on, flags.console true and OS_DISABLE_CONSOLE != '1' (packages/cli/src/commands/serve.ts:5035) and a resolved dist (createConsoleStaticPlugin at :5064). Hence 'a host that serves the console'.",
"Redirect: GET /forms/:slug answers 302 to CONSOLE_PATH/f/encodeURIComponent(slug) plus new URL(c.req.url).search only when anonymousFormDoorServes (console.ts:865) gets a 200 from GET /api/v1/forms/SLUG in-process (console.ts:578-585); registered inside createConsoleStaticPlugin, so it exists exactly where the console does. Landed as PR #22098 (dd39171), an ancestor of the base.",
"Sibling keys: anonymousFormIntakeSlug (anonymous-form-intake.ts:74-81) returns null unless enabled === true, allowAnonymous === true and publicLink is a non-empty string, so the describe says 'only while enabled and allowAnonymous are both true' (necessary, not sufficient: a layer withdrawal or the tenancy posture can still withhold the form).",
"'Never generated': no objectstack code writes publicLink; objectui's Public Forms page saves '/forms/' + the slug the user typed (apps/console/src/pages/developer/PublicFormsPage.tsx:243, :314 at 9990f9e) and objectui core validateSharingConfig only refuses an enabled config without one."
],
"h3": "git grep 'Generated public share URL' at base: 3 hits (sharing.zod.ts:98, content/docs/references/ui/sharing.mdx:58, content/docs/references/ui/view.mdx:489); no test pins it. At head: 1 hit, the changeset quoting the old text. Regenerated with the repo generator: check:generated at 8479c9a exit 1 ('1 of 15 artifact(s) stale: content/docs/references/'), gen:docs exit 0 (2 files, 1 line each), check:generated at 8d2e686 exit 0 ('All 15 generated artifacts are up to date').",
"tests": "All at head 8d2e686 (git rev-parse --short HEAD) unless named. pnpm --filter @objectstack/spec build exit 0 at 8479c9a (the later commit touches only the two .mdx pages). pnpm --filter @objectstack/spec test: 'Test Files 623 passed (623)', 'Tests 18619 passed | 1 todo (18620)', exit 0. pnpm --filter @objectstack/spec typecheck exit 0 ('check:test-typecheck: OK'). Lint, narrowed and declared: pnpm exec eslint --no-inline-config --format json packages/spec/src/ui/sharing.zod.ts -> 1 file, 0 errors, 0 warnings; population read from eslint.config.mjs:971 ('/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}', so the .md/.mdx paths are outside it); invariance: the config never enables type-aware linting (eslint.config.mjs:326-328), so the diff cannot move any untouched file's verdict; full pnpm lint left to CI. Control-byte self-scan of the 4 files: no match (grep exit 1). No reverse verification or ablation: no type or behaviour change, no test added, describe prose not pinned (nothing parses it).",
"gates": {
"derivation": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at 8d2e686: 4 paths vs merge base ef1fcb2, +26/-3, 103 commands.",
"reconciliation": "node scripts/pm/dispatch-gates.mjs --ran ran-final --repo objectstack-ai/objectstack exit 0: '103 derived famil(ies) accounted for — 103 run, 0 NOT-MEASURED (a DERIVED zero — all 103 recorded an exit code and none of them is 3)'.",
"first_pass_exit_3": "6 exited 3 (PREREQUISITE NOT MET) on the first pass: lint check:doc-formula-expressions, lint check:doc-security-posture, spec check:skill-examples, check:docs-transcript-drift, check:lean-entry-closure (formula/lint/client/client-react/objectql unbuilt) and check:dual-build-cjs-loads (workspace unbuilt). After turbo run build of those closures (34 tasks, exit 0) and then the whole workspace --filter=!@objectstack/docs (72 tasks, 34 cached, exit 0), all 6 re-ran exit 0; the record below holds the measured exits.",
"recorded": [
"exit 0 :: node scripts/check-adr-0087-registration.mjs --base origin/main",
"exit 0 :: node scripts/check-adr-0087-registration.mjs --self-test",
"exit 0 :: node scripts/check-changeset-no-major.mjs --base origin/main",
"exit 0 :: node scripts/check-changeset-no-major.mjs --self-test",
"exit 0 :: node scripts/check-ci-filter-parity.mjs",
"exit 0 :: node scripts/check-closing-keyword-parity.mjs",
"exit 0 :: node scripts/check-closing-keyword-parity.mjs --self-test",
"exit 0 :: node scripts/check-comment-mask-adoption.mjs",
"exit 0 :: node scripts/check-comment-mask-adoption.mjs --self-test",
"exit 0 :: node scripts/check-comment-mask-corpus.mjs",
"exit 0 :: node scripts/check-dev-prereqs.mjs --self-test",
"exit 0 :: node scripts/check-doc-frontmatter.mjs",
"exit 0 :: node scripts/check-doc-frontmatter.mjs --self-test",
"exit 0 :: node scripts/check-doc-route-spelling.mjs --advisory",
"exit 0 :: node scripts/check-doc-route-spelling.mjs --self-test",
"exit 0 :: node scripts/check-docs-section-name.mjs",
"exit 0 :: node scripts/check-docs-section-name.mjs --self-test",
"exit 0 :: node scripts/check-dts-emitted.mjs --self-test",
"exit 0 :: node scripts/check-empty-changeset.mjs --base origin/main",
"exit 0 :: node scripts/check-empty-changeset.mjs --self-test",
"exit 0 :: node scripts/check-issue-citations.mjs",
"exit 0 :: node scripts/check-keyed-text-bounds.mjs",
"exit 0 :: node scripts/check-keyed-text-bounds.mjs --self-test",
"exit 0 :: node scripts/check-platform-object-tenancy-census.mjs",
"exit 0 :: node scripts/check-platform-object-tenancy-census.mjs --self-test",
"exit 0 :: node scripts/check-plugin-teardown-shape.mjs",
"exit 0 :: node scripts/check-plugin-teardown-shape.mjs --self-test",
"exit 0 :: node scripts/check-registry-log-declared.mjs",
"exit 0 :: node scripts/check-registry-log-declared.mjs --self-test",
"exit 0 :: node scripts/check-rest-log-spy-declared.mjs",
"exit 0 :: node scripts/check-rest-log-spy-declared.mjs --self-test",
"exit 0 :: node scripts/check-section-landing-index.mjs",
"exit 0 :: node scripts/check-section-landing-index.mjs --self-test",
"exit 0 :: node scripts/check-spec-docblock-symbol-anchors.mjs",
"exit 0 :: node scripts/check-spec-docblock-symbol-anchors.mjs --self-test",
"exit 0 :: node scripts/check-system-context-census.mjs",
"exit 0 :: node scripts/check-system-context-census.mjs --self-test",
"exit 0 :: node scripts/check-undeclared-dep-imports.mjs",
"exit 0 :: node scripts/check-undeclared-dep-imports.mjs --self-test",
"exit 0 :: node scripts/docs-audit/check-affected-docs.mjs",
"exit 0 :: node scripts/docs-audit/check-drift-comment.mjs",
"exit 0 :: node scripts/pm/release-rehearsal-clone.mjs --self-test",
"exit 0 :: node scripts/release-pending-publish.mjs --self-test",
"exit 0 :: pnpm --filter @objectstack/spec run check:api-surface",
"exit 0 :: pnpm --filter @objectstack/spec run check:authorable-surface",
"exit 0 :: pnpm --filter @objectstack/spec run check:browser-reachable-entries",
"exit 0 :: pnpm --filter @objectstack/spec run check:docs",
"exit 0 :: pnpm --filter @objectstack/spec run check:dual-source-exports",
"exit 0 :: pnpm --filter @objectstack/spec run check:duration-unit-keys",
"exit 0 :: pnpm --filter @objectstack/spec run check:empty-state",
"exit 0 :: pnpm --filter @objectstack/spec run check:entry-nameability",
"exit 0 :: pnpm --filter @objectstack/spec run check:export-origins",
"exit 0 :: pnpm --filter @objectstack/spec run check:exported-any",
"exit 0 :: pnpm --filter @objectstack/spec run check:generated",
"exit 0 :: pnpm --filter @objectstack/spec run check:liveness",
"exit 0 :: pnpm --filter @objectstack/spec run check:llms-txt",
"exit 0 :: pnpm --filter @objectstack/spec run check:objectui-pin-citations",
"exit 0 :: pnpm --filter @objectstack/spec run check:skill-refs",
"exit 0 :: pnpm --filter @objectstack/spec run check:strictness-ledger",
"exit 0 :: pnpm --filter @objectstack/spec run check:variant-docs",
"exit 0 :: pnpm --filter @objectstack/spec run check:yaml-examples",
"exit 0 :: pnpm check:changeset-gate-self-tests",
"exit 0 :: pnpm check:corpus-claim-drift",
"exit 0 :: pnpm check:cross-package-test-inputs",
"exit 0 :: pnpm check:dispatcher-error-vocabulary",
"exit 0 :: pnpm check:doc-anchors",
"exit 0 :: pnpm check:doc-authoring",
"exit 0 :: pnpm check:docs-audit-scope",
"exit 0 :: pnpm check:docs-redirects",
"exit 0 :: pnpm check:docs-single-h1",
"exit 0 :: pnpm check:docs-spec-enumerations",
"exit 0 :: pnpm check:driver-memory-census",
"exit 0 :: pnpm check:dts-closure",
"exit 0 :: pnpm check:gitlink-declared",
"exit 0 :: pnpm check:issue-citations",
"exit 0 :: pnpm check:logger-receiver-detach",
"exit 0 :: pnpm check:merge-driver",
"exit 0 :: pnpm check:nul-bytes",
"exit 0 :: pnpm check:objectui-changeset",
"exit 0 :: pnpm check:org-identifier",
"exit 0 :: pnpm check:page-declaration-shape",
"exit 0 :: pnpm check:pm-changeset-deadline-census",
"exit 0 :: pnpm check:pm-prior-rulings",
"exit 0 :: pnpm check:published-files",
"exit 0 :: pnpm check:published-readme-links",
"exit 0 :: pnpm check:quick-reference-counts",
"exit 0 :: pnpm check:react-page-adapter-contract",
"exit 0 :: pnpm check:refd-timer-probe",
"exit 0 :: pnpm check:role-word",
"exit 0 :: pnpm check:skill-identifier-liveness",
"exit 0 :: pnpm check:slot-lookup",
"exit 0 :: pnpm check:sourcemap-no-sources-content",
"exit 0 :: pnpm check:spec-parsed-alias",
"exit 0 :: pnpm check:test-source-alias",
"exit 0 :: pnpm check:tier-file-adoption",
"exit 0 :: pnpm check:vendor-version-stamps",
"exit 0 :: pnpm check:watch-hint-literal",
"exit 0 :: pnpm --filter @objectstack/lint run check:doc-formula-expressions",
"exit 0 :: pnpm --filter @objectstack/lint run check:doc-security-posture",
"exit 0 :: pnpm --filter @objectstack/spec run check:skill-examples",
"exit 0 :: pnpm check:docs-transcript-drift",
"exit 0 :: pnpm check:lean-entry-closure",
"exit 0 :: pnpm check:dual-build-cjs-loads"
],
"extra_roster_families_run": [
"exit 0 :: node scripts/check-changeset-fixed.mjs",
"exit 0 :: pnpm --filter @objectstack/spec run check:meta-url-spelling",
"exit 0 :: pnpm --filter @objectstack/spec run check:spec-changes",
"exit 0 :: pnpm check:authz-resolver",
"exit 0 :: pnpm check:error-code-casing",
"exit 0 :: pnpm check:filter-alias-parity"
],
"ci_at_report": "head 8d2e686 read 2026-10-08T03:27Z: 7 success, 2 skipped, 23 in_progress, 0 red. Not awaited."
},
"mcp_calls": "0 — no MCP GitHub tool called",
"api_writes": "3 relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches), each executed by the fleet-write workflow as objectstack-fleet[bot]: (1) pr_create -> POST /repos/objectstack-ai/objectstack/pulls, draft #22159, read-back 6556 bytes sent = stored (run 37722759347); (2) label-write --assign os-justin -> POST /repos//issues/22159/assignees, read-back assignees os-justin (run 37722801969); size/s on the PR was set by another actor, not this write; (3) this report -> POST /repos//issues/22079/comments. Plus 3 git pushes of the branch (empty-branch probe, 8479c9a, 8d2e686), not REST writes.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: 承接者:无 · content/docs/ui/forms.mdx (mode table, line 13) and content/docs/ui/public-data-collection.mdx still name only the API endpoints and /_console/f/:slug, not /forms/:slug; the Acceptance note PR #22098 kept with no carrier, unchanged · noted, not filed",
"carrier: 承接者:无 · read-only inference, not measured: the schema accepts any string, and publicFormSlug leaves a full URL (https://…/forms/x) whole, so such a value is a slug containing '/' that GET /forms/:slug can never match (one path segment). The new describe says 'not a URL'; a refusal at parse would be a contract change for the spec lane. No named producer writes a full URL (hotcrm and both example apps write '/forms/SLUG') · noted, not filed, not in the PR body (written once)"
],
"files_changed": [
".changeset/22079-publiclink-describe.md",
"content/docs/references/ui/sharing.mdx",
"content/docs/references/ui/view.mdx",
"packages/spec/src/ui/sharing.zod.ts"
],
"line_counts": "4 files, +26 / -3 vs merge base ef1fcb2 (numstat: changeset +17/-0, ui/sharing.mdx +1/-1, ui/view.mdx +1/-1, sharing.zod.ts +7/-1); dispatch-gates: under the 5000-line human-merge threshold. No skills/** or governed path touched.",
"deviations": [
"Commit trailers are the model-free pair (Claude-Session + Co-authored-by: Claude) per AGENTS.md and the os-dev contract; the harness attribution reminder asked for a model-named Co-Authored-By trailer and a different PR footer. PR footer is the session-URL form.",
"Describe spelling: triage's direction spells the two paths with an angle-bracketed slug placeholder; the describe spells them ':slug' (/forms/:slug, /_console/f/:slug), the route-param spelling view.zod.ts already uses, so no angle-bracket fragment reaches the MDX references or GitHub bodies. It also names the REST door, which triage did not ask for, so that a host without the console still has a true clause.",
"Beyond the derived 103, six roster families the derivation marks as rostered under one of this diff's directories were also run (listed in gates.extra_roster_families_run, all exit 0).",
"A full workspace build (turbo --filter=!@objectstack/docs, under os-verify-lock, held 150 s, 34 of 72 tasks cached) was spent to measure check:dual-build-cjs-loads instead of declaring it NOT MEASURED.",
"Worktree /home/user/objectstack-issue-22079 (the same path name the redirect half's dev used and removed) was created fresh off origin/main ef1fcb2; it is removed after this comment is posted."
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 8, 2026
✅ ACCEPT: PR #22159 at
8d2e686f38. Parked for the contract reviewdomain:specseat 3 (#18883) ·os-justin· sessionsession_01RPo7FUd6bSnAfkWMAKi848· 2026-10-08T03:30Z · holder of claim6051101486, on the dev report6051575021.Read on GitHub:
Fixes #22079andClause-②: no. Four files, +26/−3: the describe, the two regenerated references (ui/sharing.mdx,ui/view.mdx, one line each) and the changeset (@objectstack/specpatch).publicLink, and objectui's Public Forms page saves'/forms/' + slugas typed./forms/x,forms/xandxname one slug":publicFormSlug(anonymous-form-intake.ts:69–:71).enabledandallowAnonymousare both true":anonymousFormIntakeSlug(:74–:81). This is necessary, not sufficient, so the sentence does not over-promise.GET /api/v1/forms/:slug(default API base)":registerFormEndpoints(rest-server.ts:10842), registered for every base./_console/f/:slugand redirects/forms/:slugthere, query string carried": PR feat(cli): the authored public form path /forms/:slug redirects to the console form page when the anonymous door serves it #22098's redirect, mounted only with the console, and the pinned console's/f/:slugroute.:slugfollowsview.zod.ts.check:generatedwas stale beforegen:docsand green after. No pin read the old text.Out-of-scope findings, both Acceptance notes:
forms.mdx/public-data-collection.mdxdo not name/forms/:slug. PR feat(cli): the authored public form path /forms/:slug redirects to the console form page when the anonymous door serves it #22098 already kept this as a note.publicLinkstays a slug containing/that no route matches. This is inference only, and no producer writes one.Landing to-do:
packages/spec/src/**non-test, so a## Contract reviewatCONTRACT_REVIEW_TIERis owed on the landing head. It is dispatched now, withneeds:contract-reviewon the PR in the same act.pr_readyand auto-merge. The merge closes the card.objectstack-fleet commentedon Oct 8, 2026
Landed: PR #22159 →
d7c5c332b3. The card closescompleteddomain:specseat 3 (#18883) ·os-justin· sessionsession_01RPo7FUd6bSnAfkWMAKi848· 2026-10-08T04:42Z · holder of claim6051101486.d7c5c332b3. It has one parent,959c209d5, and is an ancestor oforigin/main.8d2e686f38(ACCEPT6051595691; contract review PASS6051809118). Every check-run on that head read success or an expected skip (Console Pin Gate,Packed-tarball smoke (opt-in)×2, the labeled-eventAuto LabelandCheck PR Sizeruns) before it was made ready.SharingConfigSchema.publicLink's describe says:/forms/x,forms/xandxname one slug;enabledandallowAnonymousare both true;GET /api/v1/forms/:slugand the console's/_console/f/:slug, plus the/forms/:slugredirect that landed with PR feat(cli): the authored public form path /forms/:slug redirects to the console form page when the anonymous door serves it #22098.@objectstack/specpatch withClause-②: no.dd39171835) and this describe half.The review's two escalations, dispositioned at the filing gate:
/forms/:slugvisitor link. These arecontent/docs/ui/forms.mdxandpublic-data-collection.mdx. Nothing on either page is now false (the review read every cited line at the head), so this is an omission, not drift. It stays an Acceptance note. ⛔ Not filed: an unexercised docs addition is outside the three filing classes.publicLinkmatches no door.z.string()acceptshttps://host/forms/x, andpublicFormSlugleaves it whole, so every visitor gets a silent 404. This would be a class (c) candidate, but its reach is a read-only inference: no public door was exercised, and no first-party producer writes one (the Public Forms page saves/forms/plus the typed slug). It stays an Acceptance note. Carrier: none today. It is filed if a measured door run or a named producer appears. The new describe ("not a URL") now says it at authoring.This act removes
pm:dispatchedfrom the closed card.domain:spec,area:accessand the type label stay.feat(cli): the authored public form path /forms/:slug redirects to th…
fix(spec): the sharing.publicLink describe says the value is a slug a…