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
routeGroupfields 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.limitis strictly less than the entry whererouteGroup === "public:read"AND itsauditCategoryis"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 /siteswith 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 theMemoryAuditAdaptersnapshot contains exactly one event whosedetails.path === "/sites"anddetails.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, andsite, 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"