Architectural Rules Enforced by Instatic's Test Suite: 18 Critical Constraints
Instatic encodes 18 categories of structural and design-time invariants as automated architecture tests in src/__tests__/architecture/*.test.ts, breaking the build on violations of barrel-import discipline, ANSI-SQL compliance, TypeBox validation boundaries, and plugin sandbox isolation.
Instatic, maintained by CoreBunch, treats architectural decisions as executable code. The test suite located in src/__tests__/architecture/ runs on every bun test invocation, enforcing contracts that span database portability, UI consistency, and security boundaries. These tests ensure that the codebase remains free of circular dependencies, unauthorized capability access, and framework-specific lock-in.
Module Import Discipline
Barrel-Import Enforcement
The test no-core-barrel-deep-imports.test.ts mandates that all external code import public APIs through module barrels rather than internal file paths. This preserves public surface stability and prevents accidental coupling to private implementation details.
// ❌ Wrong – violates no-core-barrel-deep-imports.test.ts
import { PageNode } from '@core/page-tree/node';
// ✅ Correct – uses the barrel export
import { PageNode } from '@core/page-tree';
Database Portability and Schema Rules
ANSI-SQL Compliance
db-postgres-isms.test.ts bans PostgreSQL-specific syntax (now(), ::int, etc.) to maintain cross-database compatibility. Only ANSI-SQL constructs are permitted, ensuring the application runs identically on both PostgreSQL and SQLite.
// ❌ Illegal – fails db-postgres-isms.test.ts
await db.query('SELECT * FROM posts WHERE created_at > now()');
// ✅ Compliant – ANSI-SQL
await db.query('SELECT * FROM posts WHERE created_at > CURRENT_TIMESTAMP');
JSON Column Conventions
db-json-column-naming.test.ts enforces that all JSON columns end with the _json suffix. This allows the database layer to map Postgres jsonb types to SQLite text types automatically without schema drift.
Migration Parity
migration-parity.test.ts ensures that PostgreSQL and SQLite migrations share identical IDs and execution order, preventing environment-specific schema divergence.
Content Storage Invariants
Tests including data-tables-system-flag.test.ts, no-legacy-content-domain.test.ts, and no-legacy-pages-table.test.ts enforce that:
- System tables (
posts,pages,components) are seeded withsystem: true - No legacy
pagesorpage_versionstables exist - All content lives in
data_*tables
Validation and Type Safety
TypeBox Boundary Validation
boundary-validation.test.ts defines five strict rules for data validation:
- HTTP responses must use
apiRequestorreadEnvelope - Raw
JSON.parse(... ) ascasts are prohibited at persistence boundaries - Admin code
fetchusage is restricted to an allow-list (NDJSON streams, SVG bytes, FormData uploads) - Server handlers must use
readValidatedBody - Post-validation, fields must reference TypeBox schemas rather than manual casting
// ❌ Fails boundary-validation.test.ts
const data = JSON.parse(body) as MyType;
// ✅ Valid – uses TypeBox helper
import { safeParseJson } from '@core/utils/json';
const data = safeParseJson(body, MyTypeSchema);
Error Handling Consistency
no-inline-error-ternary.test.ts requires that every catch (err) block in admin code extract messages via getErrorMessage(err, fallback), prohibiting manual ternary error checks.
Security and Capability Gating
Handler Protection
cms-handlers-capability-gated.test.ts mandates that every CMS handler calls a capability check such as requireCapability or requireAuthenticatedUser before executing logic.
// ❌ Missing capability guard – will fail
export async function deletePost(req: Request) {
// ...
}
// ✅ Protected – passes capability gating
export async function deletePost(req: Request) {
requireCapability(req, 'cms.content.delete');
// ...
}
Metadata Synchronization
capability-picker-coverage.test.ts ensures that capability metadata and client-side capability lists remain synchronized, preventing authorization gaps between server and UI.
Design System and Styling Constraints
CSS Token Policies
css-token-policy.test.ts and no-css-var-fallbacks.test.ts enforce that CSS Modules use only token variables (var(--token)) without raw hex/rgb/hsl values or fallback values in var(--x, fallback).
Tailwind Prohibition
noTailwindUtilities.test.ts and no-tailwind-deps.test.ts completely ban Tailwind utility classes and related dependencies, enforcing a CSS Modules-only architecture.
// ❌ Prohibited by noTailwindUtilities.test.ts
<div className="flex items-center gap-2">...</div>
// ✅ Preferred – CSS Module with token vars
import styles from './MyComponent.module.css';
<div className={styles.container}>...</div>
UI Primitive Requirements
Six tests (button-primitive-usage.test.ts, ui-primitives-location.test.ts, no-native-browser-dialogs.test.ts, no-native-title-tooltips.test.ts, no-third-party-icons.test.ts, direct-icon-imports.test.ts) enforce that:
- Interactive controls use primitives under
src/ui/components/ - Bare
<button>elements require explicit allow-listing with justification - Native
alert/confirm/promptare banned in favor of built-inDialog/Toast - Icons must be deep-imported from the vendored
pixel-art-iconspackage only
Admin Router Discipline
admin-router-usage.test.ts mandates that all internal navigation in the admin UI use the custom router from @admin/lib/routing. Direct <a href="/admin..."> links and react-router-dom usage are prohibited.
Editor State and Canvas Integrity
Component Boundaries
canvasFastRefreshBoundaries.test.ts and component-system-placement.test.ts prevent mixing component and non-component exports in .tsx files and require that component insertion always uses insertComponentRef rather than direct tree mutations.
Dependency and State Rules
no-circular-dependencies.test.ts maintains a circular-import-free codebase, while canvas-aware-selectors.test.ts ensures canvas selectors subscribe to the correct state slices.
Mutation Contracts
Four tests govern page-tree mutations:
no-vc-mode-branches-in-mutations.test.ts– Store actions likeinsertNodeanddeleteNodenever branch onkind === 'visualComponent'visual-components-mutation-contract.test.ts– Preserves slot-instance/slot-outlet invariants during Visual-Component tree mutationscentralized-site-mutation-history.test.ts– All mutations funnel through a single entry point for consistent undo/redono-vc-in-site-shell.test.ts– Prevents visual components in site shell contexts
Spotlight and Keyboard Registry
spotlight-no-direct-store-mutation.test.ts blocks Spotlight providers from mutating the editor store directly, while keybindings-registry-single-source.test.ts ensures all shortcuts flow through a central registry rather than scattered event listeners.
Plugin Architecture and Sandboxing
RPC and Bootstrap Contracts
plugin-rpc-target-registry.test.ts enforces one-to-one mappings between RPC targets and handlers, while plugin-bootstrap-fresh.test.ts validates that bootstrap artifacts match source bundles exactly.
Security Boundaries
plugin-sandbox-invariants.test.ts prevents plugin bundles from importing Node/Bun core modules or performing I/O, requiring all permissions to be centrally declared. plugin-host-import-boundaries.test.ts blocks hosts from importing the API dispatch layer to avoid circular dependencies.
Content Access Enforcement
plugin-content-access-enforced.test.ts and plugin-content-tree-via-engine.test.ts ensure plugins access content only through the engine API, never directly.
AI Infrastructure Isolation
ai-driver-isolation.test.ts bans provider SDKs (@anthropic-ai/..., @openai/...) outside the MCP server context. Complementary tests enforce that:
- All AI-tool schemas are defined once with TypeBox (
ai-tools-typebox-only.test.ts,ai-tool-schema-ssot.test.ts) - Every AI handler checks capabilities (
ai-handlers-capability-gated.test.ts) - Credentials never leak in responses (
ai-credentials-never-leak.test.ts)
Media and Publishing Pipeline
Media Correctness
Five tests (media-migration-invariants.test.ts, media-presentation-pipeline.test.ts, media-signed-redirect-serving.test.ts, media-storage-no-bytes-in-sandbox.test.ts, media-storage-panel.test.ts) ensure:
- Media migrations preserve all variants
<picture>andsrcsetgeneration are validated- Signed URLs are used for media downloads
- Sandboxed plugins cannot read raw media bytes
Publisher Integrity
dispatcher-html-pipeline.test.ts enforces the correct execution order (sanitize → filters → injections), while publish-html-filter-context.test.ts ensures HTML filter plugins receive proper context. Additional tests verify that static artifacts are served before full renders when possible (static-artefact-served-before-render.test.ts), every publish bumps the cache version (publish-bumps-cache-version.test.ts), and the hole runtime route precedes public routes (hole-runtime-asset-route.test.ts).
Tooling and Agent Contracts
Site Import Isolation
siteImport-headless.test.ts verifies that the headless site-import package has no dependencies on admin UI, server code, or React, ensuring pure Node environment execution.
Agent Surface Rules
Three tests govern AI agents:
agent-no-raw-html-in-reply-rule.test.ts– Replies remain plain text, no raw HTML/CSS/JSONagent-system-prompt-no-module-enumeration.test.ts– System prompts cannot enumerate internal modulesagent-tool-surface.test.ts– Write-tools match the documented surface exactly
Summary
- Barrel-import discipline prevents deep coupling to internal modules through
no-core-barrel-deep-imports.test.ts - Database portability is enforced via ANSI-SQL compliance and migration parity tests
- TypeBox boundaries ensure type-safe serialization at all system edges
- Capability gating mandates authorization checks on every CMS handler
- Design system consistency is maintained by banning Tailwind and enforcing CSS token variables
- Plugin sandboxing isolates extensions from Node.js APIs and direct content access
- AI infrastructure isolates provider SDKs and validates tool schemas uniformly
Frequently Asked Questions
What happens when an architectural rule is violated in Instatic?
The relevant test in src/__tests__/architecture/ fails immediately during bun test, breaking the build before the code can be merged. For example, importing from @core/page-tree/node.ts instead of the barrel export triggers no-core-barrel-deep-imports.test.ts to fail, forcing the developer to correct the import at the source.
How does Instatic ensure database compatibility between PostgreSQL and SQLite?
The db-postgres-isms.test.ts test bans PostgreSQL-specific functions like now() and ::int, requiring ANSI-SQL equivalents such as CURRENT_TIMESTAMP. Additionally, migration-parity.test.ts ensures both dialects share identical migration IDs and order, while db-json-column-naming.test.ts standardizes JSON column naming conventions across environments.
Why are Tailwind CSS utility classes prohibited in the Instatic codebase?
Tests noTailwindUtilities.test.ts and no-tailwind-deps.test.ts enforce a CSS Modules-only approach to prevent utility-class bloat and ensure all styling uses the centralized design token system (var(--token)). This guarantees visual consistency and simplifies theming across the application.
How do architecture tests secure the plugin system?
plugin-sandbox-invariants.test.ts prevents plugin bundles from importing Node/Bun core modules or performing unauthorized I/O, while plugin-host-import-boundaries.test.ts blocks circular dependencies between plugins and the API dispatch layer. These tests ensure plugins operate within strict sandbox boundaries, accessing content only through the engine API as enforced by plugin-content-access-enforced.test.ts.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →