Skip to content

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

Description

@objectstack-fleet

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').

URL an author or visitor would try answer
GET /forms/contact-us (the path as authored) 404 {"success":false,"error":{"code":"ENDPOINT_NOT_FOUND","message":"Not found"}}
GET /_console/forms/contact-us 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/main 8caa131e52)

  • 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


Generated by Claude Code

Activity

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

Metadata

Metadata

Assignees

Labels

area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsbugSomething isn't workingdomain:specpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions