# Security Follow-ups for Plan 1 Items flagged by the security review plugin that were deferred at the user's request ("ease up on the security plugin") and are to be addressed in a consolidated pass before Plan 1 is declared complete. ## Migration 005 (cross-cutting / polymorphic tables) The polymorphic shape (`entity_type` text + `entity_id` uuid, no composite FK to a parent) was an approved design decision in `docs/superpowers/specs/2026-05-31-void-v2-design.md`. That decision trades referential integrity at the DB layer for one shared join table across entity types. The plugin's findings are accurate but require revisiting the design choice — not a one-line fix. - **[HIGH] entity_tags / entity_links / attachments lack `space_id`.** Cross-tenant linkage is possible at the DB layer. Mitigation options: 1. Add `space_id` NOT NULL to each polymorphic row; require callers to filter. 2. Per-type junction tables (e.g. `page_tags`, `task_links`) with real FKs. - **[MEDIUM] `tags.name UNIQUE` is global, not per-space.** Cross-tenant collision creates a side-channel for tag-name discovery. Fix: `UNIQUE(space_id, name)`. - **[MEDIUM] No cascade on parent delete for `attachments` / `entity_tags`.** Polymorphic FKs cannot be expressed in standard SQL. Fix options as above, or a deletion trigger per parent type. ## Decision pending Before closing Plan 1, decide whether to: - (a) **Tighten now**: add `space_id` columns + per-type composite FKs to `entity_tags`, `entity_links`, `attachments`, and a per-space UNIQUE on `tags`. Cost: ~1-2 hrs and invalidates the polymorphic claim in the spec. - (b) **Document and defer**: accept the tradeoff for Plan 1, gate access at the REST/MCP layer (where `space_id` IS available from the actor's session), and revisit when multi-tenant becomes load-bearing. Owner-only authn (Plan 1) means there's only one tenant in practice today, so (b) is defensible for the alpha. (a) is the right long-term answer.