Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions docs/04-backlog.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@
"Integration tests cover allow/deny matrix for critical tables",
"Admin console exposes role assignment behind flag"
],
"subtasks": [
"Schema hardening: add foreign keys, composite keys, and indexes for roles/profile_roles/spaces tables",
"Space model: create spaces, space_members, and space_rules with canonical role slugs",
"Content model: ensure posts, post_versions, comments reference spaces and enforce NOT NULL slugs",
"RLS deny-by-default: implement policies for identity, community, content, safety, platform tables",
"Helper SQL: highest_role(profile_id) + legacy slug mapping function with unit tests",
"App guards: reuse requireAdmin across admin routes, emit telemetry + audit logs",
"Admin UI: role manager behind rbac_hardening_v1 with audit trail",
"Telemetry: authz_denied_count dashboard panel + tagged increments",
"Tests: integration matrix role×action×table + admin route unit tests",
"Accessibility: axe scan for role manager surface",
"Docs: security matrix update, RLS denial spike runbook, data model deltas"
],
"definition_of_done": [
"Green CI, tests added",
"Docs updated (auth matrix in /docs/07-security-privacy.md)",
Expand All @@ -63,6 +76,14 @@
"Design tokens defined for color, spacing, typography, elevation",
"Dark/light mode parity maintained"
],
"subtasks": [
"Tokens: extend Tailwind theme for color, spacing, typography, elevation, radius with dark parity",
"Global nav: expose Spaces, Feeds, Events, Funding, Projects, Admin via nav_ia_v1 + RBAC checks",
"Content page application: apply tokens to at least one content layout",
"Accessibility: skip link, focus-visible styles, keyboard trap tests, axe scans",
"Storybook: SpaceHeader, TemplatePickerModal, DonationWidget, EventCard token usage",
"Docs: update /docs/05-ui-ux-delta.md with token tables, IA screenshots, a11y notes"
],
"definition_of_done": [
"Green CI, tests added",
"Docs updated in /docs/05-ui-ux-delta.md",
Expand All @@ -88,6 +109,15 @@
"Role matrix enforced at API and UI for member/contributor/organizer/mod/admin",
"Audit log entries for all moderative actions"
],
"subtasks": [
"Schema/migrations: create or finalize spaces, space_members, space_rules, post_templates with indexes (slug uniqueness, membership status partial) and reversible down scripts",
"RLS: deny-by-default policies for spaces, space_members, space_rules leveraging highest_role(profile_id) and user_space_role_at_least helper",
"APIs: /api/spaces CRUD and /api/spaces/[id]/members join/approve/ban endpoints with audit logging",
"UI: SpaceShell + SpaceHeader + SpaceRolePill flows (create, join, approve) behind spaces_v1 with loading/error states",
"Telemetry: emit space_creation_success_rate and space_join_approval_latency_ms with dashboard panels",
"Tests: integration RLS matrix for new tables and e2e create→join→approve journey with axe scan on SpaceShell",
"Docs: update security matrix, data-model delta, UX screenshots, plus space creation failure runbook"
],
"definition_of_done": [
"Green CI, tests added",
"Docs updated and screenshots recorded",
Expand All @@ -113,6 +143,14 @@
"Draft autosave and post_versions diff viewer implemented",
"Scheduling and canonical URL workflows validated"
],
"subtasks": [
"Schema: add post_versions JSONB history and post_templates scoped per space with indexes on (post_id, version_number)",
"Composer: modular ContentComposer with TemplatePickerModal, diff viewer, scheduling validation behind content_templates_v1",
"RLS: ensure authors manage drafts, contributor+ publish/revert per space rules, moderators revert",
"Telemetry: capture draft_autosave_latency_ms and draft_to_publish_conversion_rate with dashboards",
"Tests: integration coverage for version history/revert plus e2e autosave→diff→schedule→publish with axe checks",
"Docs: update data-model delta, UX flows, and test strategy for autosave/versioning"
],
"definition_of_done": [
"Green CI, tests added",
"Docs updated (product spec & UX states)",
Expand All @@ -138,6 +176,13 @@
"Search service indexes posts, comments, events, profiles",
"Topic pages render curated feeds with filters"
],
"subtasks": [
"Schema: tag_synonyms, topic_pages, and search index materialization with refresh job",
"APIs/UI: tags CRUD with merge flows, topic page templates, unified search typeahead integrated into NewNavbar",
"Telemetry: emit search_latency_ms histogram and search_zero_result_rate counters with alerts",
"Tests: integration for synonym merge + background refresh plus e2e search flows with typo tolerance",
"Docs: taxonomy guide, observability targets, accessibility of filter controls"
],
"definition_of_done": [
"Green CI, tests added",
"Docs updated (taxonomy guide)",
Expand Down Expand Up @@ -313,6 +358,15 @@
"Distributed tracing instrumented for major services",
"Dashboards and alerting policies documented"
],
"subtasks": [
"Metrics: emit content_publish_latency_ms, flag_evaluation_latency_ms, authz_denied_count, crash_free_sessions",
"Tracing: OpenTelemetry spans for publish + admin routes annotated with space_id/post_id/flag_keys",
"Logging: structured JSON with request_id, hashed user_id, feature flag context",
"Dashboards: Executive + Operations panels covering new metrics",
"Alerts: configure thresholds per /docs/08-observability.md routed to on-call",
"Synthetic: Playwright journeys for home/admin/publish with artifact retention",
"Docs: update observability runbook with identifiers and rollout notes"
],
"definition_of_done": [
"Green CI, tests added",
"Docs updated (/docs/08-observability.md)",
Expand Down
29 changes: 28 additions & 1 deletion docs/05-ui-ux-delta.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
## 2. Component Inventory (New & Updated)
| Component | Type | Status | Notes |
| --- | --- | --- | --- |
| `SpaceHeader` | Server component | New | Displays space branding, rules CTA, join/leave actions, feature-flag aware. |
| `SpaceHeader` | Client component | New | Displays space branding, rules CTA, join/leave actions, feature-flag aware. |
| `SpaceShell` | Client component | New | Wraps header, membership panel, and rules editor for `spaces_v1` detail page. |
| `SpaceRolePill` | Client component | New | Shows member role, tooltip with privileges. |
| `MembershipPanel` | Client component | New | Organizer approval dashboard for pending requests with keyboard-accessible actions. |
| `CreateSpaceForm` | Client component | New | Organizer-only creation flow with zod-backed validation and feature flag guard. |
| `ContentComposer` | Client component | Updated | Modular editor supporting Article/Discussion/Q&A/Event/Workshop templates with plugin architecture. |
| `TemplatePickerModal` | Client component | New | Allows selecting space-level templates with previews and accessibility hints. |
| `ModerationQueueTable` | Client component | Updated | Adds filters for queue type, bulk actions, SLA indicators. |
Expand All @@ -27,11 +30,34 @@
- **Elevation:** Create shadow tokens for interactive surfaces (cards, modals) aligned with neo-brutalism outlines.
- **Radius:** Maintain bold outlines but add `radius-sm` (4px) for chip components and `radius-lg` (16px) for cards.

### 3.1 Token Snapshot — 2025-10-31
| Token | Value | Notes |
| --- | --- | --- |
| `brand.ink` | `#1F1F1F` | Primary copy color for Role Manager, nav links, and badges. |
| `brand.panel` | `#FFF8F1` | Background for RBAC Role Manager container; meets 7:1 contrast against ink text. |
| `brand.surface.info` | `#F2F4FF` | Applied to informational badges within nav IA flyouts. |
| `brand.border.muted` | `#D9D3F4` | Outline for neutral stats in Role Manager roster. |
| `brand.border.warning` | `#FFB020` | Moderator badge border; accessible against ink text. |
| `brand.focus` | `#6C63FF` | Used for ring styles on search, skip-link, and nav buttons. |
| `shadow-brand-sm` | `4px 4px 0px rgba(34, 34, 34, 0.12)` | Applied to summary cards and nav chips. |
| `shadow-brand-lg` | `8px 8px 0px rgba(34, 34, 34, 0.18)` | Elevated Role Manager forms. |

Tokens are declared in `tailwind.config.js` and consumed within `src/components/admin/RoleManager.tsx` and `src/components/ui/NewNavbar.tsx` to ensure a single source of truth.

## 4. Accessibility Notes
- All new interactive components must support keyboard navigation, focus-visible styles, and ARIA attributes.
- Provide descriptive labels for toggles (e.g., fee coverage slider) and ensure error messages include guidance.
- For events, include accessibility notes (wheelchair access, ASL availability) and ensure color-coded statuses have text equivalents.
- Implement reduced motion mode for animations in reputation celebrations and feed transitions.
- RBAC Role Manager exposes live search and roster list with `aria-live="polite"` status updates and keyboard-visible focus rings tied to `brand.focus`.
- Space Shell components expose join actions with `aria-disabled`, focus-visible outlines, and announce success/error via inline status banners that meet contrast ratios.

### 4.1 Accessibility Validation Checklist — 2025-11-07
- ✅ `tests/e2e/admin-role-manager.spec.ts`: Axe scan (`@axe-core/playwright`) focused on the role manager section verifies no WCAG 2.1 AA violations when `rbac_hardening_v1` is enabled for staff.
- ✅ `tests/e2e/nav-ia.spec.ts`: Confirms skip-link/focus states on the new navigation hubs (`nav_ia_v1`) and asserts hub visibility per role gate.
- ⚠️ `tests/e2e/space-shell.spec.ts` (planned): Axe scan will cover `SpaceShell` header + membership panel to confirm join buttons announce state changes and tab order matches visual layout once Playwright fixtures land.
- ⚠️ Publish flow axe validation deferred to Phase-2 composer overhaul; current admin table relies on legacy markup and is tracked in MOD-001 follow-up.
- Keyboard walkthroughs recorded in `/docs/operations/runbooks/rls-denial-spike.md` appendix to ensure moderators can assign roles without pointer devices.

## 5. Responsive Behavior
- **Mobile:** Sticky quick actions (Join Space, New Post) at bottom; collapsible filters for search and moderation queues.
Expand All @@ -42,3 +68,4 @@
- Maintain component specs in Storybook (to be configured) with accessibility checklists.
- Update `neobrutalismthemecomp.MD` with new tokens and examples.
- Capture screenshots/GIFs for each new flow when feature flags progress to pilot.
- Telemetry: `recordNavInteraction` logs `nav_interaction_total{target,from,variant,role}` from `NewNavbar`, enabling engagement panels on `dash_ops_rbac_v1`.
17 changes: 14 additions & 3 deletions docs/06-data-model-delta.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
| Table | Purpose | Key Columns | Notes |
| --- | --- | --- | --- |
| `spaces` | Defines communities with branding and governance metadata | `id`, `slug`, `name`, `description`, `visibility`, `rules`, `created_by`, `feature_flags`, `created_at`, `updated_at` | `slug` unique; `feature_flags` JSONB for space-level toggles |
| `space_members` | Maps users to spaces with roles and status | `space_id`, `profile_id`, `role`, `status`, `invited_by`, `joined_at`, `last_active_at` | Composite PK (`space_id`, `profile_id`); status enum (pending, active, banned) |
| `space_rules` | Structured rules/flairs/templates | `id`, `space_id`, `type`, `value`, `position` | `type` enum (rule, flair, template, automod) |
| `post_templates` | Stores reusable template metadata | `id`, `space_id`, `content_type`, `title`, `body`, `config` | `config` JSONB for form fields, required sections |
| `space_members` | Maps users to spaces with roles and status | `space_id`, `profile_id`, `role_id`, `role_slug`, `status`, `requested_at`, `decision_at`, `joined_at`, `last_active_at` | Composite PK (`space_id`, `profile_id`); `status` enum (`pending`, `active`, `banned`); `role_slug` maintained via trigger |
| `space_rules` | Structured rules/flairs/templates | `id`, `space_id`, `title`, `body`, `kind`, `value`, `position` | `kind` enum (`rule`, `flair`, `template`, `automod`); JSONB `value` stores config |
| `post_templates` | Stores reusable template metadata | `id`, `space_id`, `content_type`, `title`, `body`, `config` | `content_type` enum (`article`, `discussion`, `qa`, `event`, `workshop`); `config` JSONB for form fields |
| `post_versions` | Version history for posts | `id`, `post_id`, `version_number`, `content`, `metadata`, `created_by`, `created_at` | Add `content` as JSONB to support editor structure |
| `questions` | Extends posts for Q&A | `post_id`, `accepted_answer_id`, `bounty_amount`, `bounty_currency`, `bounty_expires_at` | `post_id` FK to `posts`; `accepted_answer_id` references `answers` table |
| `answers` | Stores answers for Q&A posts | `id`, `question_id`, `body`, `author_id`, `is_accepted`, `created_at`, `updated_at` | Add index on (`question_id`, `is_accepted`) |
Expand All @@ -20,6 +20,17 @@
| `automod_rules` | Per-space automation | `id`, `space_id`, `rule_type`, `config`, `enabled`, `created_at` | `rule_type` enum (rate_limit, first_post, banned_domain, trust_score) |
| `sanctions` | Records enforcement | `id`, `space_id`, `profile_id`, `type`, `reason`, `status`, `expires_at`, `created_by` | `type` enum (removal, quarantine, shadow_ban, space_ban, site_ban) |
| `audit_logs` | Immutable log for staff actions | `id`, `actor_id`, `actor_role`, `entity_type`, `entity_id`, `action`, `metadata`, `created_at` | Store hashed chain for immutability |

> 2025-10-24: Created baseline `audit_logs` table with service-role write policy and admin read access to support SEC-001 guard telemetry.
> 2025-10-31: Hardened SEC-001 scope with community scaffolding. Added `spaces` (slug, name, visibility, created_by, timestamps), `space_members` (space_id, profile_id, role_id, status, joined_at, last_seen_at), `space_rules` (space_id, title, body, created_by, timestamps), `post_versions` (post_id, version_number, content JSONB, metadata JSONB, created_by, created_at), and `reports` (reporter_profile_id, subject_type/id, reason, status, space_id, timestamps). Added helper functions `normalize_role_slug`, `highest_role_slug`, `user_space_role_at_least` to back policies.
> 2025-11-07: MOD-001 expansion introduced `feature_flags` JSONB + optional banner imagery on `spaces`, normalized `space_membership_status` to `pending|active|banned`, added `role_slug`/`requested_at`/`decision_at` columns with sync trigger on `space_members`, extended `space_rules` with `kind` enum + JSONB `value`, created `content_template_type` enum + `post_templates` table, and added `space_members_pending_idx` / `audit_logs_space_*` indexes. Policy `Members request access` now allows self-service join requests gated to `status='pending'`.

### Index & Policy Update — 2025-10-31

- Indexes: `space_members(role_id, status)`, `space_members(space_id, role_id)`, `spaces(visibility)`, `posts(space_id, status)`, `posts(space_id, published_at DESC)`, `comments(thread_root_id, created_at DESC)`, `reports(space_id, status)`, `reports(subject_type, subject_id)`.
- 2025-10-31 Follow-up (`0021_sec_001_constraints_indexes.sql`): Added unique index `profile_roles_profile_role_idx`, composite moderation index `space_members_role_status_v2_idx`, refined post timeline index `posts_space_status_published_idx`, and `comments_thread_status_created_idx` to stabilize queue queries. Enforced canonical slug constraint `roles_slug_canonical_ck` to guarantee `normalize_role_slug` invariants.
- Constraints: canonical slug check on `roles.slug`; composite PK enforced on `space_members`.
- RLS: deny-by-default policies now depend on helper functions to gate CRUD by canonical role ladder across `spaces`, `space_members`, `space_rules`, `posts`, `post_versions`, `comments`, `reports`, `feature_flags`, `audit_logs`, `profile_roles`.
| `donations` | Monetary contributions | `id`, `profile_id`, `target_type`, `target_id`, `amount`, `currency`, `fee_amount`, `donor_covers_fees`, `is_recurring`, `status`, `receipt_url`, `created_at` | Index on (`target_type`, `target_id`) |
| `pledges` | Recurring commitments | `id`, `profile_id`, `target_type`, `target_id`, `interval`, `amount`, `currency`, `status`, `next_charge_at`, `cancelled_at` | |
| `payment_methods` | Tokenized payment references | `id`, `profile_id`, `provider`, `external_id`, `status`, `last4`, `expires_at` | PII encrypted at rest |
Expand Down
8 changes: 8 additions & 0 deletions docs/07-security-privacy.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@

Full matrix with endpoint mapping maintained alongside Supabase policy definitions. Automated tests validate allow/deny paths per `/tests/security`.

- Integration coverage refreshed on 2025-11-07: `tests/security/rbac-policies.test.ts` exercises the role/action/table matrix (spaces, space_members, space_rules, posts, post_versions, comments, reports, audit_logs, feature_flags) using Supabase service credentials plus per-role JWT fixtures. Route-level guards for admin user management are unit tested (`tests/unit/require-admin.test.ts`, `tests/unit/feature-flags-admin-route.test.ts`) and new permissions helpers are validated via `tests/unit/rbac-permissions.test.ts`.

**Admin Guard Hardening:** Unified admin API routes now delegate to `requireAdmin` in `src/lib/auth/require-admin.ts`, which resolves canonical roles, audits denials via `audit_logs`, and emits `authz_denied_count{resource,role,space,reason}`. Guard usage now extends to user management and gamification APIs, ensuring telemetry tags include `resource`, `role`, `space`, `reason` for Operations dashboards. RLS helper functions (`normalize_role_slug`, `user_space_role_at_least`, `highest_role_slug`) back deny-by-default policies across `spaces`, `space_members`, `space_rules`, `posts`, `post_versions`, `comments`, `reports`, `feature_flags`, and `audit_logs`. The role manager UI behind `rbac_hardening_v1` surfaces canonical badges, enforces audit logging on each mutation, and is covered by synthetic navigation tests plus axe scans.

**Space Guard Enhancements (2025-11-07):** Introduced `requireRole` and `requireSpaceRole` helpers under `src/lib/auth/` to unify canonical-role enforcement across Phase-2 APIs. `requireRole` gates global actions (e.g., space creation) while `requireSpaceRole` validates per-space membership, emits `authz_denied_count{resource,role,space,reason}`, and logs denials with structured metadata. Supabase policies now include `Members request access` to allow self-service join requests gated to `status='pending'`; organizers/moderators approve via audited endpoints that record `space_join_approval_latency_ms` telemetry. API routes under `/api/spaces` use these guards and server spans to preserve RLS invariants before mutating Supabase tables.

**Runbook – RLS Denial Spike (2025-10-31):** If `authz_denied_count` surges, check Operations dashboard panel `op_rbac_denials` for `resource` + `space` tags. Use `/admin/audit` to confirm actor role assignments and `feature_flag_audit` for recent flag toggles. Validate helper functions are returning canonical slugs via Supabase SQL (`select public.highest_role_slug('<profile-id>'::uuid)`). Rollback: toggle `rbac_hardening_v1` off, apply migration `0020_sec_001_rls_policies.down.sql`, restore from PITR if required. Document investigation outcomes in `/docs/operations/runbooks/rls-denial-spike.md`.

## 3. Input Validation & Sanitization
- Use Zod schemas for all API inputs, with centralized validation utilities.
- Sanitize rich text/HTML via vetted library (e.g., DOMPurify) server-side before storage.
Expand Down
Loading
Loading