Repository navigation
fix(spec): the sharing.publicLink describe says the value is a slug and names where it is served - #22159
Conversation
…nd names where it is served The describe called the value a "Generated public share URL". The author chooses it, nothing generates it, and the server reads it as a slug (publicFormSlug: /forms/x, forms/x and x are one slug). The describe now says so and names the REST form door and, on a console host, the console page /_console/f/:slug with the /forms/:slug redirect. Claude-Session: https://claude.ai/code/session_01RPo7FUd6bSnAfkWMAKi848 Co-authored-by: Claude <noreply@anthropic.com>
…publicLink describe pnpm --filter @objectstack/spec gen:docs, after check:generated named content/docs/references/** as the one stale artifact. Claude-Session: https://claude.ai/code/session_01RPo7FUd6bSnAfkWMAKi848 Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 3 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 2 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 139 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin b7213edd140aea2e5e050e7cbbfe560586d4e30b && git checkout b7213edd140aea2e5e050e7cbbfe560586d4e30b
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin fec87e7e0753f66a6bb92607f436b6b1429f4112 8d2e686f38b1bfe69d4e211623b2ea40837f1476 && git checkout -B drift-repro fec87e7e0753f66a6bb92607f436b6b1429f4112 && git merge --no-ff 8d2e686f38b1bfe69d4e211623b2ea40837f1476
node scripts/docs-audit/affected-docs.mjs --json fec87e7e0753f66a6bb92607f436b6b1429f4112
|
Contract reviewServed-tier: PR #22159 on card #22079: the describe half of the card. The redirect half landed as PR #22098 ( ① Derived judgmentsThe diff changes ONE
The describe's six clauses, each read against source at the head:
Spelling: route parameters are spelled Nothing in ① is judged wrong. ② Semver level
③ Boundary flagsDev report
Out-of-scope findings, both kept as Acceptance notes by the seat in
Noted, no action: the alias-block comment Scope and shape: 4 files, all inside the surface claim Check-runs on the head, as read (conclusions are the gate verdicts;
Implemented-by: VERDICT: PASS |
Fixes #22079
Clause-②: no
The describe half of the card. The redirect half landed as PR #22098 (
dd39171835), so this PR closes the card.What changes
FormView.sharing.publicLink(packages/spec/src/ui/sharing.zod.ts) described itself as aGenerated public share URL. It is neither generated nor a URL. The describe now reads:The two generated reference pages that print it (
content/docs/references/ui/sharing.mdx,content/docs/references/ui/view.mdx) are regenerated withgen:docsafter the spec build (which runsgen:schema). Nothing is hand-edited. The changeset is@objectstack/specpatch.Describe text only. The accepted values, keys, types and exports do not change.
Each clause, and what makes it true on every host (read at base
ef1fcb26a2)publicFormSlug()(packages/spec/src/ui/anonymous-form-intake.ts:69-71) strips leading slashes and oneforms/prefix, so/forms/x,forms/xandxare one slug. Every door compares that slug to the request's:slug(anonymousFormIntakeCandidates,c.slug !== sluginfindPublicFormView,packages/rest/src/rest-server.ts:10749)./forms/plus the slug the user typed (objectuiapps/console/src/pages/developer/PublicFormsPage.tsx:243,:314, at9990f9e). objectui'svalidateSharingConfigrefuses an enabled config without one; it does not make one.enabledandallowAnonymousare both true.anonymousFormIntakeSlug()returnsnullunlessenabled === true,allowAnonymous === trueandpublicLinkis a non-empty string (anonymous-form-intake.ts:74-81). Those two switches are necessary, not sufficient: a withdrawal in another layer or the tenancy posture can still withhold the form. "Only while" claims no more than that.registerFormEndpointsregistersGET {basePath}/forms/:slugandPOST {basePath}/forms/:slug/submit(rest-server.ts:10842,:11012) for every base (registerForBase,:4519). The default base is/api/v1(getApiBasePath,:4472-4475);api.apiPathcan move it, hence "(default API base)".CONSOLE_PATH = '/_console'(packages/cli/src/utils/console.ts:54). The pinned console (.objectui-shaa58626c88) routes/f/:slugto the publicFormPage(objectuiapps/console/src/App.tsx:242). The CLI mounts the console only when the UI tier is on,--no-console/OS_DISABLE_CONSOLE=1are absent and a console dist resolves (packages/cli/src/commands/serve.ts:5035,:5064). So the describe says "a host that serves the console".GET /forms/:sluganswers302to${CONSOLE_PATH}/f/${encodeURIComponent(slug)}plus the request's query string, only when the anonymous door serves that slug (console.ts:578-585,anonymousFormDoorServes:865). It is registered insidecreateConsoleStaticPlugin, so it exists exactly where the console does.Pins and readers
git grep "Generated public share URL"at base: three hits, the describe and the two generated pages. No test pins the text. At head: one hit, the changeset quoting the old text.Out of scope
${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 link), per triage6044725872.content/docs/ui/forms.mdx,content/docs/ui/public-data-collection.mdx) still do not name the visitor link. That was kept as an Acceptance note with no carrier on PR feat(cli): the authored public form path /forms/:slug redirects to the console form page when the anonymous door serves it #22098, and it stays one here.Verification
All at head
8d2e686f3unless named. Each exit code captured before any pipe.pnpm --filter @objectstack/spec buildexit 0 (at8479c9a3a; the later commit touches only the two generated pages, notpackages/spec).pnpm --filter @objectstack/spec check:generatedat8479c9a3a: exit 1,1 of 15 artifact(s) stale: content/docs/references/**. Thengen:docs(exit 0) changed exactlyui/sharing.mdxandui/view.mdx, one line each. At8d2e686f3:All 15 generated artifacts are up to date, exit 0.pnpm --filter @objectstack/spec test:Test Files 623 passed (623),Tests 18619 passed | 1 todo (18620), exit 0.pnpm --filter @objectstack/spec typecheckexit 0 (check:test-typecheck: OK).node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 103 commands for the 4 paths. All 103 ran. Six first exited 3 (PREREQUISITE NOT MET:@objectstack/formula,@objectstack/lint,@objectstack/client,@objectstack/client-react,@objectstack/objectqland the workspace were not built). They exited 0 afterturbo run buildof those closures and then the whole workspace (--filter=!@objectstack/docs).dispatch-gates --ran:103 derived famil(ies) accounted for, 103 run, 0 NOT-MEASURED. Also run, for the six roster families the derivation flags as rostered under one of these paths:check-changeset-fixed,check:meta-url-spelling,check:spec-changes,check:authz-resolver,check:error-code-casing,check:filter-alias-parity, all exit 0.pnpm exec eslint --no-inline-config --format json packages/spec/src/ui/sharing.zod.ts: 1 file, 0 errors, 0 warnings. The population comes fromeslint.config.mjs:971(**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}), so the.md/.mdxpaths are outside it. The config never enables type-aware linting (eslint.config.mjs:326-328), so this diff cannot change the verdict on any file it does not touch. The fullpnpm lintis CI's.check:nul-bytesexit 0, and a self-scan of the 4 files for C0/DEL bytes found none.Generated by Claude Code