Embedded FAQ assistant and enquiry

This increment adds an optional public FAQ assistant to an existing form. It is disabled by default both in the definition and by the server's EMBEDDED_FORM_ASSISTANT_ENABLED switch. It does not expose QA Commander, personas, private knowledge, CRM reads or agent tools. Source qualification does not enable production.

Publish and embed

An authenticated form editor with current org:manage_forms and access to the form's project uses Build → Published website assistant. The JSON editor validates the explicit public FAQ, exact site origins, language/style, organization inference policy, input/context/output ceilings and finite form/visitor allowances. Apply stages the definition; Save fields publishes it through the existing form management route. Every configuration value is public. Never publish private material or secrets. FAQ answers should already use the selected language/style: inference selects a source; the server returns that source's exact published answer.

Example host markup, once an operator has intentionally enabled this feature:

<script src="https://your-goodqa-origin/v1/public/form-assistant/embed.js"
        data-form-token="YOUR_PUBLIC_FORM_LOCATOR"></script>

Use data-invited="true" for a normal invite locator. Passwords are entered inside the iframe. The origin allowlist sets the iframe's frame-ancestors; it constrains browser embedding and is not HTTP caller authentication. No wildcard origins or postMessage trust are used. The script, iframe and fetch endpoints use the same GoodQA origin. /embed/forms/[token]?parentOrigin=... redirects to the maintained API iframe.

Authority and metering

Publishing records the actual authenticated human and digest of the definition/title/description in existing audit events. A client cannot submit a sponsor identity. API keys and delegated user tokens cannot publish an enabled assistant. Every access, new answer and replay resolves the current normal public form access checks, current enabled definition, sponsor grant and live org/project permissions, AI entitlements and organization credential setup. A five-minute signed capability binds the form, definition, locator, embed origin, visitor nonce and sponsor publication. It carries no organization credentials. Access is checked again after inference before publishing an answer.

Before inference, a transaction locks the form and writes a content-free durable request claim. The identity binds the capability's scope and request ID; a canonical content digest fences changed-payload reuse. Concurrent duplicate claims and fresh application restarts cannot resend a claimed request. Replays report unknown, including after a successful original response: answers are not retained server-side. A lost response must not be interpreted as a successful answer. Revocation is checked before replay.

Form and visitor allowances count all lifetime inference claims, including unknown outcomes, across definition changes. A confirmed organization admission refusal with no provider dispatch appends form.assistant.admission_refused referencing that attempt’s immutable claim, retaining content-free audit evidence while releasing form, visitor and token capacity. An ambiguous error or crash retains the claim and cannot trigger a resend. Token allowance claims conservatively include UTF-8 input bytes, output ceiling, framing and the existing client's bounded repair envelope. Publication uses the same envelope calculation and requires enough tokens for one maximum bounded request, including worst-case JSON escaping and all context slots. Organization quota reserves through meteredCompleteJson; spend admission uses withApiAiSpend; credentials resolve through resolveOrgLlmClient with existing platform/BYOK rules. Provider usage settles the organization reservation, while an unknown dispatch consumes its conservative ceiling. No new wallet, credential store, conversation table or migration is introduced. A visitor can reset a session, so visitor limits constrain a session; the durable form/org ceilings constrain total anonymous usage.

Only the explicit FAQ and visitor's bounded recent questions enter the inference request. The model returns a typed FAQ ID or null. Unknown IDs, extra fields and malformed/empty output produce an insufficient-knowledge state. Answers and source labels are rendered as text. No model text can submit the form, manufacture consent or execute tools/links. Audit rows contain identities, digests, state and ceilings, without raw questions or answers.

Explicit enquiry and receipt

Make an enquiry loads the actual published form through its normal access endpoint. Visitors enter their details and select explicit consent before submitting. The iframe uses submitPublicFormResponse, the normal definition-bound ticket, validation, automation checks, nonce/payload replay and configured destination outbox. There is no model-to-CRM write path. A refused validation remains editable. An ambiguous transport retry retains its original submission.

The receipt shows the canonical response ID and the CRM outbox state/reference (pending, retrying, delivered, failed, skipped, or unconfigured). Browser session storage retains the original submission only within the normal ticket lifetime; reload replays that submission to read its same receipt and current destination state. It is local to the iframe session, contains entered contact details, and expires after 25 minutes. It is not a server conversation store. Receipt replay does not claim new delivery. Forms requiring conditional rules, uploads or additional unsupported controls direct visitors to the existing full form. The native non-AI form remains usable when AI is disabled or unavailable.

Qualification and follow-ons

Owning HTTP/DB tests mount the real application and public plugin, normal forms/CRM services and organization metering. A recording at LlmClient.completeJson asserts request context in memory and persists only a request digest, byte count, output ceiling, message count and typed usage; it proves integration behavior, not live model quality. The browser test drives the maintained iframe from a second origin, explicit consent, canonical submit and receipt reload. With ASSISTANT_PRODUCTION_BROWSER=1, it additionally drives publication in the production Next editor and reads the resulting contact in the existing CRM UI. The disposable PostgreSQL fixture and synthetic identities are required. No real provider calls, customer data, outreach, deployment or activation are part of these tests.

Verified scheduling/booking, availability promises, sales qualification, intentional follow-up under actual grants/consent, and workflow/QAC/MCP assistant consumption remain future work. Existing form submission events and CRM projections remain their canonical seams. This increment does not register general MCP tools, authorize outreach or create bookings. Full GQA14 remains open after this source slice.

Implementation references: Fastify route request limits and PostgreSQL row locks.

We use essential cookies to keep you signed in. See our Privacy Policy for details.