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,53 @@
# Document site middleware integration
**Package**: `@suaveplan/api-plugin-site`
**Status**: PROPOSED
**Type**: spec-modification (no new runtime deps)
- **Spec delta**: ./specs/api-plugin-site/spec.md
## Why
The initial `@suaveplan/api-plugin-site` migration (archived 2026-05-19) explicitly excluded JWT / permissions / rate-limit / audit middleware wiring with the following justification:
> JWT / permissions / rate-limit / audit middleware wiring — depends on `@suaveplan/api-plugin-rate-limit` + `@suaveplan/api-plugin-audit` already landed in genesis, but the integration knob is the host app's `app.use(prefix, middleware)` Hono pattern. The site plugin does NOT hard-depend on them so excluding integration from THIS migration does not block consumers from layering them on top.
Both sibling plugins now ship on genesis. The exclusion remains correct in spirit — the site plugin must NOT hard-depend on them so consumers can swap implementations or skip them entirely — but the integration pattern itself is currently undocumented and unverified. Consumers wiring the three packages together today must reconstruct the pattern from first principles and have no test fixture proving the composition works.
This change closes the gap **through documentation + a runnable integration test**, not through new runtime dependencies. The site plugin keeps zero runtime deps on `api-plugin-rate-limit` and `api-plugin-audit`; those packages become `devDependencies` consumed solely by a new integration test that boots the canonical composed-host configuration and asserts (a) site behaviour is unchanged, (b) rate-limit headers appear on responses, (c) audit events are emitted into the in-memory sink.
## What changes
- ADDED: `src/integration/middleware-composition.integration.test.ts` — boots a Hono app with `createSitePlugin` route trees, layered under `rateLimit(...)` and `createAuditMiddleware(...)`, exercises a write route, asserts the four observable outcomes (status, site row persisted, `X-RateLimit-*` headers, audit `events.length === 1`).
- ADDED: `MIDDLEWARE_RECOMMENDATIONS` — readonly typed bundle (`MiddlewareRecommendation[]`) describing recommended rate-limit windows and audit categories per site route group (public resolve, public read, private write). Pure data; callers consume it to derive their middleware configuration. Not bound by the site plugin itself.
- ADDED: `src/integration/middleware-recommendations.ts` (+ sibling `.md`) — exports the recommendations bundle and the `MiddlewareRecommendation` type.
- ADDED: `docs/middleware-integration.md` — package-level guide with the canonical `app.use(prefix, middleware)` Hono sequence, the recommended layering order (audit OUTERMOST → rate-limit MIDDLE → site routes INNERMOST), justification, and a copy-pasteable example.
- MODIFIED: `src/routes/private-routes.md` — appends a "Recommended middleware" section pointing at `MIDDLEWARE_RECOMMENDATIONS` and explaining why write routes benefit most from both layers.
- MODIFIED: `README.md` — adds a "Middleware composition" subsection linking to `docs/middleware-integration.md` and `MIDDLEWARE_RECOMMENDATIONS`.
- MODIFIED: `package.json` — adds `@suaveplan/api-plugin-rate-limit` and `@suaveplan/api-plugin-audit` as **devDependencies only** (consumed by the integration test). NO runtime-dep change.
- MODIFIED: `src/index.ts` — re-exports `MIDDLEWARE_RECOMMENDATIONS` and `MiddlewareRecommendation`.
### Source mapping
| Concern | New file | Notes |
|---|---|---|
| Composed-host integration proof | `src/integration/middleware-composition.integration.test.ts` | Real `rateLimit` middleware + real `createAuditMiddleware` + real `createPrivateSiteRoutes` against in-memory site DB. No mocks. |
| Typed recommendations consumable by callers | `src/integration/middleware-recommendations.ts` | Pure data + types; zero runtime dep on the middleware plugins. |
| Package-level guide | `docs/middleware-integration.md` | Allowed exception — explicit docs subfolder permitted per the §0 task brief; supplements the README. |
| Feature-doc cross-reference | `src/routes/private-routes.md` (modified) | Adds "Recommended middleware" section. |
### Excluded from this change
- JWT / permissions wiring — `api-plugin-auth` has shipped its first chain but the broader permissions plugin family is still in flight; documenting auth integration would risk inverting the dep ordering. Will be revisited once the permissions plugin ships.
- Hard runtime deps on `api-plugin-rate-limit` / `api-plugin-audit` — explicitly prohibited by §0 task brief and by the original exclusion rationale (composition stays in the host).
- Helper factory that wires all three plugins together (e.g. `createComposedSiteHost(...)`) — would be either redundant (one-liner around `app.use`) or premature abstraction; the documented pattern + integration test cover the need.
## Migration
No public-API breakage. Consumers already wiring middleware around the site plugin keep their current code; they MAY adopt `MIDDLEWARE_RECOMMENDATIONS` for typed limits but are not required to. The two new packages are devDependencies, so consumer installs are unaffected.
## Impact
### Affected dependents
`bunx turbo ls --filter=...@suaveplan/api-plugin-site` returns zero downstream consumers on genesis (this is still the first landing wave). No dependent sweep required.

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"`
---

View File

@@ -0,0 +1,36 @@
# Tasks — document-site-middleware-integration
## 1. Authoring
- [x] 1.1 Read the original `add-api-plugin-site` proposal exclusion paragraph and confirm the no-hard-dep constraint.
- [x] 1.2 Author `proposal.md` with `### Source mapping` + `### Excluded from this change` + `### Affected dependents`.
- [x] 1.3 Author the spec delta in `specs/api-plugin-site/spec.md` with `## ADDED Requirements` + `## MODIFIED Requirements`.
## 2. Implementation
- [x] 2.1 Add `src/integration/middleware-recommendations.ts` exporting `MiddlewareRecommendation` type + `MIDDLEWARE_RECOMMENDATIONS` constant with one recommendation per route group (public-resolve, public-read, private-write).
- [x] 2.2 Add sibling `src/integration/middleware-recommendations.md` (≥200 words, Purpose / Features / Basic / Advanced / API Reference / Implementation Notes).
- [x] 2.3 Add `src/integration/middleware-composition.integration.test.ts` — real Hono app composing `createAuditMiddleware`, `rateLimit`, and `createPrivateSiteRoutes`; assert site behaviour preserved, rate-limit headers set, audit event recorded.
- [x] 2.4 Update `src/routes/private-routes.md` with "Recommended middleware" section.
- [x] 2.5 Update `README.md` with "Middleware composition" subsection linking the doc + recommendations.
- [x] 2.6 Add `docs/middleware-integration.md` (package-level guide).
- [x] 2.7 Update `src/index.ts` to re-export `MIDDLEWARE_RECOMMENDATIONS` and `MiddlewareRecommendation`.
- [x] 2.8 Update `package.json` to add `@suaveplan/api-plugin-rate-limit` + `@suaveplan/api-plugin-audit` as `devDependencies` only.
- [x] 2.9 Update the `api-plugin-site.spec-conformance.test.ts` surface count to include the new export.
## 3. Pre-archive gates
- [x] 3.1 `bunx biome check src/` clean.
- [x] 3.2 `bunx turbo lint typecheck test --filter=@suaveplan/api-plugin-site` green.
- [x] 3.3 `bunx turbo test:coverage --filter=@suaveplan/api-plugin-site` ≥ 100% on every metric.
- [x] 3.4 `bun scripts/openspec-conformance.ts @suaveplan/api-plugin-site` returns 0 errors.
- [x] 3.5 `bunx turbo build --filter=@suaveplan/api-plugin-site` green.
- [x] 3.6 Banned-pattern scan returns no hits (`@deprecated`, `TODO`, `FIXME`, `ts-ignore`, `ts-expect-error`, `.skip`, `.only`, ` any `, `console.log`).
- [x] 3.7 Test-runner import scan returns no hits (`from "vitest"` / `from "bun:test"`).
- [x] 3.8 Sibling `.md` scan returns no missing-doc hits.
- [x] 3.9 No bare versions in `package.json`.
## 4. Archive
- [ ] 4.1 Fold `specs/api-plugin-site/spec.md` into `openspec/specs/api-plugin-site/spec.md`.
- [ ] 4.2 `mv openspec/changes/document-site-middleware-integration openspec/archive/2026-05-19-document-site-middleware-integration`.