Skip to main content

Documentation Index

Fetch the complete documentation index at: https://grantmaster.dev/llms.txt

Use this file to discover all available pages before exploring further.

Launch Gate Architecture

This document describes the first-launch gating system that narrows GrantMaster to a trustworthy production surface.

Goals

The launch gate exists to enforce a smaller but credible release by making the following agree with each other:
  • route registration
  • direct-route access
  • sidebar and header navigation
  • command palette and shortcuts
  • widget availability
  • helper-shell affordances
  • selected build-time route inclusion
The core design goal is simple: if a feature is not ready for launch, it should not remain partially visible.

Source Of Truth

Primary source:
  • src/config/launchScope.ts
This file currently owns:
  • launch-scoped tab and sub-view allowlists
  • hidden settings items
  • disabled route prefixes
  • redirect mappings for blocked paths
  • disabled route-path definitions
  • disabled widget IDs
  • disabled helper-shell controls
  • build-time feature flags for route trees and helper bundles
  • metadata used by the SuperAdmin Launch Control page

Main Layers

1. Runtime surface gating

Used to hide or redirect user-facing surfaces while keeping the code available in the repo. Examples of exported helpers:
  • isLaunchPathEnabled(path)
  • getLaunchPathRedirect(path)
  • isLaunchRoutePathEnabled(path)
  • isLaunchWidgetEnabled(widgetId)
  • isDocumentBrainTabLaunchEnabled(tab)
  • isReportTabLaunchEnabled(tab)
  • isProjectsTabLaunchEnabled(tab)
These functions are consumed by routes, layout/navigation surfaces, widget loading, and module-local tab builders.

2. Build-time route gating

Used to keep disabled route trees out of the production build graph. Examples:
  • BUILD_ENABLE_GRANTORS_ROUTE
  • BUILD_ENABLE_GRANT_CONTROL_ROUTE
  • BUILD_ENABLE_PORTAL_ROUTES
  • BUILD_ENABLE_PARTNERSHIP_ROUTES (controls partnershipRoutes and the platform sidebar Partnerships item)
  • BUILD_ENABLE_MISSION_ROUTE (controls missionRoutes and the tenant sidebar Mission item)
  • BUILD_ENABLE_INVITATIONS_ROUTE (controls invitations route activation independently from Mission workspace routing)
  • BUILD_ENABLE_BILLING_ROUTES
  • BUILD_ENABLE_REPORTING_AUX_ROUTES
  • BUILD_ENABLE_PROJECT_PORTAL_TAB
These flags are literal booleans so route config modules can be tree-shaken by Vite/Rollup. PlatformNavItemDef (in src/components/layout/navConfig.ts) and tenant NavItemDef both support an optional launchCheck?: () => boolean. This lets a nav item reference a build flag directly:
{
  id: "partnerships",
  label: "Partnerships",
  icon: Handshake,
  to: "/platform/partnerships",
  launchCheck: () => BUILD_ENABLE_PARTNERSHIP_ROUTES,
}
The tenant nav filters via useNavResolver (item.launchCheck?.() ?? true); the platform sidebar filter in Sidebar.tsx mirrors the same predicate. This prevents a nav link from pointing to a tree-shaken route. See ADR #20 (Partnership Routes Build-Gated for Launch) in docs/overview/decision-log.md.

3. Access-layer alignment

Launch scope is not the same as permission scope. Launch gating answers:
  • “Is this surface available at all?”
RBAC answers:
  • “Which role may use it?”
These are combined through:
  • src/lib/featureAccess.ts
  • src/hooks/useLaunchFeatureAccess.ts
This is what powers the role preview inside the SuperAdmin Launch Control UI.

Current Architecture Flow

What Is Centralized Today

Module-level gating

Representative modules currently captured in launch-scope metadata:
  • Journaling
  • Expenses
  • Projects
  • Document Brain
  • Reporting
  • Personnel
  • Grant Control
  • Grantors
  • Billing and subscription
  • Impact and portal surfaces
  • launch-disabled widget sets

Shell-level gating

Representative shell controls:
  • floating assistant
  • quick tracker
  • feedback widget
  • notification permission prompt

Build-level gating

Representative build exclusions:
  • Grantors route
  • Grant Control route
  • Portal route tree
  • Partnership route tree
  • Mission + invitations route tree (independent build controls)
  • Billing route tree
  • reporting auxiliary routes
  • personnel development route
  • project portal tab

SuperAdmin Surface

Operational UI:
  • src/features/superadmin/components/pages/LaunchControlPage.tsx
Host:
  • src/features/superadmin/components/pages/PlatformManagement.tsx
Current behavior:
  • read-only operational visibility
  • no runtime mutation of launch policy
  • no false “toggle” UX for build-time flags
This is deliberate. The current system is deploy-backed, so the UI reflects the deployed launch state rather than pretending to manage it live.

Why The System Is Read-Only Today

The launch gate affects both runtime behavior and build composition. Some controls can theoretically become runtime-editable later:
  • navigation exposure
  • widget exposure
  • shell helpers
  • selected route redirects
Some controls cannot be made truly runtime-editable without changing the architecture:
  • route-tree tree-shaking
  • bundle exclusion
  • build-only feature partitions
Because of that split, editable toggles were intentionally avoided in the first version. If runtime launch operations are required later, use a two-tier model.

Tier 1: Runtime launch policy

Persist in a platform config document:
  • visible modules
  • visible widgets
  • helper-shell controls
  • route redirect policy
Requirements:
  • server-side validation
  • audit logging
  • environment awareness
  • cache invalidation strategy

Tier 2: Build policy

Keep deploy-only:
  • route-bundle inclusion
  • tree-shaken feature partitions
  • heavy optional module imports
Requirements:
  • compile-time constants
  • release review checklist
  • explicit docs and audit trail

Testing Expectations

The launch gate should be verified at three levels:

Unit level

Example:
  • src/config/launchScope.test.ts
This covers:
  • path gating
  • redirect behavior
  • tab gating
  • widget gating
  • helper visibility
  • launch-control metadata

Route/navigation level

Examples:
  • route config tests
  • navigation action tests
  • shell tests
These ensure hidden surfaces do not leak through route registries or user affordances.

E2E level

Representative launch-scoped specs:
  • tests/e2e/launch-scope.admin.spec.ts
  • tests/e2e/people.spec.ts
  • tests/e2e/critical-flows.*.spec.ts
These validate that launch-visible flows still work after gating reductions.

Design Constraints

The launch gate should continue to follow these constraints:
  • centralized policy, not scattered local booleans
  • no UI toggle unless it controls something real
  • runtime gating and RBAC must not drift
  • build-disabled routes should not remain emitted as chunks when avoidable
  • hidden surfaces must be removed from:
    • navigation
    • direct routes
    • quick actions
    • command palette
    • widget library
  • src/config/launchScope.ts
  • src/lib/featureAccess.ts
  • src/hooks/useLaunchFeatureAccess.ts
  • src/features/superadmin/components/pages/LaunchControlPage.tsx
  • src/features/superadmin/components/pages/PlatformManagement.tsx
  • src/routes/config/platformLegacyRoutes.tsx
  • src/config/launchScope.test.ts