[pending-judge] feat(DC-165): product/site uniformity — fleet gate, complete premium list, LLM-readable capabilities endpoint

Site-vs-product audit (2026-10-09, owner decision: "advertise as Premium")
reconciles the entitlement triangle: marketing copy <-> PREMIUM_FEATURES
<-> license-server grant list.

- Fleet: the pricing page has always sold Multi-Host Fleet Management as
  Premium; code never gated it. Added fleet to PREMIUM_FEATURES and mounted
  requirePremium('fleet') at the ROUTER level (app.js) so every current AND
  future /fleet/* sub-route inherits the gate (fail-closed for new endpoints).
  License-server side: plans.js grants fleet for new activations; existing
  premium license records backfilled (ops, DNS-license-server).
- Workflows + auto-backup: these were requirePremium-gated in routes since
  forever but absent from PREMIUM_FEATURES — the offline path could never
  grant them and the site never advertised them. Listed them (descriptions
  taken from bundled-workflows.js + backups/schedule schema fields) so the
  single source of truth now covers every gated feature; offline migration
  (below) grants them to existing activations; server grant list updated.
- Offline activation forward-migration: load() now refreshes an OFFLINE
  activation's features snapshot to the current PREMIUM_FEATURES set when
  entries are missing (exactly what re-activating the same code today would
  store). ONLINE activations are never touched — the license server stays
  authoritative across the network boundary; this is the creator's local
  build-to-build coherence rule, not an entitlement widening over an
  external service. Persisted via credential store; in-memory state is
  correct even if persistence fails (warn, not fail).
- GET /api/v1/capabilities (public, like /version): machine-readable ground
  truth of the RUNNING build — version, template count + categories, MCP
  tool names, protocol revisions, premium features, language count. Every
  number derived from the same modules the product uses (no drift by
  construction). Registered in PUBLIC_ROUTES (exact:true, GET), added to
  public-routes-drift.test.js directMounts, guarded like /version.
  No secrets, no host data (tested).
- 8 new executed tests: fleet 403-on-free / pass-on-premium through the REAL
  requirePremium middleware (duck-typed LicenseManager instance, prototype
  preserved), hasFeature fallback, offline migration (persisted + in-memory),
  online NOT migrated (valid bounded cache stub incl. lastOnlineValidatedAt),
  capabilities payload == module-derived values (78 templates/17 cats/31
  langs/fleet present), no-secrets scan of the payload.

Tests: dc165 8/8; license-manager 76; tier-enforcement 21; public-routes-
drift + composition-root unchanged green (119 combined on the targeted run).
This commit is contained in:
Hermes committed 2026-10-09 01:26:48 -07:00
1 parent 4143bff8aa
commit d478268de6
7 files changed
+334 -1

No files matched your search

+26
View File
@@ -218,6 +218,32 @@ paths:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/v1/capabilities:
get:
tags: [System]
summary: Get capability manifest
description: >-
Public, machine-readable ground truth of the running build (DC-165):
product version, app-template count and per-category breakdown, MCP
tool names and protocol revisions, premium feature list, and
supported-language count. Every value is derived from the same source
modules the product uses at runtime — intended as the single source of
truth for AI assistants and external docs so static prose cannot
drift. Contains no secrets, credentials, or host-specific data.
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessResponse'
'401':
description: Unauthorized - authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/v1/csrf-token:
get:
tags: [Authentication]