Commit cb352a0
fix(spec): cross-validate permission object grants against declared objects (#1997)
* feat(crm): working Web-to-Lead public form example
The app-crm example showed Web-to-Lead only via `customer.portal` `anonymousEntry`
— a spec property with NO runtime consumer, so it never worked (404). Add the
mechanism that actually does, and make the example coherent:
- lead.view.ts: `web_to_lead` form view with `sharing.allowAnonymous` →
live `GET/POST /api/v1/forms/contact-us` (+ /submit).
- sales-roles.ts: `GuestPortalProfile` (isProfile, INSERT-only on crm_lead, keyed
by FULL object name — the anonymous permission path requires it).
- lead.object.ts: `status` gets `defaultValue: 'new'` so a minimal public create
satisfies `required` (the option-level `default` is only a UI preselect).
- customer.portal.ts: drop the dead `anonymousEntry` routes; point to the working
form view instead (re-add when the runtime mounts anonymousEntry).
- security/index.ts + objectstack.config.ts: export + register the guest profile.
Doubles as a CI regression test for the public-form path (builds against the
workspace) — the #1989 flattened-metadata resolution bug would have been caught here.
Verified end-to-end (app-crm, no auth): GET /forms/contact-us → 200 form spec;
POST /forms/contact-us/submit → creates a crm_lead (status=new); GET /data/crm_lead
→ 401 (guests can't read).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(spec): cross-validate permission/profile object grants against declared objects
`validateCrossReferences` checked hook/view/seed/app-nav/action references against
the declared object set — but NOT permission-set/profile `objects` grants, even
though `validateNamespacePrefix`'s doc already assumed it did. So a profile that
grants on a non-existent object (e.g. a short `lead` instead of the namespaced
`crm_lead`) passed build/validate/test silently. The grant then applies to
nothing: the authenticated path may namespace-resolve the short name, but the
anonymous / explicit-permission-set path does not — so e.g. a public Web-to-Lead
INSERT is denied for "roles []", with no diagnostic anywhere.
Add the missing check: every `permissions[].objects` key must reference a declared
object, or strict validation fails loudly at build time.
- stack.zod.ts: validate permission/profile object grants → object references
- stack.test.ts: +2 cases (short/undefined name fails; full name passes)
82/82 spec stack tests pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent 955e9fa commit cb352a0
2 files changed
Lines changed: 60 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
485 | 485 | | |
486 | 486 | | |
487 | 487 | | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
488 | 525 | | |
489 | 526 | | |
490 | 527 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
583 | 583 | | |
584 | 584 | | |
585 | 585 | | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
586 | 609 | | |
587 | 610 | | |
588 | 611 | | |
| |||
0 commit comments