Security and capabilities
Fenómenus follows the standard WordPress model: capability checks on every action, nonces on every state-changing request, sanitized input and escaped output.
Capabilities
| Area | Required capability |
|---|---|
| Menu items: create, edit, order, duplicate, status, prices | edit_posts |
| Deleting a menu item | delete_posts |
| Categories: create, rename, reorder, delete | manage_categories |
| Assigning a category during bulk import | The taxonomy's assign_terms |
| Settings screens | edit_posts |
| Setup assistant | edit_posts |
| QR generator, PDF generator, AI tools | edit_posts |
| Editing another user's profile flag | edit_user for that user |
Fenómenus never grants a capability the account does not already have, with one deliberate exception described below.
The Basic profile
A per-user flag, stored per site on multisite, that reduces the administration to menu work. When set, these areas are removed and blocked by direct URL:
Posts, Pages, the standard new-post screen, Media, Comments, Appearance, Plugins, Users, Tools, Settings, and the language settings screen.
Media handling continues to work from inside an item, because upload endpoints are deliberately not blocked.
The exception mentioned above: an account with the Basic profile that already holds a post or page editing capability is granted the capabilities needed to manage content translations and their slugs, so a restricted editor can still maintain translated menus.
Nonces
Every state-changing request is nonce-protected, including item and category operations, order saving, status changes, inline meta updates, duplication, deletion, exports, bulk imports, allergen saving, settings saving, setup assistant steps, QR data requests, PDF content and settings requests, and the AI tools.
Input and output
- Titles and text values are sanitized on save.
- Textareas allowing HTML are sanitized against the permitted set; the rest are stored as plain text.
- URLs are sanitized as URLs, including logo, image, video and custom-URL values.
- Uploaded images for wine-list analysis are validated against an explicit MIME allow-list: JPEG, PNG, GIF and WebP.
- Output is escaped at the point of rendering.
The AI request boundary
Requests to the AI service are signed with the site's license and domain, through a single request boundary rather than per-feature request construction. Missing license, missing domain and invalid configuration each produce an explicit error instead of an unsigned or partial request.
No license key is rendered into a page, and no AI tool writes content without the operator saving it.
Guest-facing data
Fenómenus collects nothing from guests. The allergen filter selection, the icon visibility preference and the favorites collection are stored in the guest's own browser, are not transmitted to the site as identity, and are not readable by the restaurant.
The favorites view is rendered from data the browser sends with the request; there is no server-side record.
Multisite scoping
Menus, settings, allergen libraries, tool enablement and the Basic profile flag are per site. A user restricted on one restaurant is not restricted on another unless the flag is set there too.
Guidance for integrations
- Check the same capability the product checks for the equivalent action.
- Verify a nonce on any state-changing request you add.
- Sanitize on input, escape on output; do not rely on stored values being safe.
- Never expose the market-reference wine prices publicly.
- Never build an endpoint that returns menu data with guest identity attached — the product deliberately has none.
- Treat allergen data as safety-relevant: never derive it, never default it, never publish it unreviewed.