Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
<!-- markdownlint-disable MD024 -->
# 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"`
---