# Architectural Rules Enforced by Instatic's Test Suite: 18 Critical Constraints

> Discover Instatic's 18 architectural rules enforced by its test suite. Learn how it maintains code quality by preventing violations of import discipline, SQL compliance, and more.

- Repository: [CoreBunch/Instatic](https://github.com/CoreBunch/Instatic)
- Tags: architecture
- Published: 2026-07-03

---

**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`](https://github.com/CoreBunch/Instatic/blob/main/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.

```ts
// ❌ 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`](https://github.com/CoreBunch/Instatic/blob/main/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.

```ts
// ❌ 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`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/data-tables-system-flag.test.ts), [`no-legacy-content-domain.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/no-legacy-content-domain.test.ts), and [`no-legacy-pages-table.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/no-legacy-pages-table.test.ts) enforce that:
- System tables (`posts`, `pages`, `components`) are seeded with `system: true`
- No legacy `pages` or `page_versions` tables exist
- All content lives in `data_*` tables

## Validation and Type Safety

### TypeBox Boundary Validation

[`boundary-validation.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/boundary-validation.test.ts) defines five strict rules for data validation:
1. HTTP responses must use `apiRequest` or `readEnvelope`
2. Raw `JSON.parse(... ) as` casts are prohibited at persistence boundaries
3. Admin code `fetch` usage is restricted to an allow-list (NDJSON streams, SVG bytes, FormData uploads)
4. Server handlers must use `readValidatedBody`
5. Post-validation, fields must reference TypeBox schemas rather than manual casting

```ts
// ❌ 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`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/cms-handlers-capability-gated.test.ts) mandates that every CMS handler calls a capability check such as `requireCapability` or `requireAuthenticatedUser` before executing logic.

```ts
// ❌ 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`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/css-token-policy.test.ts) and [`no-css-var-fallbacks.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/noTailwindUtilities.test.ts) and [`no-tailwind-deps.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/no-tailwind-deps.test.ts) completely ban Tailwind utility classes and related dependencies, enforcing a CSS Modules-only architecture.

```tsx
// ❌ 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`](https://github.com/CoreBunch/Instatic/blob/main/button-primitive-usage.test.ts), [`ui-primitives-location.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/ui-primitives-location.test.ts), [`no-native-browser-dialogs.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/no-native-browser-dialogs.test.ts), [`no-native-title-tooltips.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/no-native-title-tooltips.test.ts), [`no-third-party-icons.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/no-third-party-icons.test.ts), [`direct-icon-imports.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/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/prompt` are banned in favor of built-in `Dialog`/`Toast`
- Icons must be deep-imported from the vendored `pixel-art-icons` package only

## Admin Router Discipline

[`admin-router-usage.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/canvasFastRefreshBoundaries.test.ts) and [`component-system-placement.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/no-circular-dependencies.test.ts) maintains a circular-import-free codebase, while [`canvas-aware-selectors.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/no-vc-mode-branches-in-mutations.test.ts) – Store actions like `insertNode` and `deleteNode` never branch on `kind === 'visualComponent'`
- [`visual-components-mutation-contract.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/visual-components-mutation-contract.test.ts) – Preserves slot-instance/slot-outlet invariants during Visual-Component tree mutations
- [`centralized-site-mutation-history.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/centralized-site-mutation-history.test.ts) – All mutations funnel through a single entry point for consistent undo/redo
- [`no-vc-in-site-shell.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/no-vc-in-site-shell.test.ts) – Prevents visual components in site shell contexts

## Spotlight and Keyboard Registry

[`spotlight-no-direct-store-mutation.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/spotlight-no-direct-store-mutation.test.ts) blocks Spotlight providers from mutating the editor store directly, while [`keybindings-registry-single-source.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/plugin-rpc-target-registry.test.ts) enforces one-to-one mappings between RPC targets and handlers, while [`plugin-bootstrap-fresh.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/plugin-bootstrap-fresh.test.ts) validates that bootstrap artifacts match source bundles exactly.

### Security Boundaries

[`plugin-sandbox-invariants.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/plugin-content-access-enforced.test.ts) and [`plugin-content-tree-via-engine.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/ai-tools-typebox-only.test.ts), [`ai-tool-schema-ssot.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/ai-tool-schema-ssot.test.ts))
- Every AI handler checks capabilities ([`ai-handlers-capability-gated.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/ai-handlers-capability-gated.test.ts))
- Credentials never leak in responses ([`ai-credentials-never-leak.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/ai-credentials-never-leak.test.ts))

## Media and Publishing Pipeline

### Media Correctness

Five tests ([`media-migration-invariants.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/media-migration-invariants.test.ts), [`media-presentation-pipeline.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/media-presentation-pipeline.test.ts), [`media-signed-redirect-serving.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/media-signed-redirect-serving.test.ts), [`media-storage-no-bytes-in-sandbox.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/media-storage-no-bytes-in-sandbox.test.ts), [`media-storage-panel.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/media-storage-panel.test.ts)) ensure:
- Media migrations preserve all variants
- `<picture>` and `srcset` generation are validated
- Signed URLs are used for media downloads
- Sandboxed plugins cannot read raw media bytes

### Publisher Integrity

[`dispatcher-html-pipeline.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/dispatcher-html-pipeline.test.ts) enforces the correct execution order (sanitize → filters → injections), while [`publish-html-filter-context.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/static-artefact-served-before-render.test.ts)), every publish bumps the cache version ([`publish-bumps-cache-version.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/publish-bumps-cache-version.test.ts)), and the hole runtime route precedes public routes ([`hole-runtime-asset-route.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/hole-runtime-asset-route.test.ts)).

## Tooling and Agent Contracts

### Site Import Isolation

[`siteImport-headless.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/agent-no-raw-html-in-reply-rule.test.ts) – Replies remain plain text, no raw HTML/CSS/JSON
- [`agent-system-prompt-no-module-enumeration.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/agent-system-prompt-no-module-enumeration.test.ts) – System prompts cannot enumerate internal modules
- [`agent-tool-surface.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/agent-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`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/migration-parity.test.ts) ensures both dialects share identical migration IDs and order, while [`db-json-column-naming.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/noTailwindUtilities.test.ts) and [`no-tailwind-deps.test.ts`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/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`](https://github.com/CoreBunch/Instatic/blob/main/plugin-content-access-enforced.test.ts).