Files
2026-05-27 23:29:53 +01:00

4.8 KiB

Capability Spec Delta: api-plugin-site (document-site-middleware-integration)

Package: @suaveplan/api-plugin-site Status: PROPOSED

Every requirement below carries a **Verified by:** line at authoring time.

ADDED Requirements

Requirement: Middleware composition recommendations

The package SHALL expose MIDDLEWARE_RECOMMENDATIONS — a readonly MiddlewareRecommendation[] constant describing the recommended rate-limit window, rate-limit ceiling, and audit category per documented site route group (public:resolve, public:read, private:write). The recommendations SHALL be pure data; the site plugin SHALL NOT bind the recommended middleware itself — consumers compose them via the host app's app.use(prefix, middleware) Hono pattern. MiddlewareRecommendation SHALL be re-exported from the package barrel.

Scenario: bundle covers all three route groups

  • WHEN a caller imports MIDDLEWARE_RECOMMENDATIONS
  • THEN the array contains exactly three entries whose routeGroup fields are "public:resolve", "public:read", and "private:write"

Scenario: private:write carries the tightest limit

  • WHEN a caller picks the entry where routeGroup === "private:write"
  • THEN its rateLimit.limit is strictly less than the entry where routeGroup === "public:read" AND its auditCategory is "data.mutation"

Verified by: src/integration/middleware-recommendations.test.ts::"exposes three route groups" AND src/integration/middleware-recommendations.test.ts::"private:write is tightest and audited as data.mutation"


Requirement: Host-app middleware composition pattern is integration-tested

The package SHALL ship an integration test under src/integration/middleware-composition.integration.test.ts that boots a real Hono app composing (a) createAuditMiddleware from @suaveplan/api-plugin-audit mounted globally, (b) rateLimit from @suaveplan/api-plugin-rate-limit mounted on the site prefix, and (c) createPrivateSiteRoutes from this package mounted under the same prefix. The test SHALL exercise a POST /sites write call and SHALL assert that (1) the site row is persisted (site behaviour unchanged by middleware composition), (2) the response carries at least one X-RateLimit-* header (rate-limit observed the request), and (3) exactly one AuditEvent is recorded in the in-memory audit sink (audit observed the request).

Scenario: composed write path preserves site behaviour, surfaces rate-limit headers, and records one audit event

  • WHEN the composed Hono app receives POST /sites with a valid body and a forwarded-for IP header
  • THEN the response status is 201, res.headers.get("X-RateLimit-Limit") is non-null, and the MemoryAuditAdapter snapshot contains exactly one event whose details.path === "/sites" and details.method === "POST"

Verified by: src/integration/middleware-composition.integration.test.ts::"composes audit + rate-limit + site routes in the documented order"


Requirement: Package-level integration guide

The package SHALL ship docs/middleware-integration.md documenting the canonical Hono app.use(prefix, middleware) composition order (audit outermost → rate-limit middle → site routes innermost), the rationale for that order (audit must observe rate-limit denials; rate-limit must precede expensive handlers), and a copy-pasteable end-to-end example covering all three plugins. The README SHALL link to this guide from a "Middleware composition" subsection.

Scenario: guide exists and exceeds 200 words

  • WHEN the docs-check gate inspects docs/middleware-integration.md
  • THEN the file exists, contains the words app.use, audit, rate-limit, and site, and exceeds 200 words excluding code blocks

Verified by: src/integration/middleware-recommendations.test.ts::"docs/middleware-integration.md exists and documents the composition order"


MODIFIED Requirements

Requirement: Public surface re-exports

The package barrel SHALL re-export the canonical public surface: SITE_CODES, SiteError, DEFAULT_CONFIG, mergeConfig, SiteService, DomainResolverService, normalizeDomain, createDomainResolverMiddleware, createPublicSiteRoutes, createPrivateSiteRoutes, createSitePlugin, getSiteInstruments, resetSiteInstruments, validatePushConfig, SiteSchema, DomainSchema, the four SITE_STATE_* constants, and MIDDLEWARE_RECOMMENDATIONS plus the MiddlewareRecommendation type.

Scenario: re-export surface count

  • WHEN the spec-conformance test imports every documented symbol from the package barrel
  • THEN every symbol resolves and the import does not throw

Verified by: src/api-plugin-site.spec-conformance.test.ts::"re-exports every documented symbol"