Designing Client-Editable Forms: Roles, Approval, and Safe Publishing
Designing Client-Editable Forms: Roles, Approval, and Safe Publishing
A client editor is changing production configuration. A form definition can alter required data, uploads, PII collection, notification recipients, webhook destinations, retention, and legal copy. That deserves more than a Save button.
The safe model borrows from software delivery: immutable revisions, review, approval of an exact artifact, atomic publishing, rollback, and an audit trail.
Use an explicit lifecycle
A useful state machine is:
draft → in_review → approved → scheduled/published → superseded/archived
A published revision is immutable. Editing creates a new draft. Approval applies to a specific revision checksum; any mutation invalidates approval. Scheduled publication atomically changes the active version. Rollback activates a previous valid revision without rewriting history.
Every submission stores the form_version_id it used. Old responses remain readable after fields or option labels change.
Separate capabilities
| Capability | Viewer | Analyst | Editor | Publisher | Admin |
|---|---|---|---|---|---|
| View aggregate analytics | Yes | Yes | Yes | Yes | Yes |
| View individual submissions | Policy | Policy | Policy | Policy | Yes |
| Export submissions | No | Optional | No | Optional | Yes |
| Edit draft copy/fields | No | No | Yes | Yes | Yes |
| Change integrations/secrets | No | No | No | Policy | Yes |
| Submit for review | No | No | Yes | Yes | Yes |
| Approve/publish/rollback | No | No | No | Yes | Yes |
| Change roles/retention/security limits | No | No | No | No | Yes |
This is an example, not a universal RBAC prescription. A small owner-operated application may combine roles; higher-risk organizations may require a separate approver.
Enforce every capability with Laravel policies at the service/action layer. Hidden Filament actions are not authorization. Review Laravel policies.
Put guardrails around configuration
Allowlist field types and validation rules. Bound field/step counts, upload sizes/types, and conditional-logic complexity. Disallow arbitrary PHP, JavaScript, and Blade. Make webhook destinations SSRF-safe and mask/encrypt secrets.
Warn or block risky changes: health data, password/card fields, public file visibility, external destinations, retention changes, or removing required privacy copy. Guardrails should explain the safer alternative instead of silently discarding configuration.
Preview the exact revision without side effects
A preview should render the precise draft revision with synthetic data and a visible non-production banner. It must not send production emails/webhooks, charge payments, write real analytics, or create ordinary submissions.
Test mobile layout, validation, accessibility, conditional paths, file behavior, email preview, and the success/redirect state. Preview authorization should not make the draft publicly enumerable.
Show a human publish diff
Before approval, summarize:
- fields added, removed, renamed, or reordered;
- required/optional and validation changes;
- option and conditional-path changes;
- new PII or upload categories;
- recipients and external destinations;
- retention, consent/privacy copy, publishing dates, and redirects.
Require a reason or ticket for high-risk changes. The approver signs the revision/checksum shown; editing afterward creates a new review cycle.
Publish and rollback atomically
Use a transaction and concurrency control so two publishers cannot create two active versions. A scheduled task should use withoutOverlapping() and, in multi-node deployments, onOneServer() with a shared lock-capable cache.
Rollback is one audited activation of an earlier immutable version. It does not delete the bad revision or rewrite submissions collected under it. Define what happens to in-progress drafts when active versions change.
Protect the audit trail
Append events with actor, tenant, action, version IDs/checksums, timestamp, reason, and a safe structured diff. Do not include submission answers, secrets, access tokens, or entire confidential configurations.
Version history is not a backup, and an ordinary database audit table is not automatically tamper-proof. Restrict mutation, separate privileged access, monitor exports, and define retention for the audit data itself.
Tests that enforce governance
- an editor cannot publish, export, change secrets, or view restricted submissions;
- cross-tenant IDs fail at the service layer;
- approval of revision A cannot publish modified revision B;
- simultaneous publishers produce one active revision;
- preview emits no production side effect;
- scheduled publish executes once and atomically;
- rollback preserves history and is audited;
- submissions remain linked to their revision;
- audit diffs mask secrets and PII;
- deleting a field does not destroy historical answers.
The quiet cost of rebuilding forms is not only code—it is rebuilding these operational controls. The versioning guide supplies the data model, while the new retention guide explains why publication control and data lifecycle must meet.
Client editing becomes safe when authors have freedom inside reviewed bounds and publication is a deliberate state transition—not a mutable row changing underneath active respondents.