Critique Centralized Platform Architecture
Capability Evolution: From Client POC to Centralized Platform Worker
Source Issue: #581
Status:uningested(Point-in-time capture pending/docs distillalignment into canonical architecture)
Candidate Distillation Targets:docs/architecture/CAPABILITY_LIFECYCLE.md,docs/architecture/EDGE_ARCHITECTURE.md
1. Executive Summary & Context
In SiteSwarm, horizontal capabilities deliver cross-cutting functionality—such as visual editorial review, analytics, form handling, and cache invalidation—across a multi-tenant fleet of client web applications (apps/*).
The in-situ visual feedback system (@siteswarm/critique) enables business owners, operators, and designers to inspect live DOM elements, pin feedback comments, and coordinate editorial fixes directly on their smartphones and staging previews during deployment cycles.
Originally introduced as a client-centric proof of concept (POC), the Critique capability initially embedded storage adapters and API proxy endpoints directly within each consumer application. While this rapid prototype validated the visual feedback interaction model, it introduced severe architectural liabilities: bloated client production bundles, fragmented API routes, test duplication across apps, and isolated storage silos that trapped critique comments inside ephemeral preview databases.
Under Epic #581 (epic(critique): centralized platform service & D1 persistence), SiteSwarm re-architected the capability into a centralized platform worker service (services/critique) backed by dedicated Cloudflare D1 persistence (siteswarm-critique-db) and direct browser-to-service dynamic CORS egress.
flowchart TD subgraph LegacyPOC["Legacy Client POC Architecture (Fragmented)"] BrowserOld["Client Browser / Mobile Viewport"] -->|"Same-Origin POST /api/critique"| AppWorkerOld["Client App Server (Worker A)"] AppWorkerOld -->|"Bundled Adapters\n(KV / File / D1)"| StorageOld["Siloed Per-App Storage\n(Ephemeral preview databases)"] end
subgraph CentralizedPlatform["Resolved Platform Service Architecture"] BrowserNew["Client Browser / Mobile Viewport"] -->|"Direct HTTPS + Dynamic CORS\n(Zero Client App Routes)"| CritiqueWorker["@siteswarm/service-critique (Platform Worker)"] CritiqueWorker -->|"Prepared SQL Statements\n(Compound tenant_id + environment Index)"| D1Store[("Dedicated D1 SQLite\nsiteswarm-critique-db")] ClientAppNew["Client App Server (Worker A)\nCritiqueOverlay tenantId='...'"] -.->|"Dynamic SSR Boundary\n(0 bytes in production)"| BrowserNew endThis write-up documents the architectural transition, analyzes the anti-patterns of the initial implementation, details the resolved platform worker architecture, presents concrete before-and-after empirical benchmarks, and codifies the reusable platform pattern for all future horizontal capabilities across SiteSwarm.
2. Historical Context & POC Anti-Patterns
The initial POC was designed to get in-situ review working quickly inside early client applications (such as apps/me-portfolio and apps/rcc-stpatrick). To bypass cross-origin browser restrictions without setting up dedicated cloud infrastructure, the initial design bundled storage handling and server routes into the client applications themselves.
Four severe anti-patterns emerged as the client application fleet expanded:
2.1 Fragmented Per-App API Routes (apps/*/src/pages/api/critique.ts)
Every client application was required to maintain a dedicated Astro API route endpoint to proxy incoming critique mutations and queries.
// Legacy apps/rcc-stpatrick/src/pages/api/critique.ts (Pruned in #584)import type { APIRoute } from "astro";import { createCritiqueHandler, MemoryCritiqueAdapter,} from "@siteswarm/critique";
export const prerender = false;
async function getHandler(locals?: any) { let cfEnv: Record<string, any> | undefined; try { // @ts-ignore const cfWorkers = await import("cloudflare:workers"); if (cfWorkers && cfWorkers.env) cfEnv = cfWorkers.env; } catch { // Expected in Node.js / preview runtime }
if (!cfEnv) { try { if (locals?.runtime && "env" in locals.runtime) { cfEnv = locals.runtime.env; } } catch { // Handled if runtime.env throws Astro v6+ removal error } }
const env = cfEnv || {}; const environment = env.ENVIRONMENT || (import.meta.env.DEV ? "development" : "staging"); const storage = new MemoryCritiqueAdapter();
return createCritiqueHandler({ appId: "rcc-stpatrick", environment, serviceBinding: env.CRITIQUE_SERVICE, storage, });}
export const GET: APIRoute = async ({ request, locals }) => (await getHandler(locals))(request);export const POST: APIRoute = async ({ request, locals }) => (await getHandler(locals))(request);export const PATCH: APIRoute = async ({ request, locals }) => (await getHandler(locals))(request);export const ALL: APIRoute = async ({ request, locals }) => (await getHandler(locals))(request);Operational Deficiencies:
- Boilerplate Proliferation: Onboarding a new client site required duplicating 60+ lines of routing glue and error-handling code.
- Runtime Drift & Framework Breakage: Changes to Astro runtime environments (such as the transition from
locals.runtime.envto Cloudflare Worker context in Astro v5/v6) required fleet-wide manual code refactoring across every client application repository. - Deployment Pollution: Client applications intended to be pure static sites with edge asset caching were forced into hybrid server-side rendering (SSR) mode solely to serve critique comments.
2.2 Storage Adapter Bloat in Client Packages
To accommodate varying deployment targets (local dev, Node.js previews, Cloudflare Workers), the capability package @siteswarm/critique bundled four distinct storage adapters inside its core client module:
KVCritiqueAdapter: Cloudflare Workers KV bindings;FileCritiqueAdapter: Node.js filesystem I/O (node:fs) writing to.critiques/${tenantId}.json;D1CritiqueAdapter: Raw Cloudflare D1 SQLite query execution;MemoryCritiqueAdapter: In-memory volatile Map for tests.
// Legacy packages/capabilities/critique/src/adapters.ts (612 LOC, 18,118 bytes)export class FileCritiqueAdapter implements CritiqueStorageAdapter { private baseDir: string; constructor(baseDir = ".critiques") { this.baseDir = baseDir; }
private async ensureDir(): Promise<void> { const fs = await import("node:fs"); // Forces Node.js runtime polyfills if (!fs.existsSync(this.baseDir)) fs.mkdirSync(this.baseDir, { recursive: true }); }
async list(tenantId: string, options?: { environment?: string }): Promise<Critique[]> { const fs = await import("node:fs"); const filePath = `${this.baseDir}/${tenantId}.json`; if (!fs.existsSync(filePath)) return []; return JSON.parse(fs.readFileSync(filePath, "utf8")); } // ... 500+ additional lines of SQL strings, D1 statement mappers, and KV serialization}Operational Deficiencies:
- Client Bundle Inflation: Client web applications were pulling database schemas, Node.js filesystem modules, and SQL statement builders into frontend-adjacent dependencies.
- Leaked Domain Boundaries: Client applications had direct visibility into underlying database table definitions and SQL query syntax.
2.3 Cross-Origin Connectivity & Multi-Tenant Vacuum
Under the POC architecture, critique persistence was strictly bound to the origin serving the application:
- Ephemeral Preview Silos: Critiques submitted by QA or reviewers on an ephemeral pull request preview (
https://tenant-preview-pr-123.pages.dev) were written into an ephemeral database or local file store that was destroyed when the PR merged. Feedback was lost and never visible to the developer in local development. - Missing Multi-Tenant Isolation: Local file adapters wrote unindexed JSON blobs. There was no compound query indexing, no deduplication, and no cross-origin API accessibility.
- Cross-Origin Roadblock: Smartphone visual reviewers inspecting preview URLs could not connect to a central store without encountering browser CORS blockades.
2.4 Monorepo Test Duplication & Maintenance Fragility
Because the capability logic was embedded in per-app API routes and local wrappers, monorepo test suites suffered massive duplication:
- Every client application implemented redundant Playwright E2E tests verifying inspect mode toggling, pin placement, comment inputs, and mock storage responses.
- Test suites across 11 applications broke whenever internal UI class names or keyboard shortcuts changed, resulting in high test maintenance overhead for zero added architectural safety.
3. The Centralized Platform Worker Architecture
SiteSwarm resolved these limitations by extracting critique handling into a dedicated platform worker: @siteswarm/service-critique (located in services/critique), modeled after the successful multi-worker architecture codified in MULTI_WORKER_PLATFORM_SERVICES.md.
sequenceDiagram autonumber actor Reviewer as Smartphone / Browser Reviewer participant ClientApp as Client Frontend (Worker A) participant PlatformWorker as Critique Platform Worker (services/critique) participant D1 as D1 SQLite (siteswarm-critique-db)
Note over Reviewer,ClientApp: Initial Load (Staging or PR Preview) Reviewer->>ClientApp: GET / ClientApp-->>Reviewer: 200 OK (HTML + CritiqueOverlay Dynamic Dev Island)
Note over Reviewer,PlatformWorker: Cross-Origin Direct Service Connectivity Reviewer->>PlatformWorker: OPTIONS /critiques (CORS Preflight) PlatformWorker-->>Reviewer: 204 No Content (Access-Control-Allow-Origin: preview-pr-123)
Reviewer->>PlatformWorker: GET /critiques?tenantId=rcc-stpatrick&environment=staging PlatformWorker->>D1: SELECT * FROM cap_critiques WHERE tenant_id = ? AND environment = ? D1-->>PlatformWorker: Rows (Active Pinned Feedback) PlatformWorker-->>Reviewer: 200 OK (JSON Critiques Array)
Note over Reviewer,PlatformWorker: Pinned Annotation Submission Reviewer->>PlatformWorker: POST /critiques (Payload with DOM Selector & Tags) PlatformWorker->>PlatformWorker: Content Hash Deduplication Check PlatformWorker->>D1: INSERT INTO cap_critiques (...) VALUES (...) D1-->>PlatformWorker: Query Acknowledged PlatformWorker-->>Reviewer: 201 Created { id: "uuid", status: "open" }3.1 Centralized Edge Worker & Dedicated D1 SQLite Database
The platform worker runs as an autonomous Cloudflare Worker with a dedicated Cloudflare D1 database binding (siteswarm-critique-db).
D1 Schema & Compound Indexing:
Database persistence conforms to the cap_ namespace invariant required by DATA_STORAGE_PATTERN.md to ensure capability isolation:
-- services/critique/migrations/0001_initial.sqlCREATE TABLE IF NOT EXISTS cap_critiques ( id TEXT PRIMARY KEY, tenant_id TEXT NOT NULL, environment TEXT NOT NULL, url TEXT NOT NULL, component_name TEXT, selector TEXT NOT NULL, text_snippet TEXT, tags TEXT NOT NULL DEFAULT '[]', -- JSON stringified array of quick tags comment TEXT, author_name TEXT, status TEXT NOT NULL DEFAULT 'open', -- 'open' | 'addressed' | 'resolved' created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, version_metadata TEXT);
-- Compound index optimizing multi-tenant queries and preventing full table scansCREATE INDEX IF NOT EXISTS idx_cap_critiques_tenant_env ON cap_critiques(tenant_id, environment);CREATE INDEX IF NOT EXISTS idx_cap_critiques_status ON cap_critiques(status);Query Isolation & Safety Invariants:
The platform worker repository strictly enforces multi-tenant boundaries at the SQL statement level:
- Unscoped queries (
GET /critiqueswithout atenantId) are immediately rejected with400 Bad Request. - Tenant data partitions are strictly parameterized; SQL queries bind
tenant_idon every read and mutation. - Built-in content deduplication prevents double-submission spikes caused by erratic mobile taps.
3.2 Dynamic CORS Middleware & Direct Browser Egress
Rather than proxying requests through client application servers (which wastes CPU time on Worker A and requires per-app routing boilerplate), the browser overlay connects directly to the platform worker via cross-origin HTTPS fetch requests.
The platform worker uses dynamic origin inspection middleware (services/critique/src/cors.ts) to permit legitimate local development, preview, and staging environments while rejecting untrusted domains:
export function isAllowedOrigin(origin: string | null): boolean { if (!origin) return false; try { const { hostname } = new URL(origin);
// 1. Local development origins: localhost or 127.0.0.1 if (hostname === "localhost" || hostname === "127.0.0.1") return true;
// 2. Staging domain pattern: *-staging.* if (hostname.includes("-staging.")) return true;
// 3. Ephemeral pull request previews: *-preview-pr-* if (hostname.includes("-preview-pr-")) return true;
return false; } catch { return false; }}
export function getCorsHeaders(origin: string | null): Record<string, string> { if (!origin || !isAllowedOrigin(origin)) return {}; return { "Access-Control-Allow-Origin": origin, "Access-Control-Allow-Methods": "GET, POST, PATCH, OPTIONS", "Access-Control-Allow-Headers": "Content-Type, Authorization, X-SiteSwarm-Tenant-Id, X-SiteSwarm-Environment, X-SiteSwarm-Commit-Sha, X-SiteSwarm-Build-Time", "Access-Control-Max-Age": "86400", Vary: "Origin", };}This enables seamless visual feedback across branches: a critique pinned on a mobile smartphone previewing https://rcc-stpatrick-preview-pr-584.pages.dev writes to siteswarm-critique-db and is immediately visible to the engineer running http://localhost:4321.
3.3 Dual-Component Dynamic SSR Boundary (0-Byte Production Footprint)
A core requirement for client capabilities is that development and review tools must never penalize end-user web performance or leak internal editorial notes into production client bundles.
SiteSwarm achieved a zero-production footprint using a dual-component architecture with dynamic server-side module loading:
---import type { CritiqueClientOptions } from "./client/types.js";
export interface Props { tenantId?: string; apiEndpoint?: string; environment?: string; // ... configuration props}
// In production, capability is strictly disabled unless explicitly overriddenconst isProd = import.meta.env.PROD && import.meta.env.PUBLIC_ENABLE_CRITIQUE !== "true";const { tenantId, apiEndpoint = "https://critique.siteswarm.workers.dev/critiques" } = Astro.props;
if (!tenantId && !isProd) { console.error("[SiteSwarm Critique] Initialization aborted: missing required 'tenantId' prop.");}
// Dynamic server-side import: in production builds, DevOverlay is NEVER importedlet DevOverlayComponent: any = null;if (!isProd && tenantId) { DevOverlayComponent = (await import("./client/DevOverlay.astro")).default;}---{ DevOverlayComponent && ( <DevOverlayComponent {...Astro.props} apiEndpoint={apiEndpoint} /> )}Behavioral Runtime Proof:
Because import("./client/DevOverlay.astro") is deferred behind the !isProd conditional branch, Astro’s static compiler completely elides the component, styles, and client scripts from production bundles.
Build artifact inspection in packages/capabilities/critique/tests/zero-prod-footprint.test.ts proves that dist/ contains:
- 0 bytes of HTML markup related to Critique;
- 0 bytes of client JavaScript (
mountCritiqueOverlay, DOM inspector, or floating dock); - 0 network requests to the critique platform worker.
3.4 Decoupled Testing Strategy: Centralized Suite vs. Client Smoke Tests
With the platform worker centralized, test architecture follows a strict division of responsibility:
flowchart LR subgraph CentralizedTests["services/critique & packages/capabilities/critique"] ServiceTests["18 Miniflare Integration Tests\n(Real D1 SQLite, CRUD, CORS, Dedup, Status Transitions)"] ClientCoreTests["27 Capability Unit Tests\n(Overlay lifecycle, query params, keyboard events)"] ZeroProdTests["Build Artifact Proof\n(Astro dist/ inspection for 0-byte emission)"] end
subgraph ClientAppSmoke["apps/* (e.g. apps/rcc-stpatrick)"] SmokeTests["Lightweight Smoke Assertion\n(Verify CritiqueOverlay mounts in preview/staging)"] end
CentralizedTests -->|"Guarantees Capability Correctness Monorepo-Wide"| ClientAppSmoke- Centralized Integration Test Suite: Complete interaction coverage (DOM element pinning, keyboard dismiss shortcuts, localStorage preference caching, 3-state transitions, multi-tenant SQL filtering) is tested against real Miniflare workerd and D1 instances in
services/critique/testsandpackages/capabilities/critique/tests. - Client Application Smoke Tests: Client applications run a single, lightweight smoke assertion in Playwright to verify that the canonical
<CritiqueOverlay tenantId="<app>" />mounts cleanly in non-production environments without console errors.
4. Concrete Comparative Metrics & Empirical Proof
The refactoring executed under Epic #581 delivered substantial improvements across bundle size, code reduction, and operational maintainability.
4.1 Before vs. After Metric Comparison
| Architectural Dimension | Initial POC Architecture | Resolved Platform Architecture | Empirical Impact |
|---|---|---|---|
Client Adapter Size (adapters.ts) |
18,118 bytes (612 LOC) | 3,021 bytes (95 LOC) | $\mathbf{83.33%}$ reduction (pruned KV, File, D1) |
| Client Production Bundle Footprint | ~18.5 KB JS + CSS injected into production builds | 0 bytes HTML / 0 bytes JS | $\mathbf{100%}$ bundle elimination in production |
| Client Server-Side Routes | 1 route per app (/api/critique.ts, ~62 LOC) |
0 routes across all client applications | 100% elimination of client routing glue |
| Cross-Origin Connectivity | None (blocked by browser CORS; isolated to host) | Global (Dynamic CORS for localhost, staging, PR previews) |
Direct browser-to-worker HTTPS egress |
| Storage Persistence Model | Ephemeral per-app files / local preview databases | Centralized Cloudflare D1 (siteswarm-critique-db) |
Durable multi-tenant SQL store across all PRs |
| Query Indexing | Unindexed JSON array scans / file deserialization | Compound index on (tenant_id, environment) |
$O(\log N)$ indexed retrieval; zero full-table scans |
| Monorepo Test Maintenance | 20+ duplicated E2E tests per client application | 1 centralized service suite + 1 client smoke assertion | Massive CI execution and maintenance reduction |
4.2 Bundle Reduction Formulation
The client adapter file size reduction is quantified by the metric:
$$\Delta M = \frac{M_{\text{legacy}} - M_{\text{pruned}}}{M_{\text{legacy}}} = \frac{18{,}118\text{ B} - 3{,}021\text{ B}}{18{,}118\text{ B}} = \frac{15{,}097\text{ B}}{18{,}118\text{ B}} \approx 83.33% \approx 84%$$
This reduction is permanently protected by an automated regression test in packages/capabilities/critique/tests/bundle-size.test.ts:
test("verifies adapters.ts size is drastically reduced after pruning legacy adapters", () => { const adaptersPath = path.join(PKG_DIR, "src", "adapters.ts"); const stat = fs.statSync(adaptersPath);
// Legacy unpruned adapters.ts was 18,118 bytes and 612 lines. assert.ok(stat.size < 5000, `adapters.ts size (${stat.size} bytes) should be under 5,000 bytes`);
const reductionPercent = ((18118 - stat.size) / 18118) * 100; assert.ok(reductionPercent >= 70, `Adapter pruning achieved ${reductionPercent.toFixed(1)}% reduction`);});5. Architectural Sequence & State Flows
5.1 The 3-State Critique Verification Lifecycle
Rather than a simplistic binary open/closed state, SiteSwarm critiques operate across a 3-state verification lifecycle:
$$\mathcal{S} = {\text{open}, \text{addressed}, \text{resolved}}$$
$$\text{open} \xrightarrow{\text{fix commit}} \text{addressed} \xrightarrow{\text{staging review}} \text{resolved}$$
stateDiagram-v2 [*] --> open: Reviewer Pins Element on Mobile Preview open --> addressed: Fix Committed & Deployed to Staging addressed --> open: Reopened (Visual Fix Rejected by Reviewer) addressed --> resolved: Verified & Promoted to Production resolved --> open: Reopened (Regression Detected in Subsequent Build) resolved --> [*]open: Defect is active and unresolved; overlay displays red indicator pin.addressed: Engineer has deployed a fix commit; overlay displays amber indicator pin prompting the reviewer to visually verify the change in-situ.resolved: Fix verified; overlay clears the pin from default view while retaining historical record in D1.
5.2 Direct Cross-Origin Ingress Sequence
sequenceDiagram autonumber participant Browser as Client Browser (localhost / preview-pr-* / staging) participant Worker as services/critique Edge Worker participant Storage as D1 Database (siteswarm-critique-db)
Browser->>Worker: POST /critiques (Origin: https://rcc-stpatrick-preview-pr-584.pages.dev) activate Worker Worker->>Worker: isAllowedOrigin(origin) -> true Worker->>Worker: Validate required tenantId & selector Worker->>Worker: Check deduplication hash key Worker->>Storage: INSERT INTO cap_critiques (...) VALUES (...) activate Storage Storage-->>Worker: 1 row affected deactivate Storage Worker-->>Browser: HTTP 201 Created + Access-Control-Allow-Origin deactivate Worker6. Reusable Platform Capability Pattern & Horizontal Guardrails
The successful evolution of the Critique capability provides a standardized architectural pattern for all future horizontal platform capabilities across SiteSwarm (such as form handling, customer reviews, telemetry, search, and inquiries).
flowchart TD subgraph CanonicalPattern["The SiteSwarm Horizontal Capability Blueprint"] WorkerService["1. Dedicated Platform Worker (services/:capability)\n- Multi-tenant edge routing\n- Dedicated D1 SQLite database with cap_:name schema\n- Dynamic CORS middleware (*-staging, *-preview-pr-*, localhost)"]
ThinClient["2. Thin Capability Client (packages/capabilities/:capability)\n- Canonical CapabilityOverlay Astro component\n- Dual-component dynamic SSR boundary (0 bytes in prod)\n- Minimal memory adapter retained strictly for local unit tests"]
DirectEgress["3. Direct Browser Egress\n- Zero per-app API routes (apps/*/src/pages/api/)\n- Browser connects directly to platform worker URL\n- Client apps maintain zero Cloudflare service bindings"]
DecoupledTests["4. Decoupled Verification Gate\n- Centralized Miniflare + D1 integration suite in service\n- Real Astro production build artifact inspection test\n- Lightweight smoke assertion in client applications"] endThe 5 Golden Rules for SiteSwarm Platform Capabilities:
- Direct HTTP Egress Over Client Proxying:
Capabilities that communicate with the browser must expose direct HTTPS endpoints protected by dynamic CORS. Never introduce pass-through proxy routes (apps/*/src/pages/api/<capability>.ts) inside client application servers. - Dedicated Cloudflare D1 Storage with
cap_Namespace:
Capability storage must live in a dedicated D1 SQLite database owned by the platform worker. All tables must use thecap_<capability>prefix, and queries must index(tenant_id, environment)to enforce multi-tenant isolation and prevent full table scans. - Dual-Component Dynamic SSR Boundary for Zero-Production Footprint:
Development, testing, or feedback capabilities must gate client imports behind!import.meta.env.PRODand dynamic SSR module loading (await import(...)). Build artifact inspection tests must verify that client production builds emit exactly 0 bytes of HTML and 0 bytes of JavaScript. - Adapter Pruning in Client Packages:
Client capability packages must not export heavy storage adapters (KV, filesystem, D1 drivers). Retain only a lightweight in-memory adapter strictly for hermetic offline unit testing. - Decoupled Verification Architecture:
Complex interaction testing (modal forms, keyboard shortcuts, pin placement, state transitions) must be tested once centrally within the platform worker and capability package suites. Client applications must only execute a lightweight smoke test asserting that the component mounts without runtime errors.
7. Candidate Canonical Updates
During the upcoming /docs distill alignment session, the insights from this write-up will be distilled into the following canonical architecture specifications:
7.1 Updates for docs/architecture/CAPABILITY_LIFECYCLE.md
- Scaffold Canonical Capability Lifecycle Document: Formalize the lifecycle phases of a SiteSwarm capability: Local Spike $\to$ Client POC $\to$ Platform Worker Extraction $\to$ Fleet Decoupling.
- Codify the Direct Egress Invariant: Document that client applications must never maintain server-side proxy routes for capabilities when dynamic CORS direct egress is feasible.
- Formalize Adapter Pruning Policy: Require that capability client libraries prune backend storage drivers once a centralized platform worker is provisioned.
7.2 Updates for docs/architecture/EDGE_ARCHITECTURE.md
- Edge Dynamic CORS Pattern: Add the standard regex/matching rules (
localhost:*,*-staging.*,*-preview-pr-*) as the monorepo standard for platform worker ingress. - Multi-Tenant Compound Indexing Mandate: Document the mandatory indexing strategy for all multi-tenant D1 databases:
CREATE INDEX idx_cap_<name>_tenant_env ON cap_<name>(tenant_id, environment). - Zero-Production Footprint Verification Pattern: Standardize the dynamic SSR import pattern (
await import("./DevOverlay.astro")) and the corresponding test verification pattern (zero-prod-footprint.test.ts) across all development tools.
8. Decisions Intentionally Deferred
In strict alignment with the SiteSwarm anti-scope-inflation guardrails, the following architectural enhancements were evaluated during Epic #581 and intentionally deferred to downstream tickets:
- CORS Bearer Token & Signature Authentication (Deferred to Spike #585):
Currently, dynamic CORS filters requests by checking the HTTPOriginheader against permitted staging and preview patterns. Adding cryptographic JWT or HMAC token verification for preview review sessions is deferred to Spike #585 (spike(critique): post-MVP reflection on CORS tokens, D1 tenant quotas & agent ingestion). - Tenant Storage Quotas & Automatic TTL Purging (Deferred to Spike #585):
siteswarm-critique-dbcurrently relies on D1’s standard capacity without per-tenant storage caps or automatic row expiration. Enforcing retention limits (e.g., auto-archiving resolved critiques older than 90 days) will be addressed in post-MVP database governance. - Automated AI Agent Ingestion Pipeline (Deferred to Spike #585):
Exposing a machine-readable endpoint for automated remediation agents to read pending critiques and submit pull requests is deferred until the manual review workflow achieves fleet-wide stability.