DynoStaticAdmin sign in
Documentation

Foundations

DynoStatic foundations

Locked contracts for the application spine. Product features may grow; these boundaries must not drift.

Hosting contract

  • PHP 8.4+ and MySQL 8 / MariaDB 10.6+ only.
  • No required Node runtime, Redis, containers, or URL rewrites.
  • Physical gateways: index.php, admin/index.php, api/index.php, install/index.php, health.php, integration.php, media.php, plus avatar/feed/style/verify/unsubscribe entrypoints.
  • Website is the ownership, origin, permission, and settings boundary.

Public embed (widgets)

  • Host markup: data-dynostatic-widget="WIDGET_ULID".
  • Loader: {installation}/embed.js (classic deferred script).
  • Events: dynostatic:ready, dynostatic:submitted, dynostatic:consent, dynostatic:error.
  • Public widget/discussion APIs require an exact registered Origin.
  • Mutations use signed one-use action tickets; never trust browser-only auth for writes.

Headless CMS (build-time)

  • CMS documents are not embed widgets. Widgets remain runtime islands; CMS owns SSG-rendered site content.
  • Content API: api/?action=cms.manifest|cms.routes|cms.collection|cms.entry|cms.singleton|cms.media.
  • Auth: Authorization: Bearer dynostatic_cms_… bound to a website. No browser Origin required (CI has none).
  • Public API serves published snapshots only. Drafts stay admin-only until publish.
  • Media: physical media.php?id=ULID (thin gateway into the application). Never serve raw .upload.php storage.
  • Rebuild delivery: subscribe Integrations webhooks to content.published (and related CMS events). CLI cron (bin/dynostatic cron) is the recommended path for timely delivery; the probabilistic web runner is best-effort only.

Composition invariants (acceptance bar)

After the spine rebuild, every web request must satisfy:

  1. One SiteRepository, one JobQueue, one cache facade per request (via SharedKernel).
  2. Admin site selection, roles, and audit go through AdminGate — not per-controller copies.
  3. Worker job kinds are registered by feature modules (JobHandler); discussion/platform/CMS handlers live under src/Jobs/Handlers/ and CmsWebhookFanoutHandler.
  4. Gateway query maps and Router registrations share one route catalog (parity tested). Feature packages implement AppModule (boot / routes / jobHandlers); Application is the orchestrator only.
  5. Fresh installs have no legacy users / projects / project_members / widget_comments / comment_reactions / legacy_admin_* tables.
  6. Content API auth is O(1) lookup + rate-limited; scopes are enforced.
  7. PHPUnit green, including CMS publish conflict and AdminGate role coverage.
  8. DiscussionKernel requires SharedKernel (no duplicate infra graphs).

Explicit non-goals

  • Rewriting the discussion engine or ModuleRegistry catalog from scratch.
  • Merging CMS entries into widgets (or the reverse).
  • Introducing a DI container framework.
  • Git-backed CMS storage or Keystatic Cloud CDN parity.