Pular para o conteúdo

Pilot Readiness

Purpose: Systematic health check of every tier, with pass/fail criteria, current status, and next actions. This is the single document where anyone can see what’s solid, what’s broken, and what to work on next.

How to use: Work top-down. Fix all RED items in a tier before moving to the next tier. Within a tier, fix RED before YELLOW. Check off items as they’re verified.

Last assessed: 2026-03-24 Assessed by: Claude (code audit + production SQL verification via Management API)


Each item has a health indicator:

  • PASS — Verified working correctly
  • WARN — Works but has known limitations or risks
  • FAIL — Broken, missing, or unverified — must fix before pilot
  • N/A — Not applicable or intentionally deferred

Each tier has an overall gate:

  • GATE: OPEN — Tier is healthy, safe to invest in lower tiers
  • GATE: BLOCKED — Has FAIL items that must be resolved first

Does the core compliance engine work?

GATE: OPEN (no FAIL items — 1 WARN remains: item 2.5 deferred to production)

#CheckStatusNotes
1.1Upload stores file scoped to correct companyPASSPath: users/{userId}/companies/{company_id}/documents/{year}/{docId}/{file}
1.2Document type is identified during uploadPASSTwo-step: type selection + optional OCR auto-detection
1.3Category is derived from document type (not manual)PASSRead-only, fetched from document_types table
1.4File is retrievable and viewablePASSDocumentViewer.tsx handles PDF + image rendering
1.5Upload enforces file type/size restrictionsPASSValidated in upload modal
1.6Storage bucket policies block direct accessPASSMigration 20250805012821 enforces get_user_company_id() + auth.uid() on INSERT/SELECT/UPDATE/DELETE
#CheckStatusNotes
2.1Issue date and expiry date captured (OCR or manual)PASSBoth fields in upload and edit forms; OCR auto-fills when detected
2.2Status derived automatically from datesPASSdaysUntilExpiry ≤ 0 → expired; ≤ 90 → expiring; else valid
2.3Users cannot manually override statusPASSNo status field in any edit form
2.4Indefinite-validity types handled correctlyPASSexpiry_date set to null; no false alerts
2.5Status recalculated on date editWARNStatus updates on next daily job run, not immediately on edit. Same-day gap exists
2.6RLS policies properly restrict document accessPASSVerified 2026-03-23 via SQL audit: no permissive policies. All tables use get_user_company_id(). All 39 public tables have RLS enabled
#CheckStatusNotes
3.1Alerts created at correct thresholdsPASS90, 60, 30, 15, 7 days before expiry
3.2Alert Center shows pending alerts with company_id filterPASSuseAlertCenter.ts filters by company_id + status
3.3Dashboard shows real compliance signalPASSExpired/expiring/valid counts, compliance score, blocking issues
3.4Expiring documents surfaced on dashboardPASSTop 5 expiring docs via useExpiringDocuments with company_id filter
3.5Email alerts actually reach usersPASSVerified 2026-03-24: test document (7-day expiry) triggered alert + email via SMTP2Go. emailsSent: 1 confirmed in job response. Test data cleaned up
3.6Daily alert job runs and recalculates statusPASSBUG-044 fixed 2026-03-23. CRON_SECRET set + pg_cron job updated with x-cron-secret header. Manual trigger returned success: true (3 docs processed, 1 status update)
3.7Email templates support user languagePASSFixed 2026-03-24: All 4 templates (expiry, welcome, invite, notification) now bilingual (pt/en). Daily job reads user.language and passes to template. Edge Functions redeployed
PriorityItemBugAction Required
1Verify RLS policies in productionBUG-006DONE 2026-03-23 — SQL audit confirmed no permissive policies. All 39 tables have RLS enabled
2Fix cron job auth mismatchBUG-044DONE 2026-03-23CRON_SECRET set + pg_cron job updated. Manual trigger confirmed success: true
3Verify full email deliveryDONE 2026-03-24 — Test document (7-day expiry) triggered alert + email. emailsSent: 1 confirmed

Can a real team use this daily?

GATE: OPEN (BUG-010 fixed 2026-03-24)

#CheckStatusNotes
A.1Edit document metadata (dates, number, authority)PASSDocumentEditModal.tsx supports all key fields
A.2Delete documents (soft delete to recycle bin)PASSuseRecycleBin.ts with deleted_at timestamp
A.3Restore deleted documentsPASSSingle and bulk restore with race condition guards
A.4Permanently delete from recycle binPASSIncludes storage file cleanup
A.5Document versioning/supersessionPASSMultiSupersessionDialog + is_current flag
A.6Audit trail for changesPASSuseActivityLog + useDeletionAuditLog
A.7Supersession enforces company_idPASSBUG-026 fixed 2026-03-15
A.8Duplicate detection enforces company_idPASSBUG-027 fixed 2026-03-15

Cluster A health: PASS

#CheckStatusNotes
B.1Welcome email sent on registrationPASSFire-and-forget in Auth.tsx; failure logged, not blocking
B.2Invitation email sent with signup linkPASS7-day token expiry; invite created via RPC
B.3Alert thresholds configurable per userPASSuseAlertSettings.ts stores per-type custom thresholds
B.4In-app activity feedPASSuseRecentActivity on dashboard + Reports activity tab
B.5Email failure doesn’t break user flowPASSCaught with warning toast; non-blocking
B.6SMS notificationsN/ASchema supports it; not implemented. Deferred to post-pilot
B.7Email templates bilingualPASSFixed 2026-03-24: All templates bilingual (pt/en). Uses user.language from database
B.8Notification delivery audit trailWARNNo alert_delivery_log table. Can’t confirm which emails were sent

Cluster B health: PASS (with known language limitation)

#CheckStatusNotes
C.1Global search across documents/packs/personsPASSAccent-insensitive, debounced, grouped results
C.2Category filtering on documents pagePASSMulti-select with status filters
C.3Dashboard shows real compliance signal (not vanity)PASSScore = valid/total; 0 when empty (conservative)
C.4Reports with category breakdownPASSStatus, Activity, Deletions tabs
C.5Search input properly sanitizedPASSBUG-040 was false alarm; prepareSearchQuery() escapes input

Cluster C health: PASS

#CheckStatusNotes
D.1Authentication (email/password)PASSSupabase Auth with session management
D.2Password reset flowPASSEmail link flow implemented
D.3Multi-tenancy (company_id isolation in queries)PASSAll major queries include .eq('company_id', companyId)
D.4User invitation and onboardingPASSRPC-based invite with token, email, and accept flow
D.5Roles enforced server-side (RLS)PASSBUG-010 fixed 2026-03-24: has_write_access() blocks viewers from writing across 8 tables (22 policies). is_user_manager_or_admin() on applicability tables. Storage file operations also role-gated
D.6Supabase credentials securedPASSBUG-005 fixed 2026-03-24: old token revoked + rotated. .env gitignored. Anon key is public by design
D.7RLS policies verified in productionPASSVerified 2026-03-23: no permissive policies. All 39 tables have RLS enabled
D.8Admin role assigned server-sideWARNCurrently assigned client-side in Auth.tsx. Could be spoofed
D.9Forced logout on user removalWARNUser removal sets company_id = null but doesn’t revoke session

Cluster D health: PASS — All security blockers resolved

PriorityItemBugAction Required
1Rotate Supabase credentialsBUG-005Rotate management token + anon key in Supabase dashboard. Remove .env from git tracking. Scrub history if repo may become public
2Verify RLS policies in productionBUG-006DONE 2026-03-23 — resolved by Tier 1 verification
2Implement server-side role enforcementBUG-010Create check_user_role() SQL function; add to RLS policies for INSERT/UPDATE/DELETE

What makes the product compelling?

GATE: OPEN (no blockers, but assess after Tiers 1-2 are clean)

#FeatureStatusNotes
3.1Smart Packs (nested hierarchy)PASSFully implemented with status rollup
3.2Smart Pack PDF exportPASSCover pages, document indices, ZIP bundling (BUG-020 fixed)
3.3Compliance Resolution FlowPASSGuided modal for resolving pack blockers
3.4OCR auto-extractionWARN7 of 14 document types MVP-ready. Coverage expanding
3.5Duplicate detectionPASSSHA-256 + OCR metadata matching
3.6Custom document typesPASSCompany-created types with validity + pack integration
3.7Knowledge BasePASSContextual tooltips + full articles per document type
3.8Inline form validation (WCAG 3.3.1)PASSBUG-037 fixed 2026-03-23

What makes the product excellent?

GATE: OPEN (address after Tiers 1-3 are stable)

#FeatureStatusNotes
4.1Favorites / recently accessedWARNuseFavorites tracks access; no true bookmarking UI
4.2Document timeline visualizationPASSDocumentTimelineBar component
4.3Advanced reporting / exportWARNBasic reports exist; no CSV/Excel export
4.4Mobile-optimized workflowsWARNCapacitor build-ready; mobile UX not tested on device
4.5Offline supportWARNuseOfflineSupport hook exists; depth of support unclear
4.6Accessibility (WCAG 2.1 AA)WARNActive work. Multiple bugs open: BUG-029 through BUG-038
4.7i18n coverage (all strings translated)WARNBUG-039: 555 inline ternaries; BUG-015: duplicated language check

TierGatePASSWARNFAILBlockers
1 — PillarsOPEN1810Email delivery verified; templates bilingual; BUG-045 deferred
2 — OperationalOPEN2630
3 — MultipliersOPEN710
4 — PolishOPEN160

Overall: PILOT-READY — All gates OPEN. 0 FAIL items. 11 WARN items remain (non-blocking).


These are the minimum actions to unblock the gate, in priority order:

#ActionResolvesTypeOwnerDone?
1Run RLS audit SQL in Supabase production dashboardBUG-006Verify[x] Done 2026-03-23
2Fix cron job auth mismatchBUG-044Fix[x] Done 2026-03-23
3Rotate Supabase management tokenBUG-005Fix[x] Done 2026-03-24
4Remove .env from git trackingBUG-005Fix[x] Already gitignored
5Create has_write_access() SQL function + add to RLS policiesBUG-010Build[x] Done 2026-03-24
6Verify full email deliveryItem 3.5Verify[x] Done 2026-03-24 — test doc triggered alert + email
7Translate email templates to EnglishItem 3.7 / B.7Build[x] Done 2026-03-24 — all 4 templates bilingual
1Move admin role assignment to server-side (Edge Function or trigger)Item D.8Build[ ]

All gates are OPEN. All critical path items resolved. 1 WARN-level improvement remains (D.8).


  1. Work through the checklist top-down
  2. For each item, verify in code or production (not from memory)
  3. Update the Status column and the “Last assessed” date at the top
  4. If a new issue is found, add it to docs/BUGS.md first, then reference it here
  5. When all FAIL items in a tier are resolved, change the GATE to OPEN

This document is the handoff artifact. Anyone picking up the work reads this first.