From 949299f58d1b3556becd438a502ed6adea3e575a Mon Sep 17 00:00:00 2001 From: admin Date: Fri, 29 May 2026 08:20:56 +0100 Subject: [PATCH] first commit --- .claude-plugin/marketplace.json | 18 + GUIDELINES.md | 737 +++++++++++++++ SKILL.md | 55 ++ docs/README.md | 868 +++++++++++++++++ docs/_intro.md | 3 + docs/api-stack/README.md | 106 +++ docs/api-stack/_intro.md | 3 + docs/api-stack/api/README.md | 102 ++ docs/api-stack/api/_intro.md | 1 + docs/api-stack/api/api-2pc/README.md | 109 +++ .../api-2pc/src/coordinator/coordinator.md | 150 +++ .../api-2pc/src/error-codes/error-codes.md | 97 ++ .../api-2pc/src/instruments/instruments.md | 105 +++ .../api/api-2pc/src/limits/outstanding-cap.md | 104 +++ .../api/api-2pc/src/limits/timeout-ceiling.md | 77 ++ .../api/api-2pc/src/options/options.md | 96 ++ .../api-2pc/src/persistence/persistence.md | 114 +++ .../api/api-2pc/src/phases/commit.md | 94 ++ docs/api-stack/api/api-2pc/src/phases/gid.md | 85 ++ .../api/api-2pc/src/phases/prepare.md | 105 +++ .../api/api-2pc/src/phases/rollback.md | 92 ++ .../api/api-2pc/src/recovery/recovery.md | 133 +++ .../src/registry/participant-registry.md | 111 +++ .../api/api-2pc/src/testing/conformance.md | 100 ++ .../api/api-2pc/src/types/types.types.md | 108 +++ docs/api-stack/api/api-audit-file/README.md | 85 ++ .../src/error-codes/error-codes.md | 83 ++ .../src/fs-helpers/fs-helpers.md | 86 ++ .../api/api-audit-file/src/hmac/hmac.md | 76 ++ .../src/instruments/instruments.md | 78 ++ .../api-audit-file/src/retention/retention.md | 67 ++ .../api-audit-file/src/rotation/rotation.md | 95 ++ .../api/api-audit-file/src/schema/schema.md | 79 ++ .../api/api-audit-file/src/sink/sink.md | 128 +++ docs/api-stack/api/api-audit-stdout/README.md | 79 ++ .../src/error-codes/error-codes.md | 87 ++ .../api/api-audit-stdout/src/hmac/hmac.md | 82 ++ .../src/instruments/instruments.md | 70 ++ .../api-audit-stdout/src/options/options.md | 75 ++ .../api/api-audit-stdout/src/schema/schema.md | 95 ++ .../api/api-audit-stdout/src/sink/sink.md | 108 +++ .../api/api-auth-anonymous/README.md | 60 ++ .../api-auth-anonymous/src/adapter/adapter.md | 72 ++ .../src/error-codes/error-codes.md | 77 ++ .../src/resolver/resolver.md | 79 ++ .../api/api-auth-bearer-static/README.md | 155 ++++ .../src/constant-time/token-match.md | 82 ++ .../src/error-codes/error-codes.md | 94 ++ .../factory/create-bearer-static-resolver.md | 106 +++ .../src/mtls/mtls-gate.md | 79 ++ .../options/bearer-static-resolver-options.md | 96 ++ ...ate-bearer-static-resolver-worker-proxy.md | 110 +++ .../security-scheme-contribution.md | 71 ++ .../src/telemetry/instruments.md | 76 ++ .../api/api-auth-better-auth/README.md | 172 ++++ .../api-auth-better-auth/src/db/database.md | 83 ++ .../src/error-codes/error-codes.md | 88 ++ .../independence/session-without-provider.md | 77 ++ .../src/instruments/instruments.md | 83 ++ .../src/oauth/default-factory.md | 78 ++ .../api-auth-better-auth/src/oauth/github.md | 81 ++ .../src/options/options.md | 105 +++ .../src/principal/map-user-to-principal.md | 77 ++ .../src/provider/create-provider.md | 110 +++ .../src/provider/route-translation.md | 75 ++ .../src/route-prefix/route-prefix.md | 79 ++ .../src/session/create-session.md | 94 ++ .../src/testing/testing.md | 90 ++ docs/api-stack/api/api-auth-jwt/README.md | 135 +++ .../src/claims-mapper/claims-mapper.md | 84 ++ .../src/error-codes/error-codes.md | 76 ++ .../api-auth-jwt/src/jwks-cache/jwks-cache.md | 91 ++ .../api/api-auth-jwt/src/options/options.md | 82 ++ .../api/api-auth-jwt/src/resolver/resolver.md | 108 +++ .../src/security-scheme/security-scheme.md | 66 ++ .../api-stack/api/api-auth-provider/README.md | 68 ++ .../src/capability-id/capability-id.md | 78 ++ .../collision-detector/collision-detector.md | 88 ++ .../src/error-codes/error-codes.md | 91 ++ .../src/path-ownership/path-ownership.md | 83 ++ .../src/provider/provider.md | 92 ++ .../src/route-surface/route-surface.md | 87 ++ .../src/testing/conformance.md | 89 ++ docs/api-stack/api/api-auth-rolled/README.md | 83 ++ .../src/composition/composition.md | 85 ++ .../src/error-codes/error-codes.md | 78 ++ .../api-auth-rolled/src/options/options.md | 90 ++ .../principal-projection.md | 73 ++ .../src/security-schemes/security-schemes.md | 73 ++ .../api-auth-rolled/src/session/session.md | 100 ++ .../src/token-rotator/token-rotator.md | 87 ++ .../api/api-auth-static-principal/README.md | 125 +++ .../src/adapter/adapter.md | 81 ++ .../src/error-codes/error-codes.md | 87 ++ .../create-static-principal-resolver.md | 99 ++ .../src/options/options.md | 82 ++ .../src/security-scheme/security-scheme.md | 75 ++ docs/api-stack/api/api-auth/README.md | 109 +++ .../src/capability-id/capability-id.md | 85 ++ .../api-stack/api/api-auth/src/chain/chain.md | 89 ++ .../api-auth/src/csrf-policy/csrf-policy.md | 90 ++ .../api-auth/src/error-codes/error-codes.md | 84 ++ .../api/api-auth/src/resolver/resolver.md | 119 +++ .../src/security-scheme/security-scheme.md | 89 ++ .../src/session-adapter/session-adapter.md | 81 ++ .../api/api-auth/src/testing/conformance.md | 101 ++ docs/api-stack/api/api-db-adapter/README.md | 128 +++ .../src/engine-registry/engine-registry.md | 88 ++ .../src/error-codes/error-codes.md | 77 ++ .../src/factory/create-db-adapter.md | 84 ++ .../src/migrations/run-migrations.md | 103 ++ .../src/options/db-adapter-options.md | 76 ++ .../proxy/create-db-adapter-worker-proxy.md | 81 ++ .../create-tenant-scoped-wrapper.md | 91 ++ .../src/unsafe/unsafe-query-gate.md | 84 ++ .../api/api-db-sqlite-memory/README.md | 78 ++ .../src/engine/register-engine.md | 77 ++ .../src/error-codes/error-codes.md | 64 ++ .../factory/create-sqlite-memory-adapter.md | 65 ++ .../src/factory/create-sqlite-memory-db.md | 75 ++ .../src/migrations/migrations.md | 81 ++ .../src/options/sqlite-memory-db-options.md | 65 ++ .../src/tenant-scoping/tenant-scoping.md | 81 ++ .../src/testing/harness.md | 68 ++ .../api/api-db-worker-proxy/README.md | 112 +++ .../src/error-codes/error-codes.md | 81 ++ .../src/main-side/main-side.md | 85 ++ .../src/tenant-scoped/tenant-scoped.md | 81 ++ .../src/testing/testing.md | 97 ++ .../src/worker-side/worker-side.md | 96 ++ .../api/api-events-in-memory/README.md | 105 +++ .../api/api-events-in-memory/src/bus/bus.md | 124 +++ .../src/error-codes/error-codes.md | 97 ++ .../src/history/history.md | 97 ++ .../src/options/options.md | 80 ++ .../src/testing/testing.md | 95 ++ .../api/api-events-worker-proxy/README.md | 90 ++ .../src/error-codes/error-codes.md | 71 ++ .../src/main-side/main-side.md | 61 ++ .../src/payload-codec/payload-codec.md | 73 ++ .../src/testing/testing.md | 66 ++ .../src/worker-side/worker-side.md | 58 ++ .../api/api-graphql-apollo/README.md | 69 ++ .../api-graphql-apollo/src/endpoints/http.md | 80 ++ .../src/endpoints/ui-proxy.md | 74 ++ .../src/engine/apollo-engine.md | 105 +++ .../src/error-codes/error-codes.md | 86 ++ .../src/federation/federation.md | 70 ++ .../src/guards/depth-and-complexity.md | 75 ++ .../src/instruments/instruments.md | 76 ++ .../api-graphql-apollo/src/loaders/loaders.md | 75 ++ .../api-graphql-apollo/src/options/options.md | 83 ++ .../persisted-queries/persisted-queries.md | 74 ++ .../src/studio-reporting/studio-reporting.md | 78 ++ .../src/subscriptions/subscriptions.md | 81 ++ .../src/testing/conformance.md | 62 ++ .../api/api-graphql-ui-altair/README.md | 97 ++ .../src/assets/assets.md | 85 ++ .../src/error-codes/error-codes.md | 83 ++ .../src/factory/create-altair-ui.md | 88 ++ .../api-graphql-ui-altair/src/headers/csp.md | 78 ++ .../src/html/render-shell.md | 81 ++ .../src/instruments/instruments.md | 67 ++ .../src/options/options.md | 74 ++ .../api/api-graphql-ui-graphiql/README.md | 107 +++ .../src/assets/assets.md | 78 ++ .../src/error-codes/error-codes.md | 85 ++ .../src/factory/create-graphiql-ui.md | 96 ++ .../src/headers/csp.md | 64 ++ .../src/html/render-shell.md | 77 ++ .../src/instruments/instruments.md | 72 ++ .../src/options/options.md | 81 ++ docs/api-stack/api/api-graphql-yoga/README.md | 90 ++ .../src/engine/execute-helpers.md | 62 ++ .../src/engine/yoga-engine.md | 100 ++ .../src/error-codes/error-codes.md | 71 ++ .../src/federation/federation.md | 75 ++ .../src/guards/depth-and-complexity.md | 67 ++ .../src/instruments/instruments.md | 69 ++ .../api-graphql-yoga/src/loaders/loaders.md | 67 ++ .../api-graphql-yoga/src/options/options.md | 73 ++ .../src/subscriptions/subscriptions.md | 70 ++ .../api-graphql-yoga/src/testing/testing.md | 64 ++ docs/api-stack/api/api-graphql/README.md | 81 ++ .../api-graphql/src/directives/directives.md | 84 ++ .../src/error-codes/error-codes.md | 80 ++ .../api-graphql/src/federation/merge-sdl.md | 101 ++ .../api-graphql/src/federation/namespace.md | 73 ++ .../api-graphql/src/federation/parse-sdl.md | 73 ++ .../api/api-graphql/src/registry/registry.md | 84 ++ .../src/subscription/subscription.md | 85 ++ .../api-graphql/src/testing/conformance.md | 83 ++ .../api-graphql/src/validators/validators.md | 76 ++ docs/api-stack/api/api-host/README.md | 118 +++ .../api/api-host/src/admin-api/admin-api.md | 127 +++ .../api/api-host/src/admin-api/audit-sink.md | 73 ++ .../src/admin-api/idempotency-store.md | 66 ++ .../api-host/src/admin-api/rate-limiter.md | 64 ++ .../capability-registry.md | 82 ++ .../src/define-plugin/define-plugin.md | 78 ++ .../src/empty-secrets/empty-secrets.md | 99 ++ .../src/error-boundary/error-boundary.md | 114 +++ .../api-host/src/error-codes/error-codes.md | 69 ++ docs/api-stack/api/api-host/src/host/host.md | 157 ++++ .../api-host/src/hot-reload/file-watcher.md | 101 ++ .../api/api-host/src/hot-reload/hot-reload.md | 154 +++ .../api/api-host/src/lifecycle/lifecycle.md | 188 ++++ docs/api-stack/api/api-host/src/otel/otel.md | 86 ++ .../src/pipeline-events-bus/in-memory-bus.md | 76 ++ .../src/pipeline-events-bus/noop-bus.md | 59 ++ .../pipeline-events-constants.md | 55 ++ .../api-host/src/plugin-ledger/migrations.md | 83 ++ .../src/plugin-ledger/plugin-ledger.md | 121 +++ .../request-pipeline-driver.md | 75 ++ .../request-pipeline-emitters.md | 77 ++ .../request-pipeline-helpers.md | 70 ++ .../request-pipeline-outcomes.md | 90 ++ .../request-pipeline-stage-emit.md | 74 ++ .../request-pipeline-stage-skip.md | 71 ++ .../request-pipeline-steps.md | 77 ++ .../request-pipeline-validation.md | 90 ++ .../src/request-pipeline/request-pipeline.md | 140 +++ .../src/reserved-prefix/reserved-prefix.md | 73 ++ .../create-test-host/create-test-host.md | 103 ++ .../pipeline-events-conformance.md | 91 ++ .../api/api-host/src/testing/testing.md | 62 ++ .../api/api-jobs-worker-proxy/README.md | 70 ++ .../src/client/client.md | 86 ++ .../src/error-codes/error-codes.md | 68 ++ .../src/handler-bridge/handler-bridge.md | 68 ++ .../src/server/server.md | 86 ++ .../src/testing/testing.md | 84 ++ docs/api-stack/api/api-lifecycle/README.md | 82 ++ .../src/error-codes/error-codes.md | 75 ++ .../src/fsm-factory/fsm-factory.md | 82 ++ .../src/mutex-contract/mutex-contract.md | 80 ++ .../reinstall-criteria/reinstall-criteria.md | 72 ++ .../src/retry-policies/retry-policies.md | 101 ++ .../src/side-effects/side-effects.md | 95 ++ .../api/api-lifecycle/src/states/states.md | 93 ++ .../api-lifecycle/src/testing/conformance.md | 75 ++ .../src/transitions/transitions.md | 94 ++ docs/api-stack/api/api-loader/README.md | 76 ++ .../api-loader/src/cache-bust/cache-bust.md | 91 ++ .../api-loader/src/error-codes/error-codes.md | 94 ++ .../src/journal-entry/journal-entry.md | 102 ++ .../native-binding-detector.md | 102 ++ .../api/api-loader/src/resolver/resolver.md | 107 +++ .../src/rollback-journal/rollback-journal.md | 110 +++ .../src/testing/loader-conformance.md | 104 +++ .../api/api-logger-worker-proxy/README.md | 98 ++ .../src/batching/batching.md | 109 +++ .../src/client/client.md | 95 ++ .../src/control-channel/control-channel.md | 83 ++ .../src/error-codes/error-codes.md | 92 ++ .../src/protocol/protocol.md | 101 ++ .../redaction-passthrough.md | 74 ++ .../src/server/server.md | 90 ++ .../src/testing/conformance.md | 72 ++ .../src/testing/testing.md | 92 ++ docs/api-stack/api/api-manifest/README.md | 111 +++ .../capability-resolver.md | 57 ++ .../api-manifest/src/dep-graph/dep-graph.md | 53 ++ .../api/api-manifest/src/dep-graph/semver.md | 45 + .../src/error-codes/error-codes.md | 61 ++ .../api-manifest/src/hash/canonical-json.md | 44 + .../api/api-manifest/src/hash/hash.md | 49 + .../api/api-manifest/src/parse/parse.md | 51 + .../api/api-manifest/src/schema/compat.md | 51 + .../api/api-manifest/src/schema/config.md | 44 + .../api/api-manifest/src/schema/database.md | 49 + .../api/api-manifest/src/schema/depends-on.md | 47 + .../api/api-manifest/src/schema/errors.md | 48 + .../api/api-manifest/src/schema/events.md | 44 + .../api/api-manifest/src/schema/graphql.md | 45 + .../api/api-manifest/src/schema/identity.md | 54 ++ .../api/api-manifest/src/schema/isolation.md | 46 + .../api/api-manifest/src/schema/jobs.md | 47 + .../api/api-manifest/src/schema/openapi.md | 45 + .../api-manifest/src/schema/permissions.md | 48 + .../src/schema/plugin-manifest.md | 45 + .../api/api-manifest/src/schema/routes.md | 44 + .../api/api-manifest/src/schema/sagas.md | 51 + .../api/api-manifest/src/schema/scopes.md | 46 + .../api/api-manifest/src/schema/secrets.md | 46 + .../api/api-manifest/src/schema/sse.md | 44 + .../api/api-manifest/src/schema/telemetry.md | 47 + .../src/schema/two-phase-commit.md | 44 + .../api/api-manifest/src/schema/uninstall.md | 44 + .../api/api-manifest/src/schema/websockets.md | 44 + .../api-manifest/src/testing/conformance.md | 54 ++ .../validate-error-status-map-shape.md | 49 + ...date-openapi-requires-graphql-or-routes.md | 46 + .../validate-permissions-when-sandboxed.md | 48 + .../src/validators/validate-saga-ownership.md | 46 + docs/api-stack/api/api-migrations/README.md | 126 +++ .../src/adapters/postgres/postgres.md | 88 ++ .../src/adapters/sqlite/sqlite.md | 108 +++ .../src/adapters/surrealql/surrealql.md | 101 ++ .../src/error-codes/error-codes.md | 98 ++ .../api-migrations/src/otel/instruments.md | 78 ++ .../api/api-migrations/src/runner/runner.md | 119 +++ .../api/api-migrations/src/types/migration.md | 113 +++ .../tests/integration/README.md | 29 + .../api/api-openapi-ui-redoc/README.md | 83 ++ .../api-openapi-ui-redoc/src/assets/assets.md | 81 ++ .../src/error-codes/error-codes.md | 83 ++ .../src/handler/handler.md | 96 ++ .../src/html/render-shell.md | 81 ++ .../src/options/options.md | 82 ++ .../src/per-plugin/per-plugin.md | 70 ++ .../api/api-openapi-ui-scalar/README.md | 130 +++ .../src/assets/assets.md | 92 ++ .../src/error-codes/error-codes.md | 84 ++ .../src/handler/handler.md | 91 ++ .../api-openapi-ui-scalar/src/headers/csp.md | 81 ++ .../src/html/render-shell.md | 83 ++ .../src/instruments/instruments.md | 69 ++ .../src/options/options.md | 79 ++ .../src/per-plugin/per-plugin.md | 91 ++ .../api/api-openapi-ui-swagger/README.md | 81 ++ .../src/assets/assets.md | 72 ++ .../src/error-codes/error-codes.md | 63 ++ .../src/handler/handler.md | 67 ++ .../src/html/render-shell.md | 78 ++ .../src/options/options.md | 69 ++ .../src/per-plugin/per-plugin.md | 63 ++ docs/api-stack/api/api-openapi/README.md | 223 +++++ .../api/api-openapi/src/emitter/emitter.md | 129 +++ .../api-openapi/src/endpoints/endpoints.md | 71 ++ .../src/error-codes/error-codes.md | 84 ++ .../api/api-openapi/src/merger/merger.md | 123 +++ .../src/namespacing/namespacing.md | 89 ++ .../plugin-integration/plugin-integration.md | 125 +++ .../api/api-openapi/src/registry/registry.md | 134 +++ .../src/route-factory/route-factory.md | 123 +++ .../src/schema-registry/common-schemas.md | 95 ++ .../src/schema-registry/schema-registry.md | 115 +++ .../api-openapi/src/strictness/strictness.md | 101 ++ .../api/api-openapi/src/types/openapi.md | 84 ++ docs/api-stack/api/api-plugin-audit/README.md | 88 ++ .../src/context/audit-context.md | 51 + .../src/context/context-augmentation.md | 58 ++ .../src/error-codes/error-codes.md | 62 ++ .../src/middleware/audit-middleware.md | 102 ++ .../api-plugin-audit/src/otel/instruments.md | 56 ++ .../api/api-plugin-audit/src/plugin/plugin.md | 62 ++ .../api/api-plugin-audit/src/redact/redact.md | 70 ++ .../api-plugin-audit/src/schemas/options.md | 64 ++ .../src/services/audit-service.md | 72 ++ .../src/services/registry-augmentation.md | 52 ++ .../api/api-plugin-audit/src/types/types.md | 65 ++ docs/api-stack/api/api-plugin-auth/README.md | 195 ++++ .../src/error-codes/error-codes.md | 105 +++ .../src/middleware/context-augmentation.md | 76 ++ .../src/middleware/require-auth.md | 70 ++ .../src/middleware/require-email-verified.md | 73 ++ .../src/middleware/require-role.md | 72 ++ .../api-plugin-auth/src/middleware/session.md | 97 ++ .../api-plugin-auth/src/otel/instruments.md | 103 ++ .../api/api-plugin-auth/src/plugin/plugin.md | 121 +++ .../src/principal/principal.md | 108 +++ .../src/routes/build-routes.md | 81 ++ .../api/api-plugin-auth/src/schema/schema.md | 74 ++ .../api-plugin-auth/src/schemas/options.md | 103 ++ .../api-plugin-auth/src/schemas/principal.md | 90 ++ .../src/schemas/routes/forgot-password.md | 71 ++ .../src/schemas/routes/oauth.md | 106 +++ .../src/schemas/routes/reset-password.md | 77 ++ .../src/schemas/routes/session.md | 64 ++ .../src/schemas/routes/sign-in.md | 73 ++ .../src/schemas/routes/sign-out.md | 65 ++ .../src/schemas/routes/sign-up.md | 77 ++ .../src/schemas/routes/verify-email.md | 72 ++ .../src/services/auth-service.md | 106 +++ .../src/services/registry-augmentation.md | 84 ++ .../api/api-plugin-auth/src/types/types.md | 85 ++ .../api/api-plugin-campaigns/README.md | 68 ++ .../src/context/context.md | 72 ++ .../src/error-codes/error-codes.md | 102 ++ .../src/otel/instruments.md | 90 ++ .../api-plugin-campaigns/src/plugin/plugin.md | 101 ++ .../src/repositories/campaign/campaign.md | 104 +++ .../suppression/suppression-internals.md | 88 ++ .../suppression/suppression-memory.md | 92 ++ .../repositories/suppression/suppression.md | 120 +++ .../src/routes/campaigns/action-routes.md | 96 ++ .../src/routes/campaigns/build-routes.md | 71 ++ .../src/routes/campaigns/crud-routes.md | 94 ++ .../src/routes/campaigns/schemas.md | 85 ++ .../src/routes/shared/require-tenant.md | 83 ++ .../src/routes/shared/strip-undefined.md | 70 ++ .../src/routes/suppression/build-routes.md | 61 ++ .../src/routes/suppression/routes.md | 77 ++ .../src/routes/suppression/schemas.md | 87 ++ .../src/routes/webhooks/build-routes.md | 63 ++ .../src/routes/webhooks/routes.md | 81 ++ .../src/routes/webhooks/schemas.md | 86 ++ .../src/schemas/options.md | 86 ++ .../src/services/registry-augmentation.md | 89 ++ .../api-plugin-campaigns/src/types/types.md | 77 ++ docs/api-stack/api/api-plugin-cms/README.md | 97 ++ .../api-plugin-cms/src/engine/cms-engine.md | 117 +++ .../src/error-codes/error-codes.md | 89 ++ .../api-plugin-cms/src/otel/instruments.md | 77 ++ .../api/api-plugin-cms/src/plugin/plugin.md | 83 ++ .../api-plugin-cms/src/routes/problem-json.md | 90 ++ .../api/api-plugin-cms/src/schemas/options.md | 69 ++ .../src/services/registry-augmentation.md | 82 ++ .../api/api-plugin-database/README.md | 111 +++ .../src/config/config-schema.md | 69 ++ .../src/error-codes/error-codes.md | 80 ++ .../src/migrations/lock.md | 77 ++ .../src/migrations/runner.md | 74 ++ .../src/otel/instruments.md | 77 ++ .../api-plugin-database/src/plugin/plugin.md | 71 ++ .../src/pool/extended-adapter.md | 61 ++ .../api/api-plugin-database/src/pool/pool.md | 95 ++ .../api-plugin-database/src/retry/retry.md | 85 ++ .../src/routes/problem-json.md | 77 ++ .../src/services/registry-augmentation.md | 55 ++ .../src/tenancy/tenancy.md | 65 ++ .../api-plugin-database/src/types/types.md | 101 ++ .../api/api-plugin-event-bus/README.md | 196 ++++ .../src/error-codes/error-codes.md | 104 +++ .../src/middleware/context-augmentation.md | 73 ++ .../src/middleware/request-bus.md | 102 ++ .../src/otel/instruments.md | 100 ++ .../api-plugin-event-bus/src/plugin/plugin.md | 120 +++ .../src/routes/build-routes.md | 95 ++ .../src/schemas/options.md | 106 +++ .../src/schemas/routes.md | 99 ++ .../src/services/backpressure.md | 87 ++ .../src/services/event-bus-service.md | 153 +++ .../src/services/helpers.md | 110 +++ .../src/services/idempotency-cache.md | 77 ++ .../src/services/registry-augmentation.md | 83 ++ .../api-plugin-event-bus/src/topic/topic.md | 119 +++ .../api-plugin-event-bus/src/types/types.md | 91 ++ .../api-stack/api/api-plugin-events/README.md | 112 +++ .../src/error-codes/error-codes.md | 123 +++ .../src/ics/ics-builder/ics-builder.md | 149 +++ .../api-plugin-events/src/otel/instruments.md | 119 +++ .../api-plugin-events/src/plugin/plugin.md | 112 +++ .../event-repository/event-repository.md | 120 +++ .../rsvp-repository/rsvp-repository.md | 115 +++ .../src/routes/events-routes/events-routes.md | 118 +++ .../src/routes/ics-export/ics-export.md | 150 +++ .../src/schemas/event-schemas.md | 105 +++ .../api-plugin-events/src/schemas/options.md | 101 ++ .../src/schemas/rsvp-schemas.md | 99 ++ .../src/services/registry-augmentation.md | 109 +++ .../api/api-plugin-events/src/types/types.md | 109 +++ .../api/api-plugin-example/README.md | 105 +++ .../src/domain/in-memory-store.md | 66 ++ .../src/domain/invoice-rules.md | 85 ++ .../src/domain/invoice.types.md | 64 ++ .../src/domain/validators/assert-shape.md | 94 ++ .../src/domain/validators/schema.types.md | 90 ++ .../src/error-codes/error-codes.md | 75 ++ .../src/instruments/instruments.md | 70 ++ .../api-plugin-example/src/schemas/schemas.md | 66 ++ .../src/trusted/events/events.md | 69 ++ .../src/trusted/plugin/plugin.md | 63 ++ .../src/trusted/routes/routes.md | 75 ++ .../api-plugin-example/src/wasm/dispose.md | 49 + .../src/wasm/handle-request.md | 87 ++ .../api/api-plugin-example/src/wasm/routes.md | 51 + .../api/api-plugin-example/src/wasm/start.md | 52 ++ .../api-plugin-example/src/wasm/wasm-state.md | 52 ++ .../api-stack/api/api-plugin-export/README.md | 89 ++ .../src/error-codes/error-codes.md | 62 ++ .../src/exporters/csv/csv.md | 60 ++ .../src/exporters/json/json.md | 57 ++ .../src/exporters/xlsx/xlsx.md | 58 ++ .../api-plugin-export/src/otel/instruments.md | 56 ++ .../api-plugin-export/src/plugin/plugin.md | 59 ++ .../src/routes/download/download.md | 120 +++ .../src/routes/exports/exports.md | 59 ++ .../src/routes/exports/post-handler.md | 48 + .../src/routes/problem-json/problem-json.md | 127 +++ .../src/services/export/export-service.md | 80 ++ .../src/services/registry-augmentation.md | 44 + .../src/store/memory/memory-store.md | 66 ++ .../src/store/surreal/surreal-store.md | 77 ++ .../src/store/types/types.md | 67 ++ .../api/api-plugin-export/src/types/types.md | 77 ++ .../api/api-plugin-file-upload/README.md | 100 ++ .../src/assembler/assembler.md | 72 ++ .../src/error-codes/error-codes.md | 67 ++ .../src/otel/instruments.md | 64 ++ .../src/plugin/plugin.md | 58 ++ .../src/routes/build-routes.md | 51 + .../src/routes/handlers.md | 49 + .../src/schemas/options.md | 51 + .../src/schemas/routes/initiate.md | 50 + .../src/schemas/routes/single-shot.md | 44 + .../src/schemas/routes/status.md | 60 ++ .../src/services/complete-chunked.md | 54 ++ .../src/services/file-upload-helpers.md | 57 ++ .../src/services/file-upload-service.md | 68 ++ .../src/services/registry-augmentation.md | 43 + .../src/services/single-shot.md | 49 + .../src/session-store/memory.md | 53 ++ .../src/storage/file-system.md | 52 ++ .../src/storage/memory.md | 51 + .../api-plugin-file-upload/src/types/types.md | 74 ++ .../src/validators/mime.md | 56 ++ .../src/validators/size.md | 51 + .../api/api-plugin-graphql/README.md | 108 +++ .../src/error-codes/error-codes.md | 64 ++ .../src/otel/instruments.md | 77 ++ .../api-plugin-graphql/src/plugin/plugin.md | 101 ++ .../src/resolver/resolver.md | 93 ++ .../src/schema-builder/schema-builder.md | 85 ++ .../api-plugin-graphql/src/schemas/options.md | 62 ++ .../src/type-builder/type-builder.md | 63 ++ .../src/types/graphql.types.md | 73 ++ .../api-stack/api/api-plugin-import/README.md | 141 +++ .../src/error-codes/error-codes.md | 87 ++ .../api-plugin-import/src/otel/instruments.md | 91 ++ .../api/api-plugin-import/src/parsers/csv.md | 86 ++ .../api/api-plugin-import/src/parsers/json.md | 59 ++ .../api/api-plugin-import/src/parsers/xlsx.md | 59 ++ .../api-plugin-import/src/plugin/plugin.md | 85 ++ .../api-plugin-import/src/progress/tracker.md | 83 ++ .../src/routes/build-routes.md | 69 ++ .../src/routes/problem-json.md | 70 ++ .../src/routes/progress-sse/progress-sse.md | 124 +++ .../api-plugin-import/src/schemas/options.md | 67 ++ .../api-plugin-import/src/schemas/schemas.md | 81 ++ .../api-plugin-import/src/service/service.md | 115 +++ .../src/services/registry-augmentation.md | 83 ++ .../api/api-plugin-import/src/store/memory.md | 95 ++ .../src/store/surreal/surreal-import-store.md | 155 ++++ .../src/transform/pipeline.md | 112 +++ .../api/api-plugin-import/src/types/types.md | 89 ++ .../api/api-plugin-notifications/README.md | 109 +++ .../src/channels/apn-channel/apn-channel.md | 123 +++ .../channels/email-channel/email-channel.md | 111 +++ .../idempotency-adapter.md | 109 +++ .../notification-dispatcher.md | 157 ++++ .../src/error-codes/error-codes.md | 92 ++ .../src/otel/instruments.md | 85 ++ .../src/plugin/plugin.md | 89 ++ .../device-token-repository.md | 83 ++ .../notification-repository.md | 81 ++ .../notifications-routes.md | 78 ++ .../src/routes/push-routes/push-routes.md | 78 ++ .../src/schemas/dispatch-schemas.md | 86 ++ .../src/schemas/notification-schemas.md | 95 ++ .../src/schemas/options.md | 73 ++ .../src/schemas/push-schemas.md | 97 ++ .../src/services/apn-service/apn-service.md | 105 +++ .../src/services/registry-augmentation.md | 62 ++ .../transport/apn-transport/apn-transport.md | 107 +++ .../src/types/types.md | 76 ++ .../api/api-plugin-payment/README.md | 160 ++++ .../src/error-codes/error-codes.md | 64 ++ .../src/middleware/context-augmentation.md | 47 + .../src/middleware/idempotency-middleware.md | 52 ++ .../src/otel/instruments.md | 58 ++ .../api-plugin-payment/src/plugin/plugin.md | 70 ++ .../src/routes/build-routes.md | 53 ++ .../api-plugin-payment/src/schemas/money.md | 43 + .../api-plugin-payment/src/schemas/options.md | 50 + .../src/schemas/routes/capture-intent.md | 46 + .../src/schemas/routes/create-intent.md | 56 ++ .../src/schemas/routes/empty-body.md | 42 + .../src/schemas/routes/intent-id-param.md | 39 + .../src/schemas/routes/list-intents.md | 44 + .../src/schemas/routes/payment-intent.md | 48 + .../src/schemas/routes/refund.md | 55 ++ .../src/schemas/routes/webhook.md | 45 + .../src/services/payment-service.md | 76 ++ .../src/services/registry-augmentation.md | 47 + .../src/store/memory-store.md | 52 ++ .../src/store/payment-intent-store.md | 56 ++ .../api/api-plugin-payment/src/types/types.md | 56 ++ .../src/webhook/verify-webhook.md | 64 ++ .../api/api-plugin-rate-limit/README.md | 133 +++ .../src/error-codes/error-codes.md | 98 ++ .../src/headers/headers.md | 94 ++ .../src/middleware/context-augmentation.md | 66 ++ .../src/middleware/rate-limit.md | 101 ++ .../src/otel/instruments.md | 93 ++ .../src/path-matcher/path-matcher.md | 86 ++ .../src/plugin/plugin.md | 100 ++ .../src/schemas/options.md | 87 ++ .../src/services/rate-limit-service.md | 122 +++ .../src/services/registry-augmentation.md | 73 ++ .../api-plugin-rate-limit/src/types/types.md | 108 +++ .../api-stack/api/api-plugin-search/README.md | 116 +++ .../src/analyzer/analyzer.md | 118 +++ .../src/error-codes/error-codes.md | 96 ++ .../api-plugin-search/src/otel/instruments.md | 105 +++ .../api-plugin-search/src/plugin/plugin.md | 94 ++ .../src/routes/build-routes.md | 97 ++ .../api-plugin-search/src/schemas/options.md | 82 ++ .../api-plugin-search/src/schemas/schemas.md | 112 +++ .../api-plugin-search/src/service/service.md | 137 +++ .../src/services/registry-augmentation.md | 83 ++ .../api/api-plugin-search/src/types/types.md | 88 ++ docs/api-stack/api/api-plugin-site/README.md | 101 ++ .../docs/middleware-integration.md | 112 +++ .../src/error-codes/error-codes.md | 61 ++ .../integration/middleware-recommendations.md | 92 ++ .../src/middleware/domain-resolver.md | 54 ++ .../api-plugin-site/src/otel/instruments.md | 63 ++ .../api/api-plugin-site/src/plugin/plugin.md | 66 ++ .../src/routes/private-routes.md | 53 ++ .../src/routes/public-routes.md | 43 + .../api/api-plugin-site/src/schemas/domain.md | 48 + .../api-plugin-site/src/schemas/options.md | 54 ++ .../api/api-plugin-site/src/schemas/push.md | 56 ++ .../api/api-plugin-site/src/schemas/site.md | 69 ++ .../api-plugin-site/src/service/db-port.md | 48 + .../src/service/domain-resolver.md | 69 ++ .../src/service/normalize-domain.md | 44 + .../api/api-plugin-site/src/service/site.md | 78 ++ .../src/services/registry-augmentation.md | 58 ++ .../api/api-plugin-site/src/types/types.md | 51 + docs/api-stack/api/api-plugin-sse/README.md | 109 +++ .../api-plugin-sse/src/buffer/ring-buffer.md | 66 ++ .../src/error-codes/error-codes.md | 73 ++ .../api-plugin-sse/src/fanout/in-process.md | 71 ++ .../api-plugin-sse/src/formatter/format.md | 57 ++ .../api/api-plugin-sse/src/formatter/parse.md | 61 ++ .../src/middleware/sse-handler.md | 72 ++ .../api-plugin-sse/src/otel/instruments.md | 70 ++ .../api/api-plugin-sse/src/plugin/plugin.md | 73 ++ .../src/registry/service-registry.md | 60 ++ .../api/api-plugin-sse/src/schemas/event.md | 57 ++ .../api/api-plugin-sse/src/schemas/options.md | 75 ++ .../api-plugin-sse/src/services/service.md | 93 ++ .../api-stack/api/api-plugin-tenant/README.md | 121 +++ .../src/error-codes/error-codes.md | 92 ++ .../src/middleware/tenant.md | 86 ++ .../api-plugin-tenant/src/otel/instruments.md | 83 ++ .../src/plugin/build-resolver.md | 87 ++ .../api-plugin-tenant/src/plugin/plugin.md | 100 ++ .../api-plugin-tenant/src/routes/routes.md | 85 ++ .../api-plugin-tenant/src/schemas/options.md | 82 ++ .../api-plugin-tenant/src/schemas/routes.md | 99 ++ .../src/services/registry-augmentation.md | 78 ++ .../src/services/tenant-service.md | 88 ++ .../api/api-plugin-tenant/src/store/memory.md | 82 ++ .../api/api-plugin-tenant/src/store/store.md | 94 ++ .../api/api-plugin-tenant/src/types/types.md | 95 ++ docs/api-stack/api/api-plugin-user/README.md | 203 ++++ .../src/error-codes/error-codes.md | 87 ++ .../api-plugin-user/src/otel/instruments.md | 76 ++ .../api/api-plugin-user/src/plugin/plugin.md | 87 ++ .../src/routes/build-routes.md | 80 ++ .../api-plugin-user/src/routes/delete-me.md | 68 ++ .../api/api-plugin-user/src/routes/get-me.md | 57 ++ .../api-plugin-user/src/routes/patch-me.md | 58 ++ .../api/api-plugin-user/src/schema/schema.md | 96 ++ .../api-plugin-user/src/schemas/options.md | 77 ++ .../src/schemas/user-profile.md | 110 +++ .../src/services/registry-augmentation.md | 70 ++ .../src/services/user-service.md | 86 ++ .../api/api-plugin-user/src/types/types.md | 86 ++ docs/api-stack/api/api-plugin-vault/README.md | 166 ++++ .../src/error-codes/error-codes.md | 97 ++ .../api-plugin-vault/src/otel/instruments.md | 107 +++ .../api/api-plugin-vault/src/plugin/plugin.md | 93 ++ .../api/api-plugin-vault/src/plugin/unlock.md | 98 ++ .../src/routes/build-routes.md | 103 ++ .../api/api-plugin-vault/src/schema/schema.md | 97 ++ .../api-plugin-vault/src/schemas/options.md | 93 ++ .../src/schemas/vault-item.md | 114 +++ .../src/services/registry-augmentation.md | 79 ++ .../src/services/vault-service.md | 128 +++ .../api/api-plugin-vault/src/types/types.md | 119 +++ .../api/api-plugin-webhook/README.md | 121 +++ .../src/dead-letter/dead-letter.md | 68 ++ .../src/dead-letter/memory.md | 52 ++ .../src/error-codes/error-codes.md | 61 ++ .../src/otel/instruments.md | 65 ++ .../api-plugin-webhook/src/plugin/plugin.md | 59 ++ .../src/routes/build-routes.md | 51 + .../src/schemas/endpoint.md | 68 ++ .../api-plugin-webhook/src/schemas/options.md | 47 + .../src/schemas/routes/routes.md | 67 ++ .../src/services/registry-augmentation.md | 52 ++ .../src/services/webhook-service.md | 74 ++ .../src/store/endpoint-store.md | 61 ++ .../api-plugin-webhook/src/store/memory.md | 59 ++ .../api/api-plugin-webhook/src/types/types.md | 74 ++ docs/api-stack/api/api-plugin/README.md | 119 +++ .../api/api-plugin/src/context/context.md | 111 +++ .../api/api-plugin/src/define/define.md | 96 ++ .../api-plugin/src/error-codes/error-codes.md | 92 ++ .../src/hook-executor/hook-executor.md | 104 +++ .../api/api-plugin/src/registry/registry.md | 144 +++ .../src/service-registry/service-registry.md | 110 +++ .../api/api-plugin/src/topo-sort/topo-sort.md | 96 ++ .../api/api-plugin/src/types/api-plugin.md | 90 ++ docs/api-stack/api/api-rate-limit/README.md | 101 ++ .../src/error-codes/error-codes.md | 77 ++ .../src/instruments/instruments.md | 73 ++ .../src/middleware/middleware.md | 108 +++ .../api-rate-limit/src/selector/selector.md | 85 ++ .../src/store/memory-store/memory-store.md | 88 ++ .../src/store/store-like/store-like.md | 83 ++ docs/api-stack/api/api-rbac/README.md | 85 ++ .../api-rbac/src/error-codes/error-codes.md | 94 ++ .../api-rbac/src/instruments/instruments.md | 115 +++ .../api/api-rbac/src/middleware/middleware.md | 120 +++ .../api/api-rbac/src/registry/registry.md | 114 +++ docs/api-stack/api/api-rbac/src/spec/spec.md | 99 ++ docs/api-stack/api/api-router-hono/README.md | 62 ++ .../api-router-hono/src/adapter/adapter.md | 64 ++ .../src/blue-green-slot/blue-green-slot.md | 63 ++ .../src/error-codes/error-codes.md | 52 ++ .../middleware-adapter/middleware-adapter.md | 65 ++ .../api-router-hono/src/pipeline/pipeline.md | 130 +++ .../api/api-router-in-memory/README.md | 74 ++ .../src/adapter/adapter.md | 69 ++ .../src/blue-green-slot/blue-green-slot.md | 64 ++ .../src/error-codes/error-codes.md | 66 ++ .../src/pipeline/pipeline.md | 68 ++ .../src/testing/testing.md | 53 ++ .../api/api-router-worker-bridge/README.md | 78 ++ .../src/bridge/bridge.md | 84 ++ .../src/error-codes/error-codes.md | 64 ++ .../src/marshal-request/marshal-request.md | 82 ++ .../src/marshal-response/marshal-response.md | 77 ++ .../src/streaming/streaming.md | 66 ++ .../src/testing/testing.md | 69 ++ docs/api-stack/api/api-router/README.md | 98 ++ .../api-router/src/error-codes/error-codes.md | 81 ++ .../src/middleware/insertion-point.md | 83 ++ .../api-router/src/middleware/middleware.md | 88 ++ .../api/api-router/src/request/request.md | 88 ++ .../api/api-router/src/response/response.md | 81 ++ .../api-router/src/route-match/route-match.md | 74 ++ .../src/route-options/route-options.md | 92 ++ .../api/api-router/src/router/router.md | 110 +++ .../api-stack/api/api-router/src/slot/slot.md | 98 ++ .../api/api-router/src/testing/conformance.md | 91 ++ .../pipeline-router-conformance.md | 115 +++ docs/api-stack/api/api-saga/README.md | 87 ++ .../api-saga/src/compensation/compensation.md | 126 +++ .../api-saga/src/error-codes/error-codes.md | 107 +++ .../api/api-saga/src/events/events.md | 113 +++ .../api-saga/src/idempotency/idempotency.md | 95 ++ .../api-saga/src/instruments/instruments.md | 108 +++ .../src/orchestrator/compensate-runner.md | 111 +++ .../api-saga/src/orchestrator/orchestrator.md | 151 +++ .../api-saga/src/orchestrator/step-runner.md | 114 +++ .../api-saga/src/persistence/persistence.md | 117 +++ .../api/api-saga/src/recovery/recovery.md | 106 +++ .../src/registry/participant-registry.md | 137 +++ .../api/api-saga/src/state/state-machine.md | 95 ++ .../api/api-saga/src/tenant/cross-tenant.md | 84 ++ .../api/api-saga/src/testing/testing.md | 89 ++ .../api/api-sandbox-permissions/README.md | 99 ++ .../src/budget/budget.md | 108 +++ .../src/checker/capability/capability.md | 117 +++ .../src/checker/checker.md | 118 +++ .../src/checker/fetch/fetch.md | 94 ++ .../src/checker/fs/fs.md | 104 +++ .../src/error-codes/error-codes.md | 96 ++ .../src/instruments/instruments.md | 83 ++ .../src/policy/policy.md | 127 +++ .../testing/run-permissions-conformance.md | 90 ++ .../api/api-sandbox-vm-host-bridge/README.md | 95 ++ .../src/bridge/bridge.md | 113 +++ .../src/error-codes/error-codes.md | 89 ++ .../src/instruments/instruments.md | 84 ++ .../src/lifecycle/lifecycle.md | 81 ++ .../src/marshal/marshal-request.md | 84 ++ .../src/marshal/marshal-response.md | 78 ++ .../src/route-discovery/route-discovery.md | 98 ++ .../vm-host-bridge-conformance.md | 82 ++ docs/api-stack/api/api-sandbox-vm/README.md | 92 ++ .../src/error-codes/error-codes.md | 92 ++ .../globals/frozen-globals/frozen-globals.md | 95 ++ .../api-sandbox-vm/src/otel/instruments.md | 96 ++ .../api-sandbox-vm/src/permissions/checker.md | 106 +++ .../src/proxies/fetch-proxy/fetch-proxy.md | 98 ++ .../src/proxies/fs-proxy/fs-proxy.md | 100 ++ .../install-capability-proxies.md | 99 ++ .../api/api-sandbox-vm/src/sandbox/sandbox.md | 127 +++ .../src/testing/run-vm-conformance.md | 100 ++ .../api-sandbox-wasm-host-bridge/README.md | 73 ++ .../src/abi-direct/marshal/marshal.md | 91 ++ .../src/abi-direct/memory/memory.md | 79 ++ .../src/abi-direct/memory/trap-classifier.md | 66 ++ .../src/abi-direct/wasm-abi/abi-validator.md | 65 ++ .../src/abi-direct/wasm-abi/abi.md | 53 ++ .../src/abi-wasi-stdio/wasi-stdio-validate.md | 101 ++ .../src/bridge/bridge-direct.md | 102 ++ .../src/bridge/bridge-marshal.md | 107 +++ .../src/bridge/bridge-wasi-stdio.md | 122 +++ .../src/bridge/bridge.md | 78 ++ .../src/error-codes/error-codes.md | 82 ++ .../src/instruments/instruments.md | 67 ++ .../src/lifecycle/lifecycle.md | 74 ++ .../src/route-discovery/route-discovery.md | 52 ++ .../wasm-host-bridge-conformance.md | 64 ++ .../src/wasi-stdio/wasi-stdio-frame.md | 153 +++ .../src/wasi-stdio/wasi-stdio-imports.md | 111 +++ .../src/wasi-stdio/wasi-stdio-lifecycle.md | 106 +++ .../src/wasi-stdio/wasi-stdio-memory-ref.md | 83 ++ .../src/wasi-stdio/wasi-stdio-routes.md | 94 ++ .../src/wasi-stdio/wasi-stdio-runner.md | 140 +++ .../src/wasi-stdio/wasi-stdio-streams.md | 101 ++ docs/api-stack/api/api-sandbox-wasm/README.md | 101 ++ .../src/error-codes/error-codes.md | 86 ++ .../install-capability-imports.md | 81 ++ .../api/api-sandbox-wasm/src/otel/otel.md | 71 ++ .../api-sandbox-wasm/src/outbound/outbound.md | 72 ++ .../api/api-sandbox-wasm/src/policy/policy.md | 76 ++ .../api-sandbox-wasm/src/preopens/preopens.md | 71 ++ .../api-sandbox-wasm/src/sandbox/sandbox.md | 79 ++ .../src/testing/run-wasm-conformance.md | 69 ++ .../api/api-sandbox-wasm/src/wasi/wasi.md | 74 ++ docs/api-stack/api/api-schemas/README.md | 72 ++ .../api/api-schemas/src/admin/health.md | 85 ++ .../api/api-schemas/src/admin/ping.md | 63 ++ .../api/api-schemas/src/admin/status.md | 60 ++ .../api/api-schemas/src/auth/context.md | 69 ++ .../api/api-schemas/src/auth/login.md | 87 ++ .../api/api-schemas/src/auth/logout.md | 65 ++ .../api/api-schemas/src/auth/refresh.md | 67 ++ .../api/api-schemas/src/auth/register.md | 74 ++ .../api-schemas/src/common/error-envelope.md | 91 ++ .../api/api-schemas/src/common/filter.md | 81 ++ .../api/api-schemas/src/common/id-param.md | 62 ++ .../api/api-schemas/src/common/pagination.md | 79 ++ .../api/api-schemas/src/common/sort.md | 74 ++ .../api/api-schemas/src/common/timestamps.md | 71 ++ .../api-schemas/src/events/domain-event.md | 71 ++ .../api/api-schemas/src/events/envelope.md | 69 ++ .../api/api-schemas/src/events/metadata.md | 64 ++ .../src/helpers/to-suaveplan-error.md | 74 ++ docs/api-stack/api/api-secrets-bun/README.md | 136 +++ .../api-secrets-bun/src/adapter/adapter.md | 121 +++ .../src/allowlist/allowlist.md | 73 ++ .../descriptor-builder/descriptor-builder.md | 93 ++ .../src/error-codes/error-codes.md | 86 ++ .../api-secrets-bun/src/otel/instruments.md | 75 ++ docs/api-stack/api/api-secrets-env/README.md | 134 +++ .../api-secrets-env/src/adapter/adapter.md | 113 +++ .../descriptor-builder/descriptor-builder.md | 103 ++ .../src/error-codes/error-codes.md | 91 ++ .../api-stack/api/api-secrets-vault/README.md | 108 +++ .../api-secrets-vault/src/adapter/adapter.md | 137 +++ .../src/allowlist/allowlist.md | 79 ++ .../src/error-codes/error-codes.md | 89 ++ .../src/from-vault/from-vault.md | 117 +++ .../api-secrets-vault/src/otel/instruments.md | 88 ++ .../api/api-secrets-vault/src/types/types.md | 106 +++ .../api-secrets-vault/src/watcher/watcher.md | 113 +++ .../api/api-secrets-worker-proxy/README.md | 82 ++ .../src/error-codes/error-codes.md | 76 ++ .../src/main-side/main-side.md | 76 ++ .../src/redaction/redaction.md | 75 ++ .../src/testing/testing.md | 82 ++ .../src/worker-side/worker-side.md | 75 ++ docs/api-stack/api/api-secrets/README.md | 71 ++ .../src/capability-id/capability-id.md | 56 ++ .../api-secrets/src/descriptor/descriptor.md | 71 ++ .../src/error-codes/error-codes.md | 62 ++ .../api-secrets/src/redaction/redaction.md | 59 ++ .../src/secrets-like/secrets-like.md | 58 ++ .../api-secrets/src/testing/conformance.md | 68 ++ docs/api-stack/api/api-sse-bun/README.md | 142 +++ .../src/compression/compression.md | 85 ++ .../api-sse-bun/src/engine/bun-sse-engine.md | 108 +++ .../src/error-codes/error-codes.md | 78 ++ .../src/event-buffer/event-buffer.md | 86 ++ .../api-sse-bun/src/handshake/handshake.md | 95 ++ .../src/instruments/instruments.md | 81 ++ .../api-sse-bun/src/keep-alive/keep-alive.md | 85 ++ .../src/last-event-id/last-event-id.md | 73 ++ .../api/api-sse-bun/src/limits/tenant-cap.md | 75 ++ .../api/api-sse-bun/src/options/options.md | 91 ++ .../api/api-sse-bun/src/stream/sse-stream.md | 72 ++ .../src/subscription/subscription-bus.md | 94 ++ .../api-sse-bun/src/testing/conformance.md | 81 ++ docs/api-stack/api/api-sse/README.md | 69 ++ .../api/api-sse/src/broker/broker.md | 67 ++ .../src/capability-id/capability-id.md | 47 + .../connection-registry.md | 67 ++ .../api/api-sse/src/connection/connection.md | 64 ++ .../api-sse/src/error-codes/error-codes.md | 65 ++ .../src/error-codes/production-throws.md | 60 ++ docs/api-stack/api/api-sse/src/event/event.md | 52 ++ .../src/replay-buffer/replay-buffer.md | 74 ++ .../api/api-sse/src/testing/conformance.md | 72 ++ .../api/api-tenant-provider-memory/README.md | 70 ++ .../src/error-codes/error-codes.md | 79 ++ .../src/provider/provider.md | 111 +++ .../api/api-tenant-provider/README.md | 51 + .../src/capability-id/capability-id.md | 77 ++ .../api-tenant-provider/src/chain/chain.md | 128 +++ .../src/error-codes/error-codes.md | 86 ++ .../src/pagination/pagination.md | 93 ++ .../src/provider/provider.md | 125 +++ .../src/tenant-record/tenant-record.md | 95 ++ .../src/testing/conformance.md | 88 ++ .../api/api-tenant-resolver-header/README.md | 102 ++ .../src/error-codes/error-codes.md | 86 ++ .../src/instruments/instruments.md | 74 ++ .../src/options/options.md | 91 ++ .../src/resolver/resolver.md | 108 +++ .../src/trust/trust.md | 86 ++ .../src/validate/validate.md | 75 ++ .../api/api-tenant-resolver-jwt/README.md | 73 ++ .../src/error-codes/error-codes.md | 85 ++ .../src/options/options.md | 81 ++ .../src/resolver/resolver.md | 95 ++ .../api-tenant-resolver-subdomain/README.md | 88 ++ .../src/error-codes/error-codes.md | 84 ++ .../src/forwarded/forwarded.md | 83 ++ .../src/options/options.md | 84 ++ .../src/otel/instruments.md | 76 ++ .../src/resolver/resolver.md | 100 ++ .../src/validate/validate.md | 78 ++ docs/api-stack/api/api-tenant/README.md | 188 ++++ .../api/api-tenant/src/cache/cache.md | 86 ++ .../api/api-tenant/src/context/context.md | 86 ++ .../api-tenant/src/error-codes/error-codes.md | 83 ++ .../api/api-tenant/src/lifecycle/lifecycle.md | 112 +++ .../api-tenant/src/middleware/middleware.md | 121 +++ .../src/middleware/require-feature.md | 61 ++ .../src/middleware/require-plugin.md | 69 ++ .../api-tenant/src/rate-limit/rate-limit.md | 100 ++ .../api/api-tenant/src/resolver/resolver.md | 91 ++ .../api/api-tenant/src/storage/storage.md | 95 ++ .../api/api-tenant/src/types/tenant.md | 96 ++ docs/api-stack/api/api-types/README.md | 105 +++ docs/api-stack/api/api-types/src/auth/auth.md | 66 ++ .../src/capabilities/capabilities.md | 81 ++ docs/api-stack/api/api-types/src/db/db.md | 56 ++ .../api/api-types/src/errors/errors.md | 53 ++ .../api/api-types/src/graphql/graphql.md | 50 + .../api-types/src/instruments/instruments.md | 53 ++ .../api/api-types/src/lifecycle/lifecycle.md | 62 ++ .../api/api-types/src/manifest/manifest.md | 53 ++ .../src/pipeline-events/pipeline-events.md | 106 +++ .../src/plugin-context/plugin-context.md | 57 ++ .../api/api-types/src/principal/principal.md | 59 ++ .../src/rollback-journal/rollback-journal.md | 56 ++ .../api/api-types/src/router/router.md | 99 ++ docs/api-stack/api/api-types/src/saga/saga.md | 64 ++ .../src/sandbox-bridge/sandbox-bridge.md | 92 ++ .../src/sandbox-bridge/wasi-stdio-protocol.md | 160 ++++ .../api/api-types/src/secrets/secrets.md | 54 ++ docs/api-stack/api/api-types/src/sse/sse.md | 50 + .../src/tenant-resolver/tenant-resolver.md | 66 ++ .../api/api-types/src/tenant/tenant.md | 52 ++ .../api/api-types/src/twopc/twopc.md | 60 ++ .../api-types/src/worker-rpc/worker-rpc.md | 56 ++ docs/api-stack/api/api-types/src/ws/ws.md | 54 ++ docs/api-stack/api/api-worker-host/README.md | 72 ++ .../src/bootstrap/bootstrap.md | 100 ++ .../capability-proxies/capability-proxies.md | 82 ++ .../src/crash-detection/crash-detection.md | 92 ++ .../src/error-codes/error-codes.md | 88 ++ .../src/lifecycle/lifecycle.md | 95 ++ .../protocol-extension/protocol-extension.md | 99 ++ .../api-worker-host/src/testing/testing.md | 92 ++ docs/api-stack/api/api-worker-rpc/README.md | 147 +++ .../src/abort-forwarding/abort-forwarding.md | 81 ++ .../src/backpressure/backpressure.md | 82 ++ .../api/api-worker-rpc/src/client/client.md | 99 ++ .../src/client/cloneable-guard.md | 79 ++ .../src/correlation/correlation.md | 90 ++ .../src/error-codes/error-codes.md | 71 ++ .../error-reconstruction.md | 90 ++ .../api-worker-rpc/src/protocol/protocol.md | 93 ++ .../api/api-worker-rpc/src/server/server.md | 101 ++ .../api-worker-rpc/src/streaming/streaming.md | 101 ++ .../api-worker-rpc/src/testing/conformance.md | 75 ++ .../api/api-worker-rpc/src/testing/testing.md | 87 ++ .../api/api-ws-broker-in-memory/README.md | 86 ++ .../src/broker/broker.md | 123 +++ .../src/error-codes/error-codes.md | 94 ++ .../src/options/options.md | 74 ++ .../src/testing/testing.md | 113 +++ .../api/api-ws-broker-redis/README.md | 162 ++++ .../api-ws-broker-redis/src/broker/broker.md | 130 +++ .../src/error-codes/error-codes.md | 96 ++ .../src/event-buffer/event-buffer.md | 99 ++ .../api-ws-broker-redis/src/health/health.md | 87 ++ .../src/instruments/instruments.md | 106 +++ .../src/options/options.md | 95 ++ .../src/publish/publish.md | 86 ++ .../src/reconnect/reconnect.md | 90 ++ .../src/resp-client/resp-client.md | 105 +++ .../src/subscribe/subscribe.md | 96 ++ docs/api-stack/api/api-ws-bun/README.md | 115 +++ .../src/backpressure/backpressure.md | 60 ++ .../api-ws-bun/src/engine/bun-ws-engine.md | 89 ++ .../api-ws-bun/src/error-codes/error-codes.md | 63 ++ .../api/api-ws-bun/src/handshake/handshake.md | 65 ++ .../api-ws-bun/src/handshake/subprotocol.md | 49 + .../api/api-ws-bun/src/heartbeat/heartbeat.md | 80 ++ .../api-ws-bun/src/instruments/instruments.md | 63 ++ .../api/api-ws-bun/src/limits/tenant-cap.md | 58 ++ .../api/api-ws-bun/src/options/options.md | 66 ++ .../src/principal/principal-expiry.md | 80 ++ .../api-ws-bun/src/reconnect/event-buffer.md | 57 ++ .../src/reconnect/reconnect-token.md | 66 ++ .../src/registry/connection-registry.md | 56 ++ .../src/subscription/subscription-bus.md | 58 ++ .../src/testing/conformance-binding.md | 63 ++ docs/api-stack/api/api-ws/README.md | 71 ++ .../api-ws/src/backpressure/backpressure.md | 74 ++ .../api-stack/api/api-ws/src/broker/broker.md | 81 ++ .../api-ws/src/capability-id/capability-id.md | 73 ++ .../connection-registry.md | 86 ++ .../api/api-ws/src/connection/connection.md | 77 ++ .../api/api-ws/src/envelope/envelope.md | 78 ++ .../api/api-ws/src/error-codes/error-codes.md | 69 ++ .../api/api-ws/src/heartbeat/heartbeat.md | 85 ++ .../src/reconnect-token/reconnect-token.md | 86 ++ .../src/subscription-bus/subscription-bus.md | 103 ++ .../api/api-ws/src/testing/conformance.md | 88 ++ docs/api-stack/api/api/README.md | 172 ++++ docs/api-stack/api/api/src/app/app.md | 127 +++ .../api/api/src/app/health-routes.md | 80 ++ docs/api-stack/api/api/src/app/migrations.md | 62 ++ .../api/api/src/app/request-context.md | 94 ++ docs/api-stack/api/api/src/app/timeout.md | 70 ++ .../api-stack/api/api/src/builder/assemble.md | 93 ++ docs/api-stack/api/api/src/builder/builder.md | 101 ++ .../api/api/src/builder/cors-bridge.md | 62 ++ docs/api-stack/api/api/src/config/config.md | 106 +++ docs/api-stack/api/api/src/config/loader.md | 87 ++ .../api-stack/api/api/src/config/validator.md | 80 ++ .../api/api/src/error-codes/error-codes.md | 80 ++ .../api/src/event-integration/event-bridge.md | 85 ++ .../api-stack/api/api/src/middleware/chain.md | 99 ++ .../api/api/src/middleware/composition.md | 78 ++ docs/api-stack/api/api/src/middleware/cors.md | 80 ++ .../api/api/src/middleware/error-handler.md | 80 ++ .../api/api/src/middleware/logger.md | 89 ++ .../api/api/src/middleware/request-id.md | 77 ++ .../api/src/services/registry-augmentation.md | 116 +++ docs/api-stack/api/api/src/types/api.md | 102 ++ .../api/create-suaveplan-plugin/README.md | 85 ++ .../src/bin/create-suaveplan-plugin.md | 61 ++ .../src/error-codes.md | 73 ++ .../src/generator/generator.md | 69 ++ .../src/prompt/prompt.md | 78 ++ .../src/templates/templates.md | 81 ++ .../isolated-sqlite-rest-only/README.md | 16 + .../sandboxed-none-rest-only/README.md | 16 + .../snapshots/trusted-postgres-full/README.md | 16 + .../api/wasm-compiler-javy/README.md | 50 + .../src/abi-shim/abi-shim-polyfills.md | 47 + .../src/abi-shim/abi-shim.md | 78 ++ .../api/wasm-compiler-javy/src/bin/cli.md | 57 ++ .../wasm-compiler-javy/src/bundle/bundle.md | 56 ++ .../wasm-compiler-javy/src/compile/compile.md | 66 ++ .../src/error-codes/error-codes.md | 65 ++ .../src/instruments/instruments.md | 58 ++ .../src/javy/javy-invoke.md | 57 ++ .../src/javy/javy-locate.md | 55 ++ .../src/manifest/manifest.md | 58 ++ .../src/route-extract/route-extract.md | 49 + .../wasm-compiler-conformance.md | 66 ++ .../src/validate/abi-validate.md | 50 + docs/commerce/README.md | 28 + docs/commerce/_intro.md | 3 + docs/commerce/booking/README.md | 13 + docs/commerce/booking/_intro.md | 1 + docs/commerce/booking/booking/README.md | 220 +++++ .../src/availability/resolver/resolver.md | 78 ++ .../src/availability/strategies/strategies.md | 75 ++ .../booking/src/conflict/detector/detector.md | 90 ++ .../src/conflict/exact-match/exact-match.md | 61 ++ .../provider-overlap/provider-overlap.md | 62 ++ .../conflict/range-overlap/range-overlap.md | 65 ++ .../conflict/slot-capacity/slot-capacity.md | 73 ++ .../booking/booking/src/core/engine/engine.md | 104 +++ .../booking/src/core/event-bus/event-bus.md | 80 ++ .../src/core/state-machine/state-machine.md | 82 ++ .../domains/accommodation/accommodation.md | 77 ++ .../src/domains/activities/activities.md | 74 ++ .../src/domains/appointments/appointments.md | 75 ++ .../src/domains/resources/resources.md | 83 ++ .../booking/src/domains/seats/seats.md | 77 ++ .../booking/booking/src/domains/shared.md | 74 ++ .../src/domains/transport/transport.md | 79 ++ .../booking/src/error-codes/error-codes.md | 94 ++ .../booking/booking/src/hooks/hooks.md | 94 ++ .../src/pricing/calculator/calculator.md | 71 ++ .../booking/src/pricing/dynamic/dynamic.md | 68 ++ .../booking/src/pricing/seasonal/seasonal.md | 64 ++ .../src/rules/conditions/conditions.md | 71 ++ .../booking/src/rules/evaluator/evaluator.md | 98 ++ .../booking/src/schemas/booking.schema.md | 71 ++ .../booking/src/schemas/config.schema.md | 69 ++ .../src/temporal/recurrence/recurrence.md | 77 ++ .../booking/src/temporal/slots/slots.md | 63 ++ .../booking/src/temporal/windows/windows.md | 79 ++ .../booking/src/types/bookable.types.md | 68 ++ .../booking/src/types/booking-hooks.types.md | 73 ++ .../booking/src/types/booking.types.md | 87 ++ .../booking/src/types/capacity.types.md | 76 ++ .../booking/booking/src/types/config.types.md | 75 ++ .../booking/booking/src/types/events.types.md | 73 ++ .../booking/booking/src/types/layout.types.md | 63 ++ .../booking/src/types/pricing.types.md | 80 ++ .../booking/booking/src/types/rules.types.md | 73 ++ .../booking/src/types/temporal.types.md | 83 ++ .../booking/booking/src/utils/utils.md | 74 ++ docs/commerce/contacts/README.md | 16 + docs/commerce/contacts/_intro.md | 1 + .../contacts/api-plugin-contacts/README.md | 126 +++ .../src/context/context.md | 75 ++ .../src/error-codes/error-codes.md | 107 +++ .../src/otel/instruments.md | 92 ++ .../api-plugin-contacts/src/plugin/plugin.md | 79 ++ .../api-plugin-contacts/src/plugin/schema.md | 72 ++ .../src/repositories/contact-repository.md | 90 ++ .../src/repositories/group-repository.md | 91 ++ .../src/repositories/membership-repository.md | 73 ++ .../src/routes/contacts/build-routes.md | 61 ++ .../routes/contacts/contacts-bulk-routes.md | 66 ++ .../routes/contacts/contacts-crud-routes.md | 69 ++ .../src/routes/groups/build-routes.md | 65 ++ .../src/routes/groups/groups-crud-routes.md | 67 ++ .../routes/groups/groups-members-routes.md | 71 ++ .../src/routes/groups/groups-tree-routes.md | 67 ++ .../src/routes/shared/require-tenant.md | 69 ++ .../src/routes/shared/strip-undefined.md | 59 ++ .../src/schemas/contacts-schemas.md | 74 ++ .../src/schemas/groups-schemas.md | 78 ++ .../src/schemas/options.md | 66 ++ .../src/services/registry-augmentation.md | 73 ++ .../src/tree/build-tree.md | 70 ++ .../api-plugin-contacts/src/types/types.md | 74 ++ .../contacts/audience-rules/README.md | 111 +++ .../src/error-codes/error-codes.md | 93 ++ .../src/predicates/predicates.md | 78 ++ .../audience-rules/src/schemas/schemas.md | 96 ++ .../segment-evaluator/segment-evaluator.md | 120 +++ .../segment-refresher/segment-refresher.md | 103 ++ .../audience-rules/src/store/store.md | 93 ++ .../audience-rules/src/types/segment.types.md | 105 +++ docs/commerce/contacts/contacts/README.md | 120 +++ .../audience-resolver/audience-resolver.md | 83 ++ .../core/contact-manager/contact-manager.md | 99 ++ .../src/core/contact-merger/contact-merger.md | 92 ++ .../src/core/group-manager/group-manager.md | 100 ++ .../membership-manager/membership-manager.md | 95 ++ .../contacts/src/error-codes/error-codes.md | 86 ++ .../contact-exporter/contact-exporter.md | 78 ++ .../contact-importer/contact-importer.md | 110 +++ .../contacts/contacts/src/otel/instruments.md | 86 ++ .../contacts/contacts/src/schemas/schemas.md | 93 ++ .../src/stores/contact-store/contact-store.md | 93 ++ .../src/stores/group-store/group-store.md | 88 ++ .../membership-store/membership-store.md | 82 ++ .../contacts/contacts/src/tree/tree-utils.md | 94 ++ .../contacts/src/types/contact.types.md | 85 ++ .../contacts/src/types/group.types.md | 74 ++ .../contacts/src/types/membership.types.md | 80 ++ .../contacts/macos-contacts/README.md | 61 ++ .../src/applescript/applescript.md | 74 ++ .../macos-contacts/src/bridge/bridge.md | 115 +++ .../src/error-codes/error-codes.md | 89 ++ .../macos-contacts/src/executor/executor.md | 81 ++ .../macos-contacts/src/otel/instruments.md | 96 ++ .../macos-contacts/src/parser/parser.md | 71 ++ .../macos-contacts/src/schemas/schemas.md | 84 ++ .../src/types/macos-contacts.types.md | 91 ++ docs/communication/README.md | 46 + docs/communication/_intro.md | 3 + docs/communication/emails/README.md | 20 + docs/communication/emails/_intro.md | 1 + docs/communication/emails/campaigns/README.md | 94 ++ .../src/batch-planner/batch-planner.md | 53 ++ .../emails/campaigns/src/engine/engine.md | 60 ++ .../campaigns/src/error-codes/error-codes.md | 63 ++ .../src/state-machine/state-machine.md | 59 ++ .../emails/campaigns/src/store/store.md | 56 ++ .../campaigns/src/telemetry/telemetry.md | 58 ++ .../campaigns/src/types/campaign.types.md | 70 ++ .../emails/campaigns/src/workflow/workflow.md | 60 ++ .../emails/delivery-tracking/README.md | 106 +++ .../src/core/aggregator/aggregator.md | 59 ++ .../src/core/tracker/tracker.md | 74 ++ .../src/core/tracker/tracker.schemas.md | 52 ++ .../src/core/tracking-link/tracking-link.md | 59 ++ .../src/core/tracking-pixel/token-codec.md | 61 ++ .../src/core/tracking-pixel/tracking-pixel.md | 66 ++ .../src/core/webhook-parser/webhook-parser.md | 74 ++ .../src/errors/delivery-tracking-error.md | 67 ++ .../delivery-tracking/src/otel/instruments.md | 68 ++ .../src/stores/memory/memory-store.md | 58 ++ .../src/stores/surreal/surreal-store.md | 71 ++ docs/communication/emails/dmarc/README.md | 74 ++ .../emails/dmarc/src/decoders/gzip.md | 76 ++ .../emails/dmarc/src/decoders/xml.md | 69 ++ .../emails/dmarc/src/errors/dmarc-error.md | 84 ++ .../emails/dmarc/src/otel/dmarc-otel.md | 69 ++ .../emails/dmarc/src/parsers/aggregate.md | 108 +++ .../emails/dmarc/src/parsers/forensic.md | 89 ++ .../emails/domain-normalizer/README.md | 61 ++ .../src/core/aliases/aliases.md | 102 ++ .../src/core/matcher/matcher.md | 127 +++ .../src/core/normalizer/normalizer.md | 110 +++ .../src/errors/domain-normalizer-error.md | 92 ++ .../src/types/domain-normalizer.md | 86 ++ .../src/types/domain-normalizer.types.md | 88 ++ .../emails/email-processing/README.md | 121 +++ .../attachment-processor.md | 88 ++ .../src/calendar-parser/calendar-parser.md | 81 ++ .../src/cid-resolver/cid-resolver.md | 81 ++ .../src/data-extractor/data-extractor.md | 75 ++ .../dkim-canonicalize/dkim-canonicalize.md | 86 ++ .../src/dkim-verifier/dkim-verifier.md | 84 ++ .../src/dmarc-checker/dmarc-checker.md | 78 ++ .../src/error-codes/error-codes.md | 84 ++ .../email-processing/src/hooks/hooks.md | 99 ++ .../src/mime-utils/mime-utils.md | 87 ++ .../email-processing/src/parser/parser.md | 85 ++ .../src/spam-scorer/spam-scorer.md | 97 ++ .../src/spf-checker/spf-checker.md | 74 ++ .../src/telemetry/telemetry.md | 77 ++ .../src/thread-grouper/thread-grouper.md | 91 ++ .../emails/email-templates/README.md | 118 +++ .../components/email-button/email-button.md | 92 ++ .../email-container/email-container.md | 76 ++ .../components/email-divider/email-divider.md | 66 ++ .../components/email-footer/email-footer.md | 92 ++ .../components/email-heading/email-heading.md | 77 ++ .../src/components/email-image/email-image.md | 85 ++ .../components/email-layout/email-layout.md | 80 ++ .../src/components/email-link/email-link.md | 75 ++ .../src/components/email-text/email-text.md | 71 ++ .../src/error-codes/error-codes.md | 87 ++ .../email-templates/src/message/message.md | 96 ++ .../email-templates/src/renderer/renderer.md | 107 +++ .../src/telemetry/telemetry.md | 81 ++ .../src/template-builder/template-builder.md | 84 ++ .../template-registry/template-registry.md | 102 ++ .../src/templates/invoice/invoice.md | 93 ++ .../templates/notification/notification.md | 83 ++ .../password-reset/password-reset.md | 83 ++ .../templates/verification/verification.md | 83 ++ .../src/templates/welcome/welcome.md | 84 ++ .../emails/email-templates/src/theme/theme.md | 89 ++ .../emails/email-templates/src/vnode/vnode.md | 101 ++ docs/communication/emails/emailer/README.md | 89 ++ .../email-service/base-email-transport.md | 92 ++ .../src/core/email-service/email-service.md | 104 +++ .../emails/emailer/src/core/retry/retry.md | 96 ++ .../emailer/src/core/validate/validate.md | 81 ++ .../emailer/src/error-codes/error-codes.md | 88 ++ .../emails/emailer/src/fakes/fake-fetch.md | 76 ++ .../emailer/src/fakes/fake-smtp-client.md | 65 ++ .../emails/emailer/src/otel/metrics.md | 75 ++ .../emails/emailer/src/schemas/schemas.md | 89 ++ .../src/transports/dummy/dummy-transport.md | 96 ++ .../gmail-rest/gmail-rest-transport.md | 98 ++ .../transports/smtp/smtp-client-like.types.md | 82 ++ .../src/transports/smtp/smtp-transport.md | 86 ++ .../emails/emailer/src/types/emailer.types.md | 97 ++ .../emails/suppression/README.md | 79 ++ .../src/core/exporter/csv-exporter.md | 77 ++ .../src/core/exporter/json-exporter.md | 93 ++ .../src/core/importer/csv-importer.md | 85 ++ .../src/core/store/suppression-store.md | 136 +++ .../src/errors/suppression-error.md | 94 ++ .../src/types/suppression.types.md | 128 +++ .../suppression/src/utils/email-utils.md | 106 +++ docs/communication/messaging/README.md | 19 + docs/communication/messaging/_intro.md | 1 + .../messaging/discord-client/README.md | 100 ++ .../src/core/bot-client/discord-bot-client.md | 92 ++ .../src/core/webhook/discord-webhook.md | 94 ++ .../src/errors/discord-client-error.md | 84 ++ .../src/types/discord-client.types.md | 83 ++ .../discord-client/src/utils/http.md | 90 ++ .../discord-client/src/utils/rate-limit.md | 67 ++ .../messaging/imessage-adapter/README.md | 120 +++ .../src/adapter/imessage-adapter.md | 90 ++ .../src/error-codes/error-codes.md | 87 ++ .../src/fixtures/chat-db-fixture.md | 115 +++ .../imessage-adapter/src/otel/metrics.md | 68 ++ .../src/parser/imessage-parser.md | 73 ++ .../imessage-adapter/src/schemas/schemas.md | 80 ++ .../src/sqlite/bun-sqlite-reader.md | 76 ++ .../src/watcher/imessage-watcher.md | 103 ++ .../messaging/notification-channel/README.md | 117 +++ .../src/channels/delivery-channel.md | 66 ++ .../src/channels/email-channel.md | 59 ++ .../src/channels/in-app-channel.md | 67 ++ .../src/channels/push-channel.md | 65 ++ .../src/channels/sms-channel.md | 63 ++ .../src/channels/webhook-channel.md | 56 ++ .../src/digest/digest-channel.md | 57 ++ .../src/error-codes/error-codes.md | 62 ++ .../src/error-mapping/error-mapping.md | 57 ++ .../src/fakes/fake-fetch.md | 61 ++ .../notification-channel/src/hooks/hooks.md | 75 ++ .../notification-channel/src/otel/metrics.md | 67 ++ .../src/preferences/preference-manager.md | 74 ++ .../src/rate-limiter/channel-rate-limiter.md | 63 ++ .../src/retry/delivery-retry.md | 72 ++ .../src/router/notification-router.md | 89 ++ .../src/scheduler/notification-scheduler.md | 64 ++ .../src/schemas/schemas.md | 49 + .../src/templates/template-engine.md | 80 ++ .../messaging/slack-client/README.md | 87 ++ .../slack-client/src/client/classify.md | 57 ++ .../slack-client/src/client/retry-after.md | 52 ++ .../src/client/slack-api-client.md | 68 ++ .../src/error-codes/error-codes.md | 63 ++ .../slack-client/src/fakes/fake-fetch.md | 61 ++ .../slack-client/src/otel/metrics.md | 65 ++ .../slack-client/src/schemas/schemas.md | 55 ++ .../slack-client/src/webhook/slack-webhook.md | 66 ++ .../messaging/sms-providers/README.md | 117 +++ .../sms-providers/src/aws-sns/aws-sns.md | 87 ++ .../sms-providers/src/aws-sns/sigv4.md | 80 ++ .../sms-providers/src/crypto/default-hmac.md | 74 ++ .../src/error-codes/error-codes.md | 104 +++ .../messaging/sms-providers/src/http/http.md | 71 ++ .../sms-providers/src/keywords/keywords.md | 64 ++ .../src/messagebird/messagebird.md | 58 ++ .../messaging/sms-providers/src/otel/otel.md | 84 ++ .../sms-providers/src/plivo/plivo.md | 66 ++ .../sms-providers/src/registry/registry.md | 91 ++ .../sms-providers/src/twilio/twilio.md | 85 ++ .../sms-providers/src/types/provider.md | 85 ++ .../sms-providers/src/vonage/vonage.md | 71 ++ docs/communication/messaging/sms/README.md | 133 +++ .../src/delivery-tracker/delivery-tracker.md | 85 ++ .../sms/src/error-codes/error-codes.md | 110 +++ .../in-memory-provider/in-memory-provider.md | 101 ++ .../sms/src/legacy-errors/legacy-errors.md | 93 ++ .../src/legacy-metadata/legacy-metadata.md | 85 ++ .../messaging/sms/src/opt-out/opt-out.md | 87 ++ .../messaging/sms/src/otel/metrics.md | 98 ++ .../sms/src/rate-limiter/rate-limiter.md | 92 ++ .../messaging/sms/src/retry/retry.md | 93 ++ .../messaging/sms/src/routes/problem-json.md | 86 ++ .../messaging/sms/src/scheduler/scheduler.md | 97 ++ .../messaging/sms/src/schemas/schemas.md | 101 ++ .../messaging/sms/src/service/bus-map.md | 71 ++ .../sms/src/service/legacy-emitter.md | 88 ++ .../messaging/sms/src/service/sms-service.md | 119 +++ .../messaging/sms/src/templates/templates.md | 99 ++ .../messaging/sms/src/types/sms.types.md | 114 +++ .../messaging/sms/src/validation/phone.md | 70 ++ .../messaging/telegram-client/README.md | 92 ++ .../telegram-bot-client.md | 139 +++ .../src/errors/telegram-client-error.md | 99 ++ .../src/types/telegram-bot-config.md | 84 ++ .../src/types/telegram-client.types.md | 117 +++ .../telegram-client/src/utils/build-bodies.md | 94 ++ .../src/utils/classify-error.md | 94 ++ docs/communication/webhook-client/README.md | 13 + docs/communication/webhook-client/_intro.md | 1 + .../webhook-client/webhook-client/README.md | 104 +++ .../src/core/client/webhook-client.md | 115 +++ .../src/core/delivery/webhook-delivery.md | 98 ++ .../src/errors/webhook-client-error.md | 92 ++ .../src/types/webhook-client.types.md | 164 ++++ .../src/utils/payload-builder.md | 75 ++ .../webhook-client/src/utils/signature.md | 107 +++ docs/devtools/README.md | 51 + docs/devtools/_intro.md | 3 + docs/devtools/docker/README.md | 13 + docs/devtools/docker/_intro.md | 1 + docs/devtools/docker/docker-nvidia/README.md | 5 + docs/devtools/docs/README.md | 16 + docs/devtools/docs/_intro.md | 1 + docs/devtools/docs/compress-svg/README.md | 116 +++ .../src/core/compress-svg/compress-svg.md | 74 ++ .../docs/compress-svg/src/parser/svg/svg.md | 87 ++ .../plugins/cleanup-attrs/cleanup-attrs.md | 67 ++ .../collapse-groups/collapse-groups.md | 68 ++ .../convert-path-data/convert-path-data.md | 59 ++ .../convert-transforms/convert-transforms.md | 57 ++ .../src/plugins/mangle-ids/mangle-ids.md | 67 ++ .../remove-comments/remove-comments.md | 60 ++ .../plugins/remove-doctype/remove-doctype.md | 56 ++ .../remove-metadata/remove-metadata.md | 57 ++ .../docs/compress-svg/src/types/common.md | 102 ++ docs/devtools/docs/docs/README.md | 76 ++ .../docs/docs/src/discovery/discover.md | 86 ++ docs/devtools/docs/docs/src/errors/errors.md | 102 ++ .../docs/docs/src/graph/build-graph.md | 78 ++ .../docs/docs/src/graph/find-orphans.md | 82 ++ .../docs/src/hierarchy/build-hierarchy.md | 88 ++ .../docs/src/observability/observability.md | 89 ++ docs/devtools/docs/docs/src/parser/parse.md | 88 ++ docs/devtools/docs/docs/src/search/search.md | 91 ++ .../docs/docs/src/types/docs.types.md | 107 +++ docs/devtools/docs/pdf/README.md | 133 +++ docs/devtools/docs/pdf/src/colors/colors.md | 93 ++ .../pdf/src/content-stream/content-stream.md | 109 +++ .../src/divider-element/divider-element.md | 88 ++ .../src/document-builder/document-builder.md | 120 +++ .../docs/pdf/src/error-codes/error-codes.md | 106 +++ .../pdf/src/image-element/image-element.md | 108 +++ .../pdf/src/image-registry/image-registry.md | 81 ++ .../pdf/src/layout-engine/layout-engine.md | 97 ++ .../docs/pdf/src/pdf-writer/pdf-writer.md | 143 +++ .../src/render-pipeline/render-pipeline.md | 90 ++ .../docs/pdf/src/renderer/renderer.md | 120 +++ docs/devtools/docs/pdf/src/schemas/schemas.md | 104 +++ .../pdf/src/style-resolver/style-resolver.md | 86 ++ .../pdf/src/table-element/table-element.md | 124 +++ .../docs/pdf/src/telemetry/telemetry.md | 104 +++ .../invoice-template/invoice-template.md | 142 +++ .../receipt-template/receipt-template.md | 122 +++ .../report-template/report-template.md | 119 +++ .../docs/pdf/src/text-element/text-element.md | 113 +++ docs/devtools/docs/pdf/src/types/page-size.md | 86 ++ docs/devtools/docs/pdf/src/units/units.md | 91 ++ docs/devtools/docs/sitemap/README.md | 69 ++ .../src/core/builder/sitemap-builder.md | 152 +++ .../src/core/index-builder/index-builder.md | 117 +++ .../sitemap/src/core/parser/sitemap-parser.md | 127 +++ .../docs/sitemap/src/errors/sitemap-error.md | 103 ++ .../sitemap/src/schemas/sitemap.schema.md | 113 +++ .../docs/sitemap/src/utils/url-utils.md | 97 ++ docs/devtools/tooling/README.md | 28 + docs/devtools/tooling/_intro.md | 1 + docs/devtools/tooling/cli/README.md | 202 ++++ docs/devtools/tooling/cli/src/app/app.md | 120 +++ .../tooling/cli/src/command/command.md | 122 +++ .../devtools/tooling/cli/src/errors/errors.md | 171 ++++ .../tooling/cli/src/output/format/format.md | 93 ++ .../tooling/cli/src/output/table/table.md | 81 ++ .../devtools/tooling/cli/src/parser/parser.md | 92 ++ .../tooling/cli/src/progress/progress.md | 92 ++ .../devtools/tooling/cli/src/prompt/prompt.md | 95 ++ .../tooling/cli/src/spinner/spinner.md | 99 ++ docs/devtools/tooling/cli/src/style/style.md | 82 ++ docs/devtools/tooling/electrobun/README.md | 151 +++ .../src/bin/suaveplan-electrobun.md | 65 ++ .../tooling/electrobun/src/cli/cli.md | 100 ++ .../tooling/electrobun/src/config/config.md | 82 ++ .../electrobun/src/error-codes/error-codes.md | 93 ++ docs/devtools/tooling/electrobun/src/fs/fs.md | 104 +++ .../electrobun/src/generator/generator.md | 96 ++ .../tooling/electrobun/src/icons/icons.md | 91 ++ .../tooling/electrobun/src/prompts/prompts.md | 96 ++ .../tooling/electrobun/src/runner/runner.md | 97 ++ .../tooling/electrobun/src/schemas/schemas.md | 104 +++ .../electrobun/src/telemetry/telemetry.md | 93 ++ .../electrobun/src/templates/features.md | 85 ++ .../electrobun/src/templates/templates.md | 107 +++ .../electrobun/src/types/electrobun.types.md | 115 +++ .../tooling/install-agent-skills/README.md | 94 ++ .../assets/skills/ab-testing/SKILL.md | 46 + .../assets/skills/api-schemas/SKILL.md | 42 + .../assets/skills/audit-logging/SKILL.md | 48 + .../assets/skills/auth/SKILL.md | 47 + .../assets/skills/barcode/SKILL.md | 42 + .../assets/skills/bitpacker/SKILL.md | 43 + .../assets/skills/bytes/SKILL.md | 43 + .../assets/skills/cache/SKILL.md | 44 + .../assets/skills/cli/SKILL.md | 44 + .../assets/skills/compress-image/SKILL.md | 43 + .../assets/skills/compress-svg/SKILL.md | 43 + .../assets/skills/config/SKILL.md | 45 + .../assets/skills/crdt/SKILL.md | 45 + .../assets/skills/crypto-browser/SKILL.md | 43 + .../assets/skills/crypto-cipher/SKILL.md | 44 + .../assets/skills/crypto-curve/SKILL.md | 45 + .../assets/skills/crypto-hash/SKILL.md | 44 + .../assets/skills/crypto-keys/SKILL.md | 44 + .../assets/skills/crypto-sodium/SKILL.md | 43 + .../assets/skills/crypto-utils/SKILL.md | 44 + .../assets/skills/crypto-vault/SKILL.md | 47 + .../assets/skills/crypto/SKILL.md | 47 + .../assets/skills/data-masking/SKILL.md | 42 + .../assets/skills/datetime/SKILL.md | 43 + .../assets/skills/db-sqlite/SKILL.md | 44 + .../assets/skills/db/SKILL.md | 43 + .../assets/skills/dedup/SKILL.md | 42 + .../assets/skills/diff/SKILL.md | 42 + .../assets/skills/dmarc/SKILL.md | 42 + .../assets/skills/domain-normalizer/SKILL.md | 42 + .../assets/skills/env/SKILL.md | 43 + .../assets/skills/error/SKILL.md | 42 + .../assets/skills/etl/SKILL.md | 45 + .../assets/skills/event-sourcing/SKILL.md | 45 + .../assets/skills/events-metrics/SKILL.md | 45 + .../assets/skills/events-otel/SKILL.md | 44 + .../assets/skills/events-schema/SKILL.md | 45 + .../assets/skills/events-transport/SKILL.md | 44 + .../assets/skills/events/SKILL.md | 43 + .../assets/skills/exif/SKILL.md | 42 + .../assets/skills/feature-flags/SKILL.md | 45 + .../assets/skills/font-compress/SKILL.md | 44 + .../assets/skills/font-convert/SKILL.md | 43 + .../assets/skills/font-subset/SKILL.md | 44 + .../assets/skills/fsm/SKILL.md | 44 + .../assets/skills/i18n/SKILL.md | 43 + .../assets/skills/idempotency/SKILL.md | 44 + .../assets/skills/json/SKILL.md | 43 + .../assets/skills/jwt-tenant/SKILL.md | 44 + .../assets/skills/locale-data/SKILL.md | 43 + .../assets/skills/logger/SKILL.md | 44 + .../assets/skills/metadata/SKILL.md | 42 + .../assets/skills/migration/SKILL.md | 46 + .../assets/skills/mime/SKILL.md | 43 + .../assets/skills/noise/SKILL.md | 44 + .../assets/skills/oauth-client/SKILL.md | 43 + .../assets/skills/opentelemetry/SKILL.md | 43 + .../assets/skills/pagination/SKILL.md | 43 + .../assets/skills/password-formats/SKILL.md | 42 + .../assets/skills/permissions/SKILL.md | 44 + .../assets/skills/pick-plugins/SKILL.md | 93 ++ .../assets/skills/pseudo-random/SKILL.md | 43 + .../assets/skills/qrcode/SKILL.md | 42 + .../assets/skills/queue/SKILL.md | 43 + .../assets/skills/random/SKILL.md | 44 + .../assets/skills/rate-limiter/SKILL.md | 45 + .../assets/skills/readline/SKILL.md | 43 + .../assets/skills/retry/SKILL.md | 44 + .../assets/skills/schema-registry/SKILL.md | 43 + .../assets/skills/search/SKILL.md | 44 + .../assets/skills/security-codes/SKILL.md | 42 + .../assets/skills/serialize/SKILL.md | 43 + .../assets/skills/sitemap/SKILL.md | 42 + .../assets/skills/slsa/SKILL.md | 47 + .../assets/skills/storage-s3/SKILL.md | 45 + .../assets/skills/storage/SKILL.md | 44 + .../assets/skills/streams/SKILL.md | 43 + .../assets/skills/suppression/SKILL.md | 43 + .../assets/skills/surrealdb/SKILL.md | 45 + .../assets/skills/templates/SKILL.md | 43 + .../assets/skills/testing-dom/SKILL.md | 42 + .../assets/skills/testing-e2e/SKILL.md | 42 + .../testing-integration-garage-s3/SKILL.md | 42 + .../testing-integration-mailpit/SKILL.md | 42 + .../testing-integration-postgres/SKILL.md | 42 + .../skills/testing-integration-redis/SKILL.md | 42 + .../testing-integration-surrealdb/SKILL.md | 42 + .../testing-integration-typesense/SKILL.md | 42 + .../skills/testing-integration/SKILL.md | 42 + .../assets/skills/testing/SKILL.md | 42 + .../assets/skills/timing/SKILL.md | 44 + .../assets/skills/types/SKILL.md | 42 + .../assets/skills/typescript-config/SKILL.md | 42 + .../assets/skills/undo/SKILL.md | 45 + .../assets/skills/utils/SKILL.md | 43 + .../assets/skills/validation/SKILL.md | 44 + .../assets/skills/webhook-client/SKILL.md | 44 + .../install-agent-skills/src/apply/apply.md | 63 ++ .../install-agent-skills/src/detect/detect.md | 69 ++ .../install-agent-skills/src/error-codes.md | 78 ++ .../src/manifest-loader.md | 78 ++ .../install-agent-skills/src/plan/plan.md | 85 ++ .../install-agent-skills/src/plugin/plugin.md | 88 ++ .../src/post-install/post-install.md | 70 ++ .../src/prompts/prompts.md | 75 ++ .../src/types/answers.types.md | 74 ++ docs/devtools/tooling/installer/README.md | 171 ++++ .../installer/src/bin/suaveplan-install.md | 71 ++ .../tooling/installer/src/error-codes.md | 79 ++ .../tooling/installer/src/errors/errors.md | 66 ++ .../tooling/installer/src/fs/disk-fs.md | 83 ++ .../tooling/installer/src/fs/installer-fs.md | 76 ++ .../tooling/installer/src/fs/memory-fs.md | 82 ++ .../tooling/installer/src/host/apply/apply.md | 120 +++ .../installer/src/host/apply/conflict.md | 80 ++ .../installer/src/host/apply/json-merge.md | 70 ++ .../installer/src/host/apply/text-patch.md | 76 ++ .../tooling/installer/src/host/detect.md | 78 ++ .../tooling/installer/src/host/host.md | 147 +++ .../tooling/installer/src/host/plan.md | 72 ++ .../installer/src/host/post-install.md | 66 ++ .../tooling/installer/src/host/prompts.md | 87 ++ .../installer/src/manifest/discover.md | 78 ++ .../installer/src/manifest/manifest.md | 91 ++ .../src/testing/installer-fs.test-helpers.md | 63 ++ .../installer/src/testing/run-plugin.md | 71 ++ .../installer/src/testing/script-cli.md | 70 ++ .../installer/src/types/file-op.types.md | 79 ++ .../installer/src/types/installer.types.md | 94 ++ .../tooling/javy-cli-darwin-arm64/README.md | 9 + .../javy-cli-darwin-arm64/src/index.md | 47 + .../tooling/javy-cli-darwin-x64/README.md | 9 + .../tooling/javy-cli-darwin-x64/src/index.md | 47 + .../tooling/javy-cli-linux-arm64/README.md | 9 + .../tooling/javy-cli-linux-arm64/src/index.md | 47 + .../tooling/javy-cli-linux-x64/README.md | 9 + .../tooling/javy-cli-linux-x64/src/index.md | 47 + .../tooling/javy-cli-win32-x64/README.md | 9 + .../tooling/javy-cli-win32-x64/src/index.md | 47 + docs/devtools/tooling/linter/README.md | 86 ++ docs/devtools/tooling/linter/src/bin.md | 60 ++ .../linter/src/biome-runner/biome-runner.md | 117 +++ docs/devtools/tooling/linter/src/cli/cli.md | 93 ++ .../linter/src/error-codes/error-codes.md | 112 +++ .../linter/src/glob-resolver/glob-resolver.md | 117 +++ .../src/markdown-fixer/markdown-fixer.md | 133 +++ .../linter/src/markdown-fixer/rules.md | 114 +++ .../tooling/linter/src/telemetry/telemetry.md | 105 +++ .../tooling/linter/src/types/linter.types.md | 81 ++ .../linter/src/unified-lint/unified-lint.md | 122 +++ docs/devtools/tooling/mcp/README.md | 94 ++ .../mcp/src/client/mcp-client/mcp-client.md | 76 ++ .../mcp/src/error-codes/error-codes.md | 56 ++ .../devtools/tooling/mcp/src/events/events.md | 59 ++ .../mcp/src/jsonrpc/dispatcher/dispatcher.md | 68 ++ .../tooling/mcp/src/schemas/schemas.md | 62 ++ .../mcp/src/server/mcp-server/mcp-server.md | 87 ++ .../tooling/mcp/src/telemetry/telemetry.md | 58 ++ .../mcp/src/transport/http-sse/http-sse.md | 61 ++ .../mcp/src/transport/in-memory/in-memory.md | 55 ++ .../tooling/mcp/src/transport/stdio/stdio.md | 66 ++ .../mcp/src/transport/transport/transport.md | 68 ++ docs/devtools/tooling/mcp/src/types/types.md | 70 ++ docs/devtools/tooling/overview/README.md | 106 +++ .../tooling/overview/src/discover/discover.md | 85 ++ .../tooling/overview/src/errors/errors.md | 86 ++ .../tooling/overview/src/graph/graph.md | 90 ++ .../tooling/overview/src/rollups/rollups.md | 62 ++ .../tooling/overview/src/schemas/schemas.md | 68 ++ .../overview/src/telemetry/telemetry.md | 73 ++ .../tooling/overview/src/tier/tier.md | 73 ++ .../tooling/overview/src/types/types.md | 84 ++ docs/devtools/tooling/profiler/README.md | 69 ++ .../profiler/src/bottleneck/bottleneck.md | 59 ++ .../profiler/src/comparison/comparison.md | 57 ++ .../profiler/src/error-codes/error-codes.md | 59 ++ .../profiler/src/flamegraph/flamegraph.md | 54 ++ .../tooling/profiler/src/memory/memory.md | 66 ++ .../tooling/profiler/src/otel/otel.md | 63 ++ .../tooling/profiler/src/profiler/profiler.md | 64 ++ .../tooling/profiler/src/reporter/reporter.md | 57 ++ .../tooling/profiler/src/sampler/sampler.md | 71 ++ .../profiler/src/telemetry/telemetry.md | 59 ++ .../profiler/src/types/profiler.types.md | 70 ++ docs/devtools/tooling/readline/README.md | 98 ++ .../tooling/readline/src/errors/errors.md | 162 ++++ .../readline/src/interface/interface.md | 116 +++ .../tooling/readline/src/reader/reader.md | 114 +++ .../tooling/readline/src/scanner/scanner.md | 93 ++ docs/devtools/tooling/sandbox/README.md | 108 +++ .../sandbox/src/audit-logger/audit-logger.md | 65 ++ .../src/code-transformer/code-transformer.md | 70 ++ .../sandbox/src/error-codes/error-codes.md | 68 ++ .../src/isolate-engine/isolate-engine.md | 78 ++ .../src/module-resolver/module-resolver.md | 70 ++ .../devtools/tooling/sandbox/src/pool/pool.md | 76 ++ .../src/resource-limiter/resource-limiter.md | 75 ++ .../src/result-streamer/result-streamer.md | 69 ++ .../tooling/sandbox/src/sandbox/sandbox.md | 79 ++ .../tooling/sandbox/src/schemas/schemas.md | 65 ++ .../sandbox/src/spawn-engine/runner.md | 66 ++ .../sandbox/src/spawn-engine/spawn-engine.md | 74 ++ .../sandbox/src/telemetry/telemetry.md | 60 ++ .../sandbox/src/vm-engine/vm-engine.md | 86 ++ .../src/worker-engine/worker-engine.md | 70 ++ docs/devtools/tooling/test-vite/README.md | 65 ++ .../browser-environment.md | 54 ++ .../bundle-size-snapshot.md | 60 ++ .../test-vite/src/error-codes/error-codes.md | 64 ++ .../test-vite/src/hmr-tester/hmr-tester.md | 65 ++ .../test-vite/src/matchers/matchers.md | 61 ++ .../src/port-allocator/port-allocator.md | 54 ++ .../test-vite/src/telemetry/telemetry.md | 60 ++ .../tree-shake-validator.md | 55 ++ .../test-vite/src/types/test-vite.types.md | 54 ++ .../src/vite-app-config/vite-app-config.md | 54 ++ .../vite-library-config.md | 63 ++ .../vitest-browser-config.md | 52 ++ .../src/vitest-config/vitest-config.md | 55 ++ docs/foundation/README.md | 134 +++ docs/foundation/_intro.md | 3 + docs/foundation/barcode/README.md | 14 + docs/foundation/barcode/_intro.md | 1 + docs/foundation/barcode/barcode/README.md | 132 +++ .../barcode/src/core/encoder/encoder.md | 87 ++ .../barcode/src/core/validator/validator.md | 78 ++ .../barcode/src/errors/barcode-error.md | 82 ++ .../barcode/src/symbologies/code128.md | 68 ++ .../barcode/barcode/src/symbologies/code39.md | 63 ++ .../barcode/barcode/src/symbologies/ean13.md | 77 ++ .../barcode/barcode/src/symbologies/ean8.md | 61 ++ .../barcode/barcode/src/symbologies/itf.md | 60 ++ .../barcode/barcode/src/symbologies/upca.md | 56 ++ .../barcode/barcode/src/symbologies/upce.md | 59 ++ .../barcode/src/types/barcode.types.md | 142 +++ docs/foundation/barcode/qrcode/README.md | 131 +++ .../qrcode/src/core/encoder/data-encoder.md | 83 ++ .../barcode/qrcode/src/core/mask/masking.md | 72 ++ .../qrcode/src/core/matrix/matrix-builder.md | 68 ++ .../barcode/qrcode/src/core/qrcode.md | 102 ++ .../src/core/reed-solomon/reed-solomon.md | 94 ++ .../qrcode/src/core/renderer/svg-renderer.md | 78 ++ .../barcode/qrcode/src/core/tables/tables.md | 107 +++ .../barcode/qrcode/src/errors/qrcode-error.md | 90 ++ .../barcode/qrcode/src/types/qrcode.types.md | 122 +++ docs/foundation/bitpacker/README.md | 22 + docs/foundation/bitpacker/_intro.md | 1 + .../bitpacker/bitpacker-compressed/README.md | 91 ++ .../src/adapters/deflate/deflate.md | 54 ++ .../src/adapters/gzip/gzip.md | 56 ++ .../src/adapters/none/none.md | 55 ++ .../bitpacker-compressed/src/api/api.md | 62 ++ .../compressed-bit-packer.md | 122 +++ .../compressed-bit-packer.schema.md | 65 ++ .../bitpacker-compressed/src/index.md | 8 + .../src/otel/instruments.md | 83 ++ .../src/register-schemas/register-schemas.md | 61 ++ .../src/registry/registry.md | 68 ++ .../bitpacker-compressed/src/rle/rle.md | 78 ++ .../src/rle/rle.schema.md | 48 + .../bitpacker-compressed/src/types/types.md | 92 ++ .../src/types/types.schema.md | 77 ++ .../bitpacker/bitpacker-crypto/README.md | 155 ++++ .../bitpacker/bitpacker-crypto/SUPERSEDED.md | 150 +++ .../bitpacker/bitpacker-crypto/src/crc32.md | 89 ++ .../src/encrypted/encrypted-bitschema.md | 174 ++++ .../src/envelope/envelope-schema.md | 142 +++ .../src/fingerprint/schema-fingerprint.md | 127 +++ .../src/hash-registry/hash-registry.md | 119 +++ .../src/hashchain/hashchain-schema.md | 175 ++++ .../bitpacker/bitpacker-crypto/src/index.md | 8 + .../src/multisigned/multisigned-bitschema.md | 131 +++ .../src/signed/signed-bitschema.md | 158 ++++ .../bitpacker-crypto/src/xxhash32.md | 31 + .../bitpacker/bitpacker-delta/README.md | 61 ++ .../src/delta-manager/delta-manager.md | 123 +++ .../src/delta-state/delta-state.md | 90 ++ .../bitpacker/bitpacker-delta/src/index.md | 8 + .../bitpacker-delta/src/string-diff.md | 26 + .../bitpacker-delta/src/xor-encoder.md | 23 + .../bitpacker/bitpacker-game/README.md | 145 +++ .../bitpacker-game/src/bitpacker/bitpacker.md | 82 ++ .../bitpacker/bitpacker-game/src/index.md | 8 + .../integration-manager.md | 77 ++ .../bitpacker-game/src/interpolation/index.md | 39 + .../src/interpolation/interpolation.md | 12 + .../bitpacker-game/src/otel/instruments.md | 94 ++ .../bitpacker-game/src/prediction/index.md | 39 + .../src/prediction/kalman-filter.md | 8 + .../src/prediction/motion-math.md | 8 + .../src/prediction/position-predictor.md | 8 + .../src/prediction/prediction-algorithms.md | 8 + .../src/prediction/prediction.md | 80 ++ .../src/prediction/rotation-predictor.md | 8 + .../src/quantization/quantization.md | 84 ++ .../src/reconciliation/index.md | 41 + .../src/reconciliation/reconciliation.md | 12 + .../src/register-schemas/register-schemas.md | 65 ++ .../src/schema-factory/schema-factory.md | 68 ++ .../bitpacker-game/src/schemas/schemas.md | 97 ++ .../src/state-manager/state-manager.md | 85 ++ .../bitpacker/bitpacker-game/src/types.md | 37 + .../src/types.schema/types.schema.md | 109 +++ .../bitpacker/bitpacker-network/README.md | 81 ++ .../src/defaults/default-clock.md | 45 + .../src/defaults/default-rng.md | 45 + .../src/defaults/defaults.md | 58 ++ .../bitpacker/bitpacker-network/src/index.md | 8 + .../bitpacker-network/src/otel/instruments.md | 83 ++ .../src/register-schemas/register-schemas.md | 61 ++ .../src/simulator/simulator.md | 156 ++++ .../src/simulator/simulator.schema.md | 70 ++ .../bitpacker-network/src/types/types.md | 97 ++ .../src/types/types.schema.md | 72 ++ .../bitpacker/bitpacker-schema/README.md | 71 ++ .../bitpacker/bitpacker-schema/src/index.md | 8 + .../bitpacker-schema/src/matching/matching.md | 66 ++ .../src/migration/migration.md | 95 ++ .../src/registry/defaults/default-clock.md | 56 ++ .../src/registry/factories/factories.md | 75 ++ .../bitpacker-schema/src/registry/registry.md | 112 +++ .../registry/storage/in-memory/in-memory.md | 90 ++ .../storage/local-storage/local-storage.md | 92 ++ .../src/validation/validation.md | 12 + .../src/versioning/versioning.md | 69 ++ .../src/visualization/visualization.md | 67 ++ .../bitpacker/bitpacker-strategies/README.md | 202 ++++ .../bitpacker-strategies/src/index.md | 8 + .../src/otel/instruments.md | 76 ++ .../register-default-strategies.schema.md | 72 ++ .../register-default-strategies.md | 14 + .../src/register-schemas/register-schemas.md | 68 ++ .../strategies/array-config/array-config.md | 27 + .../array-notation/array-notation.md | 22 + .../strategies/array-schema/array-schema.md | 22 + .../src/strategies/array/array.md | 12 + .../strategies/bigint-array/bigint-array.md | 18 + .../src/strategies/bigint/bigint.md | 12 + .../src/strategies/bitarray/bitarray.md | 12 + .../src/strategies/bitset/bitset.md | 12 + .../src/strategies/blob/blob.md | 12 + .../src/strategies/boolean/boolean.md | 12 + .../src/strategies/conditional/conditional.md | 12 + .../src/strategies/customType/customType.md | 12 + .../src/strategies/datetime/datetime.md | 12 + .../src/strategies/defs/defs.md | 12 + .../src/strategies/enum/enum.md | 12 + .../src/strategies/map/map.md | 12 + .../src/strategies/null/null.md | 12 + .../src/strategies/number/number.md | 12 + .../src/strategies/object/object.md | 12 + .../src/strategies/oneOf/oneOf.md | 12 + .../optional-marker/optional-marker.md | 23 + .../optional-suffix/optional-suffix.md | 22 + .../src/strategies/optional/optional.md | 12 + .../src/strategies/set/set.md | 12 + .../src/strategies/string/string.md | 12 + .../src/strategies/union/union.md | 24 + .../src/strategies/varint/varint.md | 12 + .../src/strategies/version/version.md | 103 ++ .../bitpacker/bitpacker-streaming/README.md | 89 ++ .../src/defaults/default-clock.md | 55 ++ .../bitpacker-streaming/src/index.md | 8 + .../src/otel/instruments.md | 84 ++ .../src/register-schemas/register-schemas.md | 66 ++ .../streaming-bit-packer.md | 129 +++ .../streaming-bit-packer.schema.md | 99 ++ .../src/transform/transform.md | 53 ++ .../src/transform/transform.schema.md | 79 ++ .../src/transform/transform.types.md | 8 + .../bitpacker/bitpacker-validation/README.md | 101 ++ .../bitpacker-validation/src/index.md | 8 + .../src/otel/instruments.md | 86 ++ .../src/register-schemas/register-schemas.md | 67 ++ .../src/safety/safety-checks.md | 93 ++ .../src/safety/safety-checks.schema.md | 89 ++ .../bitpacker-validation/src/safety/safety.md | 68 ++ .../src/types.schema/types.schema.md | 76 ++ .../bitpacker-validation/src/types/types.md | 103 ++ .../bitpacker-validation/src/utils/utils.md | 77 ++ .../validation/find-array-length-errors.md | 64 ++ .../src/validation/find-extra-fields.md | 78 ++ .../src/validation/validate-data.md | 72 ++ .../src/validation/validation.md | 102 ++ .../src/validation/validator.md | 79 ++ docs/foundation/bitpacker/bitpacker/README.md | 270 ++++++ .../bitpacker/src/bit-reader/bit-reader.md | 54 ++ .../bitpacker/src/bit-reader/index.md | 8 + .../bitpacker/bitpacker/src/bit-schema.md | 26 + .../bitpacker/src/bit-writer/bit-writer.md | 53 ++ .../bitpacker/src/bit-writer/index.md | 8 + .../bitpacker/bitpacker/src/core/bitpacker.md | 33 + .../bitpacker/src/core/bitpacker.schema.md | 74 ++ .../src/core/safety/safety-checks.md | 87 ++ .../bitpacker/src/core/strategies/invalid.md | 8 + .../bitpacker/src/core/strategies/manager.md | 29 + .../bitpacker/src/core/strategies/types.md | 28 + .../src/core/strategies/types.schema.md | 72 ++ .../bitpacker/src/error-codes/error-codes.md | 14 + .../src/handlers/custom-type-registry.md | 25 + .../bitpacker/bitpacker/src/index.md | 8 + .../iterators/pack-iterator/pack-iterator.md | 69 ++ .../bitpacker/src/otel/instruments.md | 83 ++ .../src/packers/array/array-packer.md | 70 ++ .../bitpacker/src/packers/base/base-packer.md | 64 ++ .../bigint-array/bigint-array-packer.md | 65 ++ .../src/packers/bigint/bigint-packer.md | 69 ++ .../src/packers/bit-array/bit-array-packer.md | 69 ++ .../packers/bit-operations/bit-operations.md | 82 ++ .../src/packers/boolean/boolean-packer.md | 66 ++ .../src/packers/datetime/datetime-packer.md | 67 ++ .../bitpacker/src/packers/enum/enum-packer.md | 71 ++ .../src/packers/float/float-packer.md | 65 ++ .../bitpacker/bitpacker/src/packers/index.md | 42 + .../src/packers/integer/integer-packer.md | 72 ++ .../bitpacker/src/packers/map/map-packer.md | 67 ++ .../bitpacker/src/packers/set/set-packer.md | 67 ++ .../src/packers/string/string-packer.md | 71 ++ .../bitpacker/src/packers/uuid/uuid-packer.md | 72 ++ .../src/packers/varint/varint-packer.md | 67 ++ .../bitpacker/src/performance/buffer-pool.md | 81 ++ .../bitpacker/src/performance/lru-cache.md | 81 ++ .../src/performance/performance-monitor.md | 87 ++ .../bitpacker/src/performance/performance.md | 28 + .../src/register-schemas/register-schemas.md | 87 ++ .../src/serialization/serialization.md | 70 ++ .../src/types.schema/types.schema.md | 88 ++ .../bitpacker/src/types/base-types.md | 90 ++ .../bitpacker/bitpacker/src/types/common.md | 8 + .../bitpacker/bitpacker/src/types/index.md | 25 + .../bitpacker/src/types/key-types.md | 77 ++ .../bitpacker/src/types/packer-types.md | 66 ++ .../src/types/schema-versioning-types.md | 114 +++ .../bitpacker/bitpacker/src/types/schemas.md | 31 + .../bitpacker/src/types/validation-types.md | 57 ++ .../bitpacker/src/utils/float-utils.md | 78 ++ .../bitpacker/src/utils/pack-bits.md | 8 + .../bitpacker/src/utils/schema-validators.md | 53 ++ .../bitpacker/src/utils/type-guards.md | 65 ++ .../bitpacker/bitpacker/src/utils/utils.md | 45 + .../bitpacker/bitpacker/src/utils/zigzag.md | 8 + docs/foundation/core/README.md | 19 + docs/foundation/core/_intro.md | 1 + docs/foundation/core/config/README.md | 184 ++++ .../src/core/config-builder/config-builder.md | 108 +++ .../src/core/config-store/config-store.md | 114 +++ .../config/src/layers/cli-layer/cli-layer.md | 101 ++ .../layers/defaults-layer/defaults-layer.md | 91 ++ .../config/src/layers/env-layer/env-layer.md | 107 +++ .../src/layers/file-layer/file-layer.md | 94 ++ .../src/layers/object-layer/object-layer.md | 83 ++ .../core/config/src/types/common.md | 181 ++++ .../core/config/src/types/schemas.md | 110 +++ docs/foundation/core/config/src/utils/mask.md | 115 +++ .../foundation/core/config/src/utils/merge.md | 90 ++ docs/foundation/core/env/README.md | 242 +++++ .../env/src/core/create-env/create-env.md | 91 ++ .../core/env/src/core/field/field.md | 97 ++ .../core/env/src/core/validator/validator.md | 108 +++ .../core/env/src/errors/env-error.md | 106 +++ .../core/env/src/errors/error-codes.md | 69 ++ .../env/src/fields/array-field/array-field.md | 91 ++ .../src/fields/boolean-field/boolean-field.md | 84 ++ .../env/src/fields/email-field/email-field.md | 84 ++ .../env/src/fields/enum-field/enum-field.md | 85 ++ .../env/src/fields/json-field/json-field.md | 90 ++ .../src/fields/number-field/number-field.md | 82 ++ .../env/src/fields/port-field/port-field.md | 78 ++ .../src/fields/string-field/string-field.md | 97 ++ .../env/src/fields/url-field/url-field.md | 89 ++ .../core/env/src/loaders/dotenv/dotenv.md | 98 ++ .../core/env/src/loaders/object/object.md | 76 ++ .../core/env/src/presets/common/common.md | 89 ++ .../core/env/src/presets/server/server.md | 108 +++ .../core/env/src/schemas/env.schemas.md | 94 ++ .../core/env/src/transforms/coerce/coerce.md | 80 ++ docs/foundation/core/env/src/types/common.md | 112 +++ .../core/env/src/utils/interpolation.md | 80 ++ docs/foundation/core/error/README.md | 113 +++ .../core/error/src/base/package-error.md | 57 ++ .../core/error/src/base/suaveplan-error.md | 83 ++ .../core/error/src/causes/walk-causes.md | 72 ++ .../core/error/src/codes/define-codes.md | 66 ++ .../core/error/src/codes/error-codes.md | 70 ++ .../core/error/src/i18n/resolver.md | 83 ++ .../core/error/src/otel/to-span-event.md | 78 ++ .../core/error/src/redact/sensitive.md | 76 ++ .../core/error/src/serialize/from-binary.md | 58 ++ .../core/error/src/serialize/from-json.md | 70 ++ .../core/error/src/serialize/to-binary.md | 53 ++ .../core/error/src/serialize/to-json.md | 74 ++ .../foundation/core/schema-registry/README.md | 88 ++ .../src/core/compatibility/compatibility.md | 113 +++ .../src/core/registry/schema-registry.md | 168 ++++ .../src/errors/schema-registry-error.md | 107 +++ .../src/types/schema-registry.types.md | 127 +++ docs/foundation/core/types/README.md | 117 +++ docs/foundation/core/types/src/aead-ops.md | 117 +++ docs/foundation/core/types/src/authority.md | 162 ++++ .../core/types/src/chunk-presence.md | 74 ++ docs/foundation/core/types/src/chunk-ref.md | 53 ++ .../foundation/core/types/src/chunk-source.md | 155 ++++ docs/foundation/core/types/src/clock.md | 50 + .../core/types/src/database-like.md | 80 ++ docs/foundation/core/types/src/dir-entry.md | 90 ++ docs/foundation/core/types/src/domain-tag.md | 84 ++ docs/foundation/core/types/src/drive-stats.md | 67 ++ .../core/types/src/events-bus-like.md | 70 ++ .../core/types/src/fetch-like/fetch-like.md | 78 ++ docs/foundation/core/types/src/framing.md | 66 ++ docs/foundation/core/types/src/hash-like.md | 60 ++ .../core/types/src/health-status.md | 78 ++ .../foundation/core/types/src/i18n-backend.md | 226 +++++ .../foundation/core/types/src/i18n-catalog.md | 166 ++++ .../foundation/core/types/src/id-generator.md | 50 + docs/foundation/core/types/src/key-status.md | 72 ++ docs/foundation/core/types/src/logger-like.md | 64 ++ .../core/types/src/message-envelope.md | 83 ++ .../core/types/src/message-resolver.md | 89 ++ docs/foundation/core/types/src/middleware.md | 75 ++ .../core/types/src/network-plugin.md | 94 ++ docs/foundation/core/types/src/options.md | 74 ++ docs/foundation/core/types/src/peer-id.md | 60 ++ .../core/types/src/pipeline-stage.md | 64 ++ docs/foundation/core/types/src/plugin.md | 104 +++ docs/foundation/core/types/src/rng.md | 65 ++ docs/foundation/core/types/src/source-hint.md | 58 ++ .../core/types/src/storage-capabilities.md | 70 ++ .../foundation/core/types/src/storage-like.md | 75 ++ .../core/types/src/stream-transformer.md | 69 ++ .../core/types/src/streaming-aead-engine.md | 81 ++ docs/foundation/core/types/src/timers-like.md | 96 ++ .../core/types/src/transform-progress.md | 62 ++ .../core/types/src/translation-record.md | 125 +++ docs/foundation/core/types/src/transport.md | 92 ++ .../core/typescript-config/README.md | 159 ++++ docs/foundation/core/utils/README.md | 118 +++ docs/foundation/core/utils/src/debug/debug.md | 87 ++ docs/foundation/core/utils/src/email/email.md | 94 ++ .../core/utils/src/errors/utils-error.md | 83 ++ .../core/utils/src/number/number.md | 134 +++ .../core/utils/src/object/object.md | 145 +++ .../core/utils/src/platform/platform.md | 102 ++ .../core/utils/src/random/pseudo.md | 94 ++ docs/foundation/core/utils/src/sound/sound.md | 107 +++ .../core/utils/src/string/string.md | 99 ++ docs/foundation/core/utils/src/types/types.md | 92 ++ .../core/utils/src/validate/validate.md | 86 ++ .../core/utils/src/validation/size.md | 105 +++ docs/foundation/data/README.md | 29 + docs/foundation/data/_intro.md | 1 + docs/foundation/data/bytes/README.md | 95 ++ .../data/bytes/src/encoding/encoding.md | 103 ++ .../data/bytes/src/errors/bytes-error.md | 89 ++ docs/foundation/data/bytes/src/types/types.md | 78 ++ docs/foundation/data/bytes/src/uint8/uint8.md | 113 +++ docs/foundation/data/bytes/src/uuid/uuid.md | 97 ++ docs/foundation/data/clipboard/README.md | 92 ++ .../data/clipboard/src/errors/errors.md | 126 +++ .../data/clipboard/src/fallback/fallback.md | 94 ++ .../data/clipboard/src/manager/helpers.md | 96 ++ .../data/clipboard/src/manager/manager.md | 142 +++ .../data/clipboard/src/manager/operations.md | 113 +++ .../src/observability/observability.md | 95 ++ .../clipboard/src/permissions/permissions.md | 91 ++ .../data/clipboard/src/queue/queue.md | 96 ++ .../data/clipboard/src/sanitizer/sanitizer.md | 88 ++ .../data/clipboard/src/security/security.md | 105 +++ .../clipboard/src/types/clipboard.types.md | 96 ++ docs/foundation/data/data-masking/README.md | 128 +++ .../src/core/masker/object-masker.md | 128 +++ .../src/errors/data-masking-error.md | 120 +++ .../src/schemas/mask-rule.schema.md | 122 +++ .../src/strategies/credit-card.md | 82 ++ .../data/data-masking/src/strategies/email.md | 75 ++ .../data/data-masking/src/strategies/full.md | 67 ++ .../data/data-masking/src/strategies/hash.md | 79 ++ .../data-masking/src/strategies/partial.md | 85 ++ .../data/data-masking/src/strategies/phone.md | 80 ++ .../src/strategies/preserve-format.md | 79 ++ .../data-masking/src/strategies/tokenize.md | 91 ++ .../data/data-masking/src/types/mask-types.md | 130 +++ .../data-masking/src/utils/path-matcher.md | 88 ++ docs/foundation/data/dedup/README.md | 49 + .../dedup/src/core/engine/dedup-engine.md | 114 +++ .../dedup/src/core/merge/merge-strategies.md | 92 ++ .../data/dedup/src/core/scoring/similarity.md | 94 ++ .../data/dedup/src/errors/dedup-error.md | 82 ++ .../data/dedup/src/schemas/dedup.schema.md | 97 ++ docs/foundation/data/diff/README.md | 69 ++ docs/foundation/data/diff/src/diff/diff.md | 99 ++ .../data/diff/src/errors/diff-error.md | 116 +++ .../data/diff/src/history/history.md | 132 +++ .../data/diff/src/operations/operations.md | 134 +++ docs/foundation/data/diff/src/patch/patch.md | 114 +++ docs/foundation/data/diff/src/path/path.md | 129 +++ docs/foundation/data/diff/src/sync/sync.md | 141 +++ docs/foundation/data/diff/src/utils/utils.md | 138 +++ docs/foundation/data/json/README.md | 123 +++ .../data/json/src/errors/json-error.md | 103 ++ .../data/json/src/safe-json/safe-json.md | 209 +++++ docs/foundation/data/json/src/types/types.md | 78 ++ docs/foundation/data/media/README.md | 112 +++ .../data/media/src/detection/detection.md | 70 ++ .../data/media/src/errors/errors.md | 67 ++ .../data/media/src/metadata/metadata.md | 65 ++ .../media/src/observability/observability.md | 60 ++ .../data/media/src/signatures/signatures.md | 71 ++ .../data/media/src/types/media.types.md | 69 ++ .../data/media/src/validation/validation.md | 78 ++ docs/foundation/data/mime/README.md | 290 ++++++ .../data/mime/src/charset/sniff-bom.md | 59 ++ .../data/mime/src/charset/sniff-html-meta.md | 65 ++ .../data/mime/src/charset/sniff-xml-decl.md | 64 ++ .../src/content-type/content-type-equals.md | 79 ++ .../src/content-type/format-content-type.md | 71 ++ .../src/content-type/parse-content-type.md | 82 ++ .../foundation/data/mime/src/db/builtin-db.md | 56 ++ docs/foundation/data/mime/src/db/registry.md | 70 ++ .../data/mime/src/detection/detect.md | 90 ++ .../mime/src/detection/from-content-type.md | 56 ++ .../data/mime/src/detection/from-extension.md | 62 ++ .../from-magic-bytes/from-magic-bytes.md | 86 ++ .../src/detection/from-magic-bytes/helpers.md | 75 ++ .../detection/from-magic-bytes/registry.md | 84 ++ .../from-magic-bytes/signatures/archives.md | 39 + .../from-magic-bytes/signatures/audio.md | 37 + .../from-magic-bytes/signatures/data.md | 39 + .../from-magic-bytes/signatures/documents.md | 38 + .../signatures/executables.md | 43 + .../from-magic-bytes/signatures/fonts.md | 37 + .../from-magic-bytes/signatures/images.md | 39 + .../from-magic-bytes/signatures/model3d.md | 36 + .../from-magic-bytes/signatures/video.md | 38 + .../mime/src/detection/from-stream-reader.md | 36 + .../data/mime/src/detection/from-stream.md | 79 ++ .../data/mime/src/error-codes/error-codes.md | 63 ++ .../src/errors/insufficient-bytes-error.md | 65 ++ .../src/errors/invalid-content-type-error.md | 72 ++ .../data/mime/src/errors/mime-error.md | 59 ++ .../data/mime/src/errors/parse-error.md | 69 ++ .../src/errors/unknown-mime-type-error.md | 63 ++ .../src/errors/unknown-signature-error.md | 67 ++ .../data/mime/src/legacy/get-mime-type.md | 65 ++ .../data/mime/src/reverse/reverse.md | 70 ++ .../data/mime/src/telemetry/meters.md | 61 ++ docs/foundation/data/packer-browser/README.md | 129 +++ .../src/adaptive-cache/adaptive-cache.md | 93 ++ .../data/packer-browser/src/cache/cache.md | 104 +++ .../src/content-address/content-address.md | 103 ++ .../src/diagnostics/diagnostics.md | 79 ++ .../encrypted-archive/encrypted-archive.md | 106 +++ .../src/error-codes/error-codes.md | 89 ++ .../data/packer-browser/src/flags/flags.md | 76 ++ .../data/packer-browser/src/i18n/messages.md | 91 ++ .../packer-browser/src/keyring/keyring.md | 98 ++ .../src/loader/loader-helpers.md | 80 ++ .../src/loader/loader-stream.md | 88 ++ .../data/packer-browser/src/loader/loader.md | 102 ++ .../src/manager/manager-helpers.md | 67 ++ .../src/manager/manager-stream.md | 86 ++ .../packer-browser/src/manager/manager.md | 105 +++ .../src/manager/tiny-emitter.md | 90 ++ .../src/observability/observability.md | 78 ++ .../packer-browser/src/prefetch/prefetch.md | 103 ++ .../packer-browser/src/preload/preload.md | 88 ++ .../src/range-response/range-response.md | 94 ++ .../packer-browser/src/runtime/runtime.md | 79 ++ .../src/service-worker/service-worker.md | 90 ++ .../src/service-worker/sw-shim.md | 81 ++ .../packer-browser/src/signature/signature.md | 80 ++ .../packer-browser/src/singleton/singleton.md | 67 ++ .../packer-browser/src/utils/cross-origin.md | 91 ++ .../src/utils/register-service-worker.md | 95 ++ .../error-context.md | 24 + .../error-context.md | 24 + .../error-context.md | 24 + .../error-context.md | 24 + .../error-context.md | 24 + .../error-context.md | 24 + docs/foundation/data/packer/README.md | 139 +++ .../data/packer/src/abstract/abstract.md | 56 ++ .../data/packer/src/chunked/codec/chunk.md | 58 ++ .../data/packer/src/chunked/codec/header.md | 62 ++ .../data/packer/src/chunked/crypto/aead.md | 54 ++ .../packer/src/chunked/manifest/manifest.md | 116 +++ .../data/packer/src/chunked/packer/packer.md | 66 ++ .../packer/src/chunked/unpacker/unpacker.md | 69 ++ .../src/chunked/verifier/chunk-verifier.md | 61 ++ .../foundation/data/packer/src/error-codes.md | 52 ++ .../foundation/data/packer/src/flags/flags.md | 107 +++ .../data/packer/src/i18n/messages.md | 94 ++ .../packer/src/idempotency/idempotency.md | 116 +++ .../data/packer/src/integrity/integrity.md | 108 +++ .../packer/src/observability/observability.md | 122 +++ .../data/packer/src/packer/packer.md | 59 ++ .../data/packer/src/plugins/plugins.md | 112 +++ .../data/packer/src/retry/retryable-read.md | 99 ++ .../data/packer/src/runtime/runtime.md | 99 ++ .../data/packer/src/schemas/registration.md | 106 +++ .../packer/src/streaming/normalize-source.md | 57 ++ .../data/packer/src/unpacker/unpacker.md | 55 ++ docs/foundation/data/pagination/README.md | 92 ++ .../src/adapters/database-adapter.md | 89 ++ .../src/cursor/cursor-pagination.md | 90 ++ .../data/pagination/src/cursor/cursor.md | 105 +++ .../data/pagination/src/errors/codes.md | 84 ++ .../pagination/src/errors/pagination-error.md | 69 ++ .../data/pagination/src/helpers/helpers.md | 110 +++ .../src/keyset/keyset-pagination.md | 103 ++ .../data/pagination/src/offset/offset.md | 105 +++ .../pagination/src/otel/pagination-otel.md | 75 ++ .../data/pagination/src/tokens/page-tokens.md | 95 ++ .../pagination/src/types/pagination.types.md | 81 ++ docs/foundation/data/pwa/README.md | 138 +++ .../caching-strategies/caching-strategies.md | 78 ++ .../data/pwa/src/caching-strategies/router.md | 87 ++ docs/foundation/data/pwa/src/errors/errors.md | 74 ++ .../pwa/src/install-prompt/install-prompt.md | 80 ++ .../data/pwa/src/manifest/manifest.md | 91 ++ .../pwa/src/observability/observability.md | 66 ++ .../push-notifications/push-notifications.md | 81 ++ .../data/pwa/src/push-notifications/vapid.md | 60 ++ .../data/pwa/src/schemas/schemas.md | 79 ++ .../pwa/src/service-worker/service-worker.md | 83 ++ .../pwa/src/sync-queue/background-sync.md | 66 ++ .../pwa/src/sync-queue/indexeddb-store.md | 61 ++ .../pwa/src/sync-queue/local-storage-store.md | 65 ++ .../data/pwa/src/sync-queue/memory-store.md | 62 ++ .../data/pwa/src/sync-queue/sync-queue.md | 87 ++ .../pwa/src/sync-queue/version-migration.md | 69 ++ docs/foundation/data/pwa/src/types/common.md | 88 ++ .../update-controller/update-controller.md | 77 ++ docs/foundation/data/react-packer/README.md | 92 ++ .../src/error-codes/error-codes.md | 94 ++ .../use-packed-audio/use-packed-audio.md | 81 ++ .../hooks/use-packed-font/use-packed-font.md | 122 +++ .../use-packed-image/use-packed-image.md | 79 ++ .../use-packed-resource.md | 121 +++ .../use-packed-video/use-packed-video.md | 77 ++ .../packed-resource-provider.md | 105 +++ .../src/types/react-packer.types.md | 85 ++ docs/foundation/data/serialize/README.md | 110 +++ .../src/adapters/eval-safe/eval-safe.md | 82 ++ .../serialize/src/codec/json/json-decode.md | 85 ++ .../serialize/src/codec/json/json-encode.md | 99 ++ .../src/codec/msgpack/msgpack-decode.md | 75 ++ .../src/codec/msgpack/msgpack-encode.md | 78 ++ .../data/serialize/src/codec/stream/stream.md | 92 ++ .../serialize/src/codec/wire/wire.schemas.md | 57 ++ .../serialize/src/error-codes/error-codes.md | 65 ++ .../data/serialize/src/errors/codes.md | 92 ++ .../serialize/src/errors/serialize-error.md | 151 +++ .../data/serialize/src/legacy/legacy.md | 80 ++ .../serialize/src/observability/metrics.md | 61 ++ .../data/serialize/src/registry/registry.md | 115 +++ docs/foundation/data/templates/README.md | 250 +++++ .../data/templates/src/engine/ParseState.md | 88 ++ .../templates/src/engine/TemplateEngine.md | 98 ++ .../data/templates/src/engine/apply-plugin.md | 97 ++ .../data/templates/src/errors/error-codes.md | 69 ++ .../templates/src/errors/template-error.md | 102 ++ .../data/templates/src/otel/templates-otel.md | 64 ++ .../src/plugins/control/ConditionalPlugin.md | 98 ++ .../src/plugins/control/LoopPlugin.md | 90 ++ .../src/plugins/dynamic/CounterPlugin.md | 75 ++ .../src/plugins/dynamic/DateTimePlugin.md | 82 ++ .../src/plugins/dynamic/UuidPlugin.md | 82 ++ .../plugins/transform/CaseTransformPlugin.md | 64 ++ .../src/plugins/transform/RegexPlugin.md | 81 ++ .../plugins/transform/StringSplitPlugin.md | 80 ++ .../src/plugins/variables/ArrayIndexPlugin.md | 56 ++ .../plugins/variables/DotNotationPlugin.md | 57 ++ .../data/templates/src/presets/full.md | 85 ++ .../data/templates/src/presets/minimal.md | 64 ++ .../data/templates/src/presets/standard.md | 81 ++ .../src/schemas/templates.schemas.md | 104 +++ .../data/templates/src/types/index.md | 130 +++ .../data/templates/src/utils/escape.md | 67 ++ .../data/templates/src/utils/format.md | 80 ++ .../data/templates/src/utils/nested-value.md | 66 ++ docs/foundation/data/validation/README.md | 121 +++ .../data/validation/src/core/schema/schema.md | 117 +++ .../data/validation/src/errors/errors.md | 90 ++ .../validation/src/otel/validation-otel.md | 83 ++ .../validation/src/schemas/array/array.md | 63 ++ .../validation/src/schemas/boolean/boolean.md | 70 ++ .../data/validation/src/schemas/date/date.md | 68 ++ .../data/validation/src/schemas/enum/enum.md | 57 ++ .../src/schemas/intersection/intersection.md | 64 ++ .../validation/src/schemas/literal/literal.md | 65 ++ .../src/schemas/nullable/nullable.md | 67 ++ .../validation/src/schemas/number/number.md | 70 ++ .../validation/src/schemas/object/object.md | 77 ++ .../src/schemas/optional/optional.md | 68 ++ .../validation/src/schemas/record/record.md | 56 ++ .../validation/src/schemas/string/string.md | 90 ++ .../validation/src/schemas/tuple/tuple.md | 55 ++ .../validation/src/schemas/union/union.md | 60 ++ .../data/validation/src/types/common.md | 83 ++ .../validation/src/types/validation-hooks.md | 100 ++ .../data/validation/src/utils/coerce.md | 74 ++ .../data/validation/src/utils/compose.md | 51 + docs/foundation/data/web-workers/README.md | 96 ++ .../src/base-manager/base-manager.md | 140 +++ .../web-workers/src/base-manager/helpers.md | 76 ++ .../src/circuit-breaker/circuit-breaker.md | 94 ++ .../data/web-workers/src/errors/errors.md | 94 ++ .../web-workers/src/helpers/define-worker.md | 88 ++ .../src/message-bus/message-bus.md | 107 +++ .../src/observability/observability.md | 100 ++ .../shared-worker-manager.md | 115 +++ .../data/web-workers/src/streaming/stream.md | 107 +++ .../src/types/web-workers.types.md | 115 +++ .../src/worker-manager/worker-manager.md | 117 +++ .../web-workers/src/worker-pool/internals.md | 76 ++ .../web-workers/src/worker-pool/scheduler.md | 76 ++ .../src/worker-pool/worker-pool.md | 120 +++ docs/foundation/etl/README.md | 13 + docs/foundation/etl/_intro.md | 1 + docs/foundation/etl/etl/README.md | 46 + .../etl/etl/src/core/pipeline/pipeline.md | 82 ++ .../etl/etl/src/errors/etl-error.md | 67 ++ .../etl/etl/src/schemas/etl.schemas.md | 50 + .../etl/etl/src/stages/sink/sink.md | 67 ++ .../etl/etl/src/stages/source/source.md | 59 ++ .../etl/etl/src/stages/transform/transform.md | 60 ++ .../foundation/etl/etl/src/types/etl.types.md | 75 ++ docs/foundation/feature-flags/README.md | 13 + docs/foundation/feature-flags/_intro.md | 1 + .../feature-flags/feature-flags/README.md | 96 ++ .../src/core/evaluator/evaluator.md | 84 ++ .../src/core/manager/flag-manager.md | 86 ++ .../src/core/registry/flag-registry.md | 85 ++ .../src/errors/feature-flags-error.md | 81 ++ .../feature-flags/src/providers/json/json.md | 73 ++ .../src/providers/memory/memory.md | 74 ++ .../src/strategies/attribute/attribute.md | 92 ++ .../src/strategies/composite/composite.md | 81 ++ .../src/strategies/percentage/percentage.md | 69 ++ .../src/strategies/schedule/schedule.md | 78 ++ .../src/strategies/user-target/user-target.md | 76 ++ .../feature-flags/src/types/common.md | 114 +++ .../feature-flags/src/utils/hash.md | 84 ++ docs/foundation/flow/README.md | 30 + docs/foundation/flow/_intro.md | 1 + docs/foundation/flow/cbor/README.md | 183 ++++ docs/foundation/flow/cbor/src/cddl/ast.md | 58 ++ docs/foundation/flow/cbor/src/cddl/lexer.md | 69 ++ docs/foundation/flow/cbor/src/cddl/parser.md | 71 ++ .../foundation/flow/cbor/src/cddl/validate.md | 84 ++ docs/foundation/flow/cbor/src/cose/alg-map.md | 67 ++ .../foundation/flow/cbor/src/cose/cose-key.md | 71 ++ docs/foundation/flow/cbor/src/cose/encrypt.md | 55 ++ .../foundation/flow/cbor/src/cose/encrypt0.md | 54 ++ docs/foundation/flow/cbor/src/cose/headers.md | 43 + docs/foundation/flow/cbor/src/cose/jwk.md | 70 ++ docs/foundation/flow/cbor/src/cose/mac.md | 55 ++ docs/foundation/flow/cbor/src/cose/mac0.md | 50 + .../flow/cbor/src/cose/sig-structure.md | 48 + docs/foundation/flow/cbor/src/cose/sign.md | 58 ++ docs/foundation/flow/cbor/src/cose/sign1.md | 60 ++ docs/foundation/flow/cbor/src/cwt/claims.md | 53 ++ docs/foundation/flow/cbor/src/cwt/verify.md | 51 + .../flow/cbor/src/decoder/decoder.md | 91 ++ .../flow/cbor/src/decoder/half-float.md | 52 ++ .../flow/cbor/src/decoder/well-formed.md | 57 ++ .../cbor/src/deterministic/deterministic.md | 65 ++ .../flow/cbor/src/diagnostic/diagnostic.md | 68 ++ .../flow/cbor/src/encoder/encoder.md | 89 ++ .../flow/cbor/src/encoder/half-float.md | 58 ++ .../flow/cbor/src/errors/error-codes.md | 77 ++ .../flow/cbor/src/sequences/sequences.md | 66 ++ .../flow/cbor/src/streaming/chunk-decoder.md | 98 ++ .../flow/cbor/src/streaming/pull-decoder.md | 79 ++ docs/foundation/flow/cbor/src/tags/builtin.md | 64 ++ .../foundation/flow/cbor/src/tags/registry.md | 65 ++ docs/foundation/flow/cbor/src/tags/tagged.md | 59 ++ docs/foundation/flow/crdt/README.md | 73 ++ .../src/core/sync-manager/sync-manager.md | 139 +++ .../src/core/vector-clock/vector-clock.md | 59 ++ .../crdt/src/crdts/g-counter/g-counter.md | 60 ++ .../src/crdts/lww-register/lww-register.md | 54 ++ .../crdt/src/crdts/mv-register/mv-register.md | 58 ++ .../flow/crdt/src/crdts/or-set/or-set.md | 62 ++ .../crdt/src/crdts/pn-counter/pn-counter.md | 55 ++ .../foundation/flow/crdt/src/crdts/rga/rga.md | 136 +++ .../crdt/src/crdts/two-p-set/two-p-set.md | 56 ++ .../flow/crdt/src/errors/crdt-error.md | 52 ++ .../flow/crdt/src/types/crdt.types.md | 48 + docs/foundation/flow/fsm/README.md | 173 ++++ .../src/core/interpreter/fsm-interpreter.md | 181 ++++ .../flow/fsm/src/errors/fsm-error.md | 106 +++ .../flow/fsm/src/types/fsm.types.md | 144 +++ .../flow/fsm/src/utils/context-helpers.md | 107 +++ .../fsm/src/utils/definition-validator.md | 89 ++ docs/foundation/flow/idempotency/README.md | 95 ++ .../src/distributed/distributed-guard.md | 91 ++ .../src/distributed/redis-lock-provider.md | 79 ++ .../src/error-codes/error-codes.md | 78 ++ .../src/errors/idempotency-error.md | 97 ++ .../src/guard/idempotency-guard.md | 109 +++ .../flow/idempotency/src/key/key-generator.md | 99 ++ .../src/metrics/idempotency-metrics.md | 106 +++ .../src/middleware/idempotency-middleware.md | 90 ++ .../idempotency/src/store/database-store.md | 78 ++ .../idempotency/src/store/memory-store.md | 85 ++ .../flow/idempotency/src/store/redis-store.md | 76 ++ .../src/types/idempotency.types.md | 76 ++ .../src/versioning/key-versioning.md | 106 +++ docs/foundation/flow/job-scheduler/README.md | 162 ++++ .../src/errors/job-scheduler-error.md | 69 ++ .../flow/job-scheduler/src/events/events.md | 56 ++ .../src/execution/job-execution.md | 91 ++ .../src/otel/job-scheduler-otel.md | 76 ++ .../flow/job-scheduler/src/queue/job-queue.md | 72 ++ .../src/registry/job-registry.md | 73 ++ .../src/scheduler/cron-rescheduler.md | 61 ++ .../src/scheduler/job-dispatcher.md | 67 ++ .../src/scheduler/job-scheduler.md | 86 ++ .../src/scheduler/job-snapshot.md | 45 + .../flow/queue-distribution-http/README.md | 75 ++ .../src/communicator/base/base.md | 80 ++ .../communicator/http/http-communicator.md | 65 ++ .../errors/queue-distribution-http-error.md | 80 ++ .../src/observability/instruments.md | 59 ++ .../src/worker/remote/remote.md | 82 ++ .../README.md | 68 ++ .../worker-thread-communicator.md | 70 ++ .../queue-distribution-worker-thread-error.md | 76 ++ .../src/observability/instruments.md | 61 ++ .../worker-thread/worker-thread-worker.md | 78 ++ .../flow/queue-distribution/README.md | 129 +++ .../src/errors/queue-distribution-error.md | 84 ++ .../src/health-checker/health-checker.md | 75 ++ .../src/internal/noop-logger.md | 50 + .../src/load-balancing/base/base.md | 74 ++ .../load-balancing/least-busy/least-busy.md | 57 ++ .../load-balancing/round-robin/round-robin.md | 63 ++ .../src/load-balancing/weighted/weighted.md | 63 ++ .../src/manager/manager-dispatch.md | 67 ++ .../src/manager/manager-supervisor.md | 64 ++ .../queue-distribution/src/manager/manager.md | 91 ++ .../src/observability/instruments.md | 62 ++ .../flow/queue-distribution/src/pool/pool.md | 76 ++ .../flow/queue-distribution/src/task/task.md | 80 ++ .../src/worker/abstract/abstract-metrics.md | 76 ++ .../src/worker/abstract/abstract.md | 95 ++ .../src/worker/local/local.md | 79 ++ .../queue-distribution/src/worker/worker.md | 82 ++ docs/foundation/flow/queue/README.md | 63 ++ .../flow/queue/src/errors/queue-error.md | 95 ++ docs/foundation/flow/queue/src/job/job.md | 111 +++ .../flow/queue/src/queue/delayed-queue.md | 65 ++ .../flow/queue/src/queue/memory-queue.md | 86 ++ .../flow/queue/src/queue/priority-queue.md | 70 ++ .../flow/queue/src/types/queue-types.md | 81 ++ .../flow/queue/src/worker/queue-worker.md | 100 ++ docs/foundation/flow/rate-limiter/README.md | 87 ++ .../src/core/fixed-window/fixed-window.md | 68 ++ .../src/core/rate-limiter/rate-limiter.md | 96 ++ .../src/core/sliding-window/sliding-window.md | 73 ++ .../src/core/token-bucket/token-bucket.md | 75 ++ .../src/errors/rate-limiter-error.md | 97 ++ .../rate-limit-middleware.md | 99 ++ .../src/schemas/rate-limiter.schemas.md | 64 ++ .../src/storage/adapter/adapter.md | 65 ++ .../storage/memory-storage/memory-storage.md | 78 ++ .../src/types/rate-limiter.types.md | 88 ++ docs/foundation/flow/retry/README.md | 78 ++ .../src/circuit-breaker/circuit-breaker.md | 97 ++ .../flow/retry/src/errors/retry-error.md | 115 +++ .../flow/retry/src/otel/retry-otel.md | 95 ++ docs/foundation/flow/retry/src/retry/retry.md | 119 +++ .../retry/src/strategies/constant/constant.md | 63 ++ .../src/strategies/exponential/exponential.md | 92 ++ .../retry/src/strategies/linear/linear.md | 67 ++ .../flow/retry/src/types/retry.types.md | 75 ++ docs/foundation/flow/rules-hono/README.md | 41 + .../flow/rules-hono/src/engine/default.md | 60 ++ .../rules-hono/src/middleware/middleware.md | 168 ++++ docs/foundation/flow/rules/README.md | 111 +++ .../flow/rules/src/actions/actions.md | 133 +++ .../flow/rules/src/builder/builder.md | 108 +++ docs/foundation/flow/rules/src/constants.md | 51 + .../flow/rules/src/context/context.md | 107 +++ .../flow/rules/src/engine/engine.md | 141 +++ .../rules/src/engine/operators-internal.md | 66 ++ .../flow/rules/src/errors/rules-error.md | 104 +++ .../flow/rules/src/events/event-bus.md | 100 ++ .../flow/rules/src/operators/operators.md | 84 ++ .../flow/rules/src/optimizer/optimizer.md | 106 +++ docs/foundation/flow/rules/src/otel/otel.md | 81 ++ .../flow/rules/src/serializer/serializer.md | 98 ++ .../rules/src/validators/custom/custom.md | 103 ++ .../flow/rules/src/validators/field/field.md | 88 ++ .../rules/src/validators/schema/schema.md | 129 +++ .../flow/streams-chunk-queue/README.md | 100 ++ .../src/binary-protocol/encoder.md | 73 ++ .../src/decryptor/decryptor.md | 91 ++ .../src/errors/streams-chunk-queue-error.md | 97 ++ .../streams-chunk-queue/src/events/events.md | 69 ++ .../streams-chunk-queue/src/hooks/hooks.md | 69 ++ .../streams-chunk-queue/src/queue/pipeline.md | 73 ++ .../src/queue/storage-ops.md | 57 ++ .../src/queue/streaming-chunk-queue.md | 151 +++ .../src/rate-limiter/adapter.md | 86 ++ .../src/storage-adapter/persister.md | 92 ++ .../src/telemetry/telemetry.md | 79 ++ .../streams-chunk-queue/src/types/types.md | 95 ++ .../src/validator/chunk-verifier-validator.md | 89 ++ .../src/validator/validator.md | 93 ++ .../flow/streams-metadata/README.md | 88 ++ .../streams-metadata/src/errors/errors.md | 108 +++ .../streams-metadata/src/events/events.md | 92 ++ .../flow/streams-metadata/src/exif/exif.md | 102 ++ .../streams-metadata/src/metadata/metadata.md | 107 +++ .../flow/streams-metadata/src/mime/mime.md | 101 ++ .../streams-metadata/src/types/payload.md | 108 +++ .../src/types/process-options.md | 84 ++ docs/foundation/flow/streams/README.md | 158 ++++ .../streams/src/base/transform/transform.md | 176 ++++ .../flow/streams/src/errors/stream-error.md | 101 ++ .../streams/src/factory/factory/factory.md | 133 +++ .../src/instrument/transform/transform.md | 74 ++ .../streams/src/manager/manager/manager.md | 137 +++ .../flow/streams/src/node/node-adapters.md | 61 ++ .../streams/src/pipeline/builder/builder.md | 90 ++ .../streams/src/pipeline/concat/concat.md | 113 +++ .../streams/src/pipeline/fan-out/fan-out.md | 68 ++ .../pipeline/merge-ordered/merge-ordered.md | 119 +++ .../flow/streams/src/pipeline/merge/merge.md | 66 ++ .../src/pipeline/partition/partition.md | 105 +++ .../flow/streams/src/pipeline/route/route.md | 115 +++ .../src/pipeline/safe-branch/safe-branch.md | 92 ++ .../flow/streams/src/pipeline/zip/zip.md | 107 +++ .../streams/src/primitives/duplex/duplex.md | 151 +++ .../streams/src/primitives/network/network.md | 148 +++ .../src/readable/from-array/from-array.md | 69 ++ .../src/readable/from-bytes/from-bytes.md | 73 ++ .../readable/from-generator/from-generator.md | 75 ++ .../streams/src/sinks/for-each/for-each.md | 66 ++ .../streams/src/sinks/to-array/to-array.md | 73 ++ .../to-async-iterable/to-async-iterable.md | 94 ++ .../streams/src/sinks/to-bytes/to-bytes.md | 67 ++ .../streams/src/transforms/batch/batch.md | 100 ++ .../src/transforms/chunk-bytes/chunk-bytes.md | 104 +++ .../coalesce-bytes/coalesce-bytes.md | 93 ++ .../src/transforms/compress/compress.md | 78 ++ .../streams/src/transforms/crypto/crypto.md | 157 ++++ .../streams/src/transforms/dedup/dedup.md | 130 +++ .../streams/src/transforms/filter/filter.md | 101 ++ .../src/transforms/flat-map/flat-map.md | 119 +++ .../length-prefix-decode.md | 115 +++ .../length-prefix-encode.md | 98 ++ .../streams/src/transforms/limit/limit.md | 137 +++ .../flow/streams/src/transforms/map/map.md | 150 +++ .../transforms/sliding-bytes/sliding-bytes.md | 146 +++ .../src/transforms/split-join/split-join.md | 102 ++ .../flow/streams/src/transforms/tap/tap.md | 120 +++ .../src/transforms/text-codec/text-codec.md | 63 ++ .../src/transforms/throttle/throttle.md | 116 +++ .../streams/src/transforms/window/window.md | 129 +++ .../flow/streams/src/types/common.md | 85 ++ .../buffer/buffer-to-uint8/buffer-to-uint8.md | 71 ++ .../get-data-from-file/get-data-from-file.md | 75 ++ .../utils/buffer/uint8-slice/uint8-slice.md | 68 ++ .../create-data-stream/create-data-stream.md | 81 ++ .../process-data-stream.md | 71 ++ .../src/utils/stream/round-trip/round-trip.md | 91 ++ .../validate-integrity/validate-integrity.md | 77 ++ docs/foundation/flow/undo/README.md | 97 ++ .../flow/undo/src/async/async-command.md | 107 +++ .../flow/undo/src/async/async-stack.md | 110 +++ .../foundation/flow/undo/src/branch/branch.md | 124 +++ .../flow/undo/src/command/command.md | 143 +++ .../src/compression/history-compressor.md | 107 +++ .../flow/undo/src/errors/undo-error.md | 111 +++ .../flow/undo/src/merge/command-merger.md | 107 +++ .../flow/undo/src/schemas/undo.schemas.md | 118 +++ .../flow/undo/src/selective/selective-undo.md | 115 +++ docs/foundation/flow/undo/src/stack/stack.md | 120 +++ .../flow/undo/src/types/undo.types.md | 165 ++++ docs/foundation/flow/workflow/README.md | 162 ++++ .../compensation/compensator/compensator.md | 95 ++ .../workflow/src/compensation/saga/saga.md | 120 +++ .../flow/workflow/src/core/context/context.md | 109 +++ .../core/workflow-builder/workflow-builder.md | 98 ++ .../core/workflow-engine/transition-hooks.md | 72 ++ .../core/workflow-engine/workflow-engine.md | 127 +++ .../workflow/src/errors/workflow-error.md | 83 ++ .../flow/workflow/src/middleware/hook/hook.md | 108 +++ .../workflow/src/middleware/retry/retry.md | 84 ++ .../flow/workflow/src/otel/instruments.md | 86 ++ .../conditional-step/conditional-step.md | 102 ++ .../src/steps/parallel-step/parallel-step.md | 107 +++ .../flow/workflow/src/steps/step/step.md | 100 ++ .../flow/workflow/src/types/common.md | 103 ++ .../flow/workflow/src/types/workflow-hooks.md | 85 ++ .../flow/workflow/src/utils/utils.md | 81 ++ docs/foundation/random/README.md | 15 + docs/foundation/random/_intro.md | 1 + docs/foundation/random/noise/README.md | 66 ++ docs/foundation/random/noise/src/blue/blue.md | 53 ++ .../random/noise/src/errors/noise-error.md | 65 ++ docs/foundation/random/noise/src/fbm/fbm.md | 49 + .../random/noise/src/perlin/perlin.md | 50 + .../random/noise/src/simplex/simplex.md | 54 ++ .../random/noise/src/types/noise.types.md | 53 ++ .../random/noise/src/utils/permutation.md | 45 + .../random/noise/src/value/value.md | 51 + .../random/noise/src/worley/worley.md | 49 + .../foundation/random/pseudo-random/README.md | 75 ++ .../src/algorithms/counter-rng.md | 44 + .../src/algorithms/mulberry32.md | 51 + .../pseudo-random/src/algorithms/sfc32.md | 48 + .../src/algorithms/xoshiro256.md | 50 + .../src/errors/pseudo-random-error.md | 64 ++ .../pseudo-random/src/seed/normalize.md | 54 ++ .../src/types/seeded-rng.types.md | 59 ++ .../random/pseudo-random/src/utils/sample.md | 51 + .../random/pseudo-random/src/utils/shuffle.md | 46 + docs/foundation/random/random/README.md | 109 +++ .../random/src/collections/collections.md | 54 ++ .../distributions/continuous/continuous.md | 51 + .../src/distributions/discrete/discrete.md | 48 + .../src/distributions/sampler/sampler.md | 51 + .../random/random/src/errors/random-error.md | 63 ++ .../foundation/random/random/src/game/dice.md | 52 ++ .../random/random/src/ids/nanoid.md | 43 + docs/foundation/random/random/src/ids/ulid.md | 40 + docs/foundation/random/random/src/ids/uuid.md | 44 + .../random/random/src/numbers/random-float.md | 61 ++ .../random/random/src/numbers/random-int.md | 45 + .../random/random/src/objects/objects.md | 52 ++ .../random/random/src/source/crypto-rng.md | 48 + .../random/random/src/source/default-rng.md | 49 + .../random/src/strings/random-string.md | 48 + docs/foundation/timing/README.md | 15 + docs/foundation/timing/_intro.md | 1 + docs/foundation/timing/cron/README.md | 144 +++ .../timing/cron/src/errors/cron-error.md | 80 ++ .../timing/cron/src/fields/cron-fields.md | 89 ++ .../timing/cron/src/macros/macros.md | 78 ++ .../cron/src/next-run/next-run-fields.md | 99 ++ .../timing/cron/src/next-run/next-run.md | 77 ++ .../timing/cron/src/otel/cron-otel.md | 80 ++ .../timing/cron/src/parse/parse-cron.md | 86 ++ .../cron/src/scheduler/cron-scheduler.md | 109 +++ .../timing/cron/src/timezone/timezone.md | 88 ++ docs/foundation/timing/datetime/README.md | 92 ++ .../src/business-days/business-days.md | 100 ++ .../src/calendar/calendar-boundary.md | 99 ++ .../datetime/src/calendar/calendar-core.md | 82 ++ .../src/calendar/calendar-duration.md | 73 ++ .../datetime/src/calendar/calendar-grid.md | 78 ++ .../timing/datetime/src/calendar/calendar.md | 112 +++ .../datetime/src/errors/datetime-error.md | 91 ++ .../timing/datetime/src/otel/datetime-otel.md | 69 ++ .../src/recurrence/recurrence-generate.md | 95 ++ .../src/recurrence/recurrence-helpers.md | 98 ++ .../datetime/src/recurrence/recurrence.md | 102 ++ .../timing/datetime/src/relative/relative.md | 84 ++ .../datetime/src/types/datetime.types.md | 69 ++ docs/foundation/timing/timing/README.md | 89 ++ .../timing/timing/src/decay/decay.md | 101 ++ .../timing/timing/src/errors/timing-error.md | 95 ++ .../timing/timing/src/otel/timing-otel.md | 116 +++ .../timing/timing/src/scheduler/scheduler.md | 107 +++ .../timing/timing/src/stopwatch/stopwatch.md | 95 ++ .../timing/timing/src/throttle/once/once.md | 94 ++ .../src/throttle/rate-limit/rate-limit.md | 112 +++ .../timing/timing/src/throttle/throttle.md | 103 ++ .../timing/timing/src/throttle/times/times.md | 88 ++ .../timing/timing/src/timer/timer.md | 127 +++ .../timing/src/vector-clock/vector-clock.md | 109 +++ docs/gaming/README.md | 19 + docs/gaming/_intro.md | 3 + docs/gaming/games/README.md | 15 + docs/gaming/games/_intro.md | 1 + docs/gaming/games/controller/README.md | 66 ++ docs/gaming/games/controller/src/base/base.md | 121 +++ .../controller/src/error-codes/error-codes.md | 126 +++ .../games/controller/src/events/events.md | 90 ++ .../src/gamepad/gamepad.internal.md | 114 +++ .../games/controller/src/gamepad/gamepad.md | 142 +++ .../games/controller/src/keyboard/keyboard.md | 134 +++ .../games/controller/src/merger/merger.md | 169 ++++ .../controller/src/telemetry/telemetry.md | 88 ++ .../controller/src/types/controller.types.md | 93 ++ .../gaming/games/controller/src/types/keys.md | 80 ++ docs/gaming/games/ecs/README.md | 91 ++ .../games/ecs/src/archetype/archetype.md | 80 ++ docs/gaming/games/ecs/src/bitset/bitset.md | 82 ++ .../component-registry/component-registry.md | 77 ++ .../games/ecs/src/entity-pool/entity-pool.md | 71 ++ docs/gaming/games/ecs/src/errors/ecs-error.md | 83 ++ .../games/ecs/src/observability/otel.md | 65 ++ docs/gaming/games/ecs/src/query/query.md | 84 ++ docs/gaming/games/ecs/src/schema/schema.md | 65 ++ docs/gaming/games/ecs/src/system/system.md | 97 ++ docs/gaming/games/ecs/src/types/ecs.types.md | 84 ++ docs/gaming/games/ecs/src/world/world.md | 108 +++ docs/gaming/games/game-server/README.md | 166 ++++ .../abstract-game-logic.md | 182 ++++ .../game-event-emitter/game-event-emitter.md | 132 +++ .../core/events/game-events/game-events.md | 105 +++ .../interfaces/i-game-logic/i-game-logic.md | 122 +++ .../i-player-manager/i-player-manager.md | 97 ++ .../i-session-manager/i-session-manager.md | 102 ++ .../i-state-manager/i-state-manager.md | 104 +++ .../src/engine/di-container/di-container.md | 131 +++ .../src/engine/game-engine/game-engine.md | 153 +++ .../src/engine/game-loop/game-loop.md | 139 +++ .../engine/player-manager/player-manager.md | 132 +++ .../engine/plugin-manager/plugin-manager.md | 145 +++ .../session-lifecycle/session-lifecycle.md | 128 +++ .../src/engine/session-node/session-node.md | 126 +++ .../src/engine/session-store/session-store.md | 137 +++ .../src/engine/session-tree/session-tree.md | 132 +++ .../anti-cheat-validator.internal.md | 71 ++ .../anti-cheat-validator.md | 131 +++ .../interest-manager.internal.md | 72 ++ .../interest-manager/interest-manager.md | 117 +++ .../lag-compensator.internal.md | 70 ++ .../lag-compensator/lag-compensator.md | 123 +++ .../leaderboard-manager.md | 113 +++ .../game-persistence/game-persistence.md | 100 ++ .../replay/replay-player/replay-player.md | 104 +++ .../replay/replay-recorder/replay-recorder.md | 105 +++ .../game-instance-registry.internal.md | 69 ++ .../game-instance-registry.md | 119 +++ .../bitpacker-state-sync.md | 104 +++ .../vector-clock-sync.internal.md | 66 ++ .../vector-clock-sync/vector-clock-sync.md | 101 ++ .../tournament-bracket.internal.md | 81 ++ .../tournament-manager/tournament-manager.md | 129 +++ .../tournament-standings.internal.md | 71 ++ .../src/errors/game-server-error.md | 140 +++ .../enhanced-server/enhanced-server.md | 125 +++ .../matchmaking-engine/matchmaking-engine.md | 117 +++ .../queue-manager/queue-manager.md | 118 +++ .../skill-matcher/skill-matcher.md | 111 +++ .../spectator-manager/spectator-manager.md | 115 +++ .../winner-stays-on/winner-stays-on.md | 105 +++ .../network-adapter/network-adapter.md | 124 +++ .../reconnection-manager.md | 119 +++ .../webrtc-transport/webrtc-transport.md | 100 ++ .../websocket-transport.md | 94 ++ .../game-server/src/observability/otel.md | 116 +++ .../network-tier-adapter.md | 127 +++ .../performance/object-pool/object-pool.md | 120 +++ .../performance/session-pool/session-pool.md | 118 +++ .../plugins/ab-test-plugin/ab-test-plugin.md | 103 ++ .../analytics-plugin/analytics-plugin.md | 97 ++ .../src/plugins/base-plugin/base-plugin.md | 106 +++ .../feature-flag-plugin.md | 100 ++ .../plugins/logging-plugin/logging-plugin.md | 89 ++ .../persistence-plugin/persistence-plugin.md | 92 ++ .../src/plugins/rules-plugin/rules-plugin.md | 89 ++ .../workflow-plugin/workflow-plugin.md | 102 ++ .../delta-compressor/delta-compressor.md | 122 +++ .../src/state/state-differ/state-differ.md | 113 +++ .../src/state/state-manager/state-manager.md | 145 +++ .../src/state/state-sync/state-sync.md | 121 +++ .../games/game-server/src/types/common.md | 109 +++ .../game-server/src/types/common.types.md | 129 +++ docs/geospatial/README.md | 31 + docs/geospatial/_intro.md | 3 + docs/geospatial/geo/README.md | 19 + docs/geospatial/geo/_intro.md | 1 + docs/geospatial/geo/geo-earth/README.md | 31 + .../geo-earth/src/coordinates/coordinates.md | 63 ++ .../src/earth-config/earth-config.md | 67 ++ .../geo/geo-earth/src/geocoding/geocoding.md | 78 ++ .../geo/geo-earth/src/geohash/geohash.md | 73 ++ docs/geospatial/geo/geo-planet/README.md | 53 ++ .../geo-planet/src/atmospheric/atmospheric.md | 86 ++ .../src/planet-surface/planet-surface.md | 111 +++ .../geo/geo-planet/src/types/schemas.md | 84 ++ .../geo/geo-planet/src/types/types.md | 117 +++ docs/geospatial/geo/geo/README.md | 69 ++ .../geospatial/geo/geo/src/angular/angular.md | 79 ++ .../geospatial/geo/geo/src/bearing/bearing.md | 55 ++ docs/geospatial/geo/geo/src/bounds/bounds.md | 66 ++ .../geo/geo/src/distance/distance.md | 100 ++ .../geo/geo/src/ellipsoid/ellipsoid.md | 51 + .../geo/src/observability/observability.md | 17 + .../geospatial/geo/geo/src/polygon/polygon.md | 63 ++ .../geo/geo/src/transforms/transforms.md | 59 ++ docs/geospatial/geo/geo/src/types/schemas.md | 102 ++ docs/geospatial/geo/geo/src/types/types.md | 114 +++ docs/geospatial/geo/geo/src/units/units.md | 95 ++ docs/geospatial/geo/solar-system/README.md | 19 + .../geo/solar-system/src/provider/provider.md | 61 ++ .../geo/solar-system/src/seasons/seasons.md | 65 ++ docs/geospatial/geo/stars/README.md | 24 + .../geo/stars/src/catalog/catalog.md | 50 + .../geo/stars/src/provider/provider.md | 57 ++ docs/geospatial/geo/stars/src/types.md | 48 + docs/geospatial/geo/tides/README.md | 33 + .../geo/tides/src/admiralty/admiralty.md | 73 ++ .../src/harmonic/harmonic-constituents.md | 54 ++ .../geo/tides/src/harmonic/harmonic.md | 69 ++ .../geo/tides/src/physics/physics.md | 57 ++ .../geo/tides/src/provider/provider.md | 66 ++ .../geo/tides/src/stations/stations.md | 50 + docs/geospatial/geo/tides/src/types/types.md | 68 ++ docs/geospatial/geo/universe/README.md | 27 + .../geo/universe/src/client/client.md | 138 +++ .../geo/universe/src/frames/frames.md | 91 ++ .../geo/universe/src/observer/observer.md | 114 +++ .../geo/universe/src/packets/packets.md | 121 +++ .../geo/universe/src/providers/providers.md | 139 +++ .../geo/universe/src/types/types.md | 137 +++ docs/geospatial/logistics/README.md | 13 + docs/geospatial/logistics/_intro.md | 1 + docs/geospatial/logistics/ports/README.md | 104 +++ .../ports/src/data/airports/airports.md | 56 ++ .../ports/src/data/all-ports/all-ports.md | 60 ++ .../src/data/rail-terminals/rail-terminals.md | 57 ++ .../sea-ports-africa-mena.md | 60 ++ .../sea-ports-americas/sea-ports-americas.md | 60 ++ .../src/data/sea-ports-asia/sea-ports-asia.md | 59 ++ .../data/sea-ports-europe/sea-ports-europe.md | 60 ++ .../sea-ports-oceania/sea-ports-oceania.md | 60 ++ .../ports/src/data/sea-ports/sea-ports.md | 65 ++ .../src/data/shipping-lanes/shipping-lanes.md | 57 ++ .../logistics/ports/src/distance/distance.md | 69 ++ .../ports/src/error-codes/error-codes.md | 96 ++ .../geospatial/logistics/ports/src/eta/eta.md | 70 ++ .../ports/src/find-port/find-port.md | 78 ++ .../ports/src/lane-distance/lane-distance.md | 65 ++ .../ports/src/lane-lookup/lane-lookup.md | 67 ++ .../ports/src/lane-progress/lane-progress.md | 71 ++ .../ports/src/nearest-port/nearest-port.md | 65 ++ .../logistics/ports/src/otel/otel.md | 72 ++ .../logistics/ports/src/schemas/schemas.md | 74 ++ .../ports/src/spatial-index/spatial-index.md | 76 ++ .../logistics/ports/src/types/port.types.md | 80 ++ docs/identity/README.md | 23 + docs/identity/_intro.md | 3 + docs/identity/auth/README.md | 19 + docs/identity/auth/_intro.md | 1 + docs/identity/auth/auth/README.md | 65 ++ .../auth/auth/src/adapters/auth/auth.md | 94 ++ .../auth/auth/src/adapters/memory/memory.md | 115 +++ .../auth/auth/src/api-keys/api-keys.md | 114 +++ .../auth/auth/src/errors/auth-error.md | 112 +++ .../auth/auth/src/jwt/token-lifecycle.md | 104 +++ .../auth/src/middleware/auth-middleware.md | 85 ++ .../auth/auth/src/schemas/auth.schemas.md | 79 ++ .../auth/auth/src/types/auth.types.md | 104 +++ .../auth/better-auth-surrealdb/README.md | 177 ++++ .../src/adapter/adapter.md | 98 ++ .../src/adapter/internals.md | 66 ++ .../src/adapter/model-to-table.md | 72 ++ .../src/adapter/operations.md | 73 ++ .../better-auth-surrealdb/src/adapter/v1.6.md | 121 +++ .../src/compile/compile-select.md | 63 ++ .../src/compile/compile-sort.md | 63 ++ .../src/compile/compile-where.md | 76 ++ .../src/error-codes/error-codes.md | 78 ++ .../src/id-strategy/id-strategy.md | 77 ++ .../src/link-fields/link-fields.md | 95 ++ .../src/otel/instruments.md | 76 ++ .../src/schema/schema.md | 75 ++ .../src/schemas/link-fields.md | 75 ++ .../src/schemas/options.md | 72 ++ .../src/testing/run-adapter-conformance.md | 86 ++ .../src/types/adapter.md | 81 ++ docs/identity/auth/jwt-tenant/README.md | 65 ++ .../jwt-tenant/src/errors/jwt-tenant-error.md | 65 ++ .../in-memory-key-store.md | 74 ++ .../src/jwks/jwks-endpoint/jwks-endpoint.md | 81 ++ .../src/keys/key-generator/key-generator.md | 110 +++ .../src/schemas/jwt-tenant.schemas.md | 77 ++ .../src/token/token-issuer/token-issuer.md | 75 ++ .../token/token-verifier/token-verifier.md | 83 ++ .../jwt-tenant/src/types/jwt-tenant.types.md | 102 ++ docs/identity/auth/macos-keychain/README.md | 142 +++ .../core/error-classifier/error-classifier.md | 97 ++ .../core/keychain-bridge/default-executor.md | 78 ++ .../core/keychain-bridge/keychain-bridge.md | 109 +++ .../src/core/output-parser/output-parser.md | 101 ++ .../auth/macos-keychain/src/error-codes.md | 91 ++ .../src/errors/keychain-errors.md | 93 ++ .../src/schemas/macos-keychain.schemas.md | 93 ++ .../src/types/macos-keychain.types.md | 114 +++ docs/identity/auth/oauth-client/README.md | 119 +++ .../authorization-code/authorization-code.md | 109 +++ .../client-credentials/client-credentials.md | 83 ++ .../src/core/client/oauth-client.md | 115 +++ .../src/core/discovery/discovery.md | 86 ++ .../src/core/provider/provider.md | 86 ++ .../src/core/token-refresh/token-refresh.md | 85 ++ .../src/errors/oauth-client-error.md | 95 ++ .../src/types/oauth-client.types.md | 158 ++++ .../auth/oauth-client/src/utils/jwt.md | 64 ++ .../auth/oauth-client/src/utils/pkce.md | 87 ++ .../oauth-client/src/utils/url-builder.md | 94 ++ docs/identity/auth/permissions/README.md | 97 ++ .../adapter-interface/adapter-interface.md | 82 ++ .../permissions/src/adapters/memory/memory.md | 128 +++ .../permission-cache/permission-cache.md | 92 ++ .../condition-matcher/condition-matcher.md | 70 ++ .../conditions/field-matcher/field-matcher.md | 64 ++ .../subject-detector/subject-detector.md | 60 ++ .../core/ability-builder/ability-builder.md | 48 + .../permissions/src/core/ability/ability.md | 97 ++ .../permission-manager/permission-manager.md | 77 ++ .../src/core/policy-engine/policy-engine.md | 79 ++ .../src/core/role-manager/role-manager.md | 89 ++ .../auth/permissions/src/core/rule/rule.md | 73 ++ .../src/errors/permission-error.md | 100 ++ .../src/events/permission-events.md | 61 ++ .../permission-middleware.md | 71 ++ .../src/presets/role-presets/role-presets.md | 65 ++ .../src/schemas/permissions.schemas.md | 61 ++ .../src/types/permissions.types.md | 103 ++ docs/identity/auth/webauthn/README.md | 153 +++ .../auth/webauthn/src/adapter/adapter.md | 75 ++ .../src/adapter/dom-exception-mapper.md | 57 ++ .../attestation/android-key/android-key.md | 54 ++ .../android-safetynet/android-safetynet.md | 60 ++ .../webauthn/src/attestation/apple/apple.md | 55 ++ .../src/attestation/fido-u2f/fido-u2f.md | 53 ++ .../webauthn/src/attestation/none/none.md | 52 ++ .../webauthn/src/attestation/packed/packed.md | 63 ++ .../auth/webauthn/src/attestation/tpm/tpm.md | 58 ++ .../webauthn/src/authenticate/authenticate.md | 66 ++ .../auth/webauthn/src/errors/error-codes.md | 51 + .../src/extensions/large-blob/large-blob.md | 80 ++ .../auth/webauthn/src/extensions/prf/prf.md | 62 ++ .../webauthn/src/observability/metrics.md | 70 ++ .../webauthn/src/parser/attestation-object.md | 50 + .../webauthn/src/parser/authenticator-data.md | 59 ++ .../auth/webauthn/src/parser/client-data.md | 53 ++ .../auth/webauthn/src/parser/cose-key.md | 53 ++ .../auth/webauthn/src/register/register.md | 80 ++ .../auth/webauthn/src/schemas/schemas.md | 74 ++ .../auth/webauthn/src/verifier/registry.md | 54 ++ .../webauthn/src/verifier/sign-counter.md | 50 + .../webauthn/src/verifier/verify-assertion.md | 68 ++ .../src/verifier/verify-attestation.md | 69 ++ docs/localization/README.md | 35 + docs/localization/_intro.md | 3 + docs/localization/i18n/README.md | 31 + docs/localization/i18n/_intro.md | 1 + .../i18n/i18n-backend-chained/README.md | 45 + .../src/backend/backend.md | 110 +++ .../src/factory/factory.md | 68 ++ .../src/observability/observability.md | 73 ++ .../i18n/i18n-backend-fs-multifile/README.md | 57 ++ .../src/backend/backend.md | 125 +++ .../src/factory/factory.md | 72 ++ .../src/observability/observability.md | 92 ++ .../i18n/i18n-backend-http/README.md | 96 ++ .../i18n-backend-http/src/backend/backend.md | 119 +++ .../i18n-backend-http/src/factory/factory.md | 76 ++ .../src/observability/observability.md | 75 ++ .../i18n/i18n-backend-memory/README.md | 121 +++ .../src/backend/backend.md | 129 +++ .../src/factory/factory.md | 84 ++ .../src/observability/observability.md | 113 +++ .../i18n/i18n-backend-storage/README.md | 130 +++ .../src/backend/backend.md | 167 ++++ .../src/factory/factory.md | 94 ++ .../src/observability/observability.md | 132 +++ .../localization/i18n/i18n-detector/README.md | 154 +++ .../src/chain/bcp47-negotiate.md | 75 ++ .../i18n/i18n-detector/src/chain/chain.md | 105 +++ .../src/default-chain/default-chain.md | 87 ++ .../accept-language/accept-language.md | 86 ++ .../cloudflare-ip-geo/cloudflare-ip-geo.md | 87 ++ .../src/detectors/cookie/cookie.md | 88 ++ .../src/detectors/fallback/fallback.md | 75 ++ .../src/detectors/html-lang/html-lang.md | 76 ++ .../detectors/local-storage/local-storage.md | 80 ++ .../src/detectors/navigator/navigator.md | 85 ++ .../src/detectors/querystring/querystring.md | 77 ++ .../user-preference/user-preference.md | 86 ++ .../i18n-detector/src/direction/direction.md | 78 ++ .../src/observability/metrics.md | 94 ++ .../i18n/i18n-formatter-collator/README.md | 104 +++ .../src/formatter/formatter.md | 121 +++ .../src/helpers/helpers.md | 107 +++ .../src/observability/observability.md | 100 ++ .../i18n/i18n-formatter-currency/README.md | 119 +++ .../src/formatter/formatter.md | 103 ++ .../src/helpers/helpers.md | 74 ++ .../src/observability/observability.md | 91 ++ .../i18n/i18n-formatter-date/README.md | 128 +++ .../src/day-month-names/day-month-names.md | 112 +++ .../src/formatter/formatter.md | 133 +++ .../src/helpers/helpers.md | 91 ++ .../src/observability/observability.md | 98 ++ .../src/presets/presets.md | 100 ++ .../i18n-formatter-display-name/README.md | 106 +++ .../src/formatter/formatter.md | 98 ++ .../src/helpers/helpers.md | 98 ++ .../src/observability/observability.md | 98 ++ .../i18n/i18n-formatter-list/README.md | 107 +++ .../src/formatter/formatter.md | 82 ++ .../src/helpers/helpers.md | 60 ++ .../src/observability/observability.md | 91 ++ .../i18n/i18n-formatter-number/README.md | 113 +++ .../src/formatter/formatter.md | 86 ++ .../src/helpers/helpers.md | 70 ++ .../src/observability/observability.md | 88 ++ .../i18n-formatter-relative-time/README.md | 109 +++ .../src/formatter/formatter.md | 82 ++ .../src/helpers/helpers.md | 73 ++ .../src/observability/observability.md | 91 ++ .../i18n/i18n-formatter-segmenter/README.md | 111 +++ .../src/formatter/formatter.md | 127 +++ .../src/helpers/helpers.md | 105 +++ .../src/observability/observability.md | 98 ++ .../i18n/i18n-icu-parser/README.md | 182 ++++ .../src/interpolation/escape-html.md | 96 ++ .../src/interpolation/escape-regex.md | 85 ++ .../src/interpolation/interpolation.md | 111 +++ .../src/observability/metrics.md | 97 ++ .../src/parser/format-bridge.md | 142 +++ .../src/parser/message-render.md | 117 +++ .../i18n-icu-parser/src/parser/message.md | 99 ++ .../src/pluralization/pluralization.md | 98 ++ docs/localization/i18n/i18n-shared/README.md | 114 +++ .../src/constants/interpolation-defaults.md | 77 ++ .../src/constants/locale-bcp47-map.md | 74 ++ .../src/constants/locale-descriptors.md | 91 ++ .../i18n-shared/src/constants/rtl-locales.md | 81 ++ .../i18n-shared/src/errors/error-codes.md | 109 +++ .../i18n/i18n-shared/src/errors/i18n-error.md | 106 +++ .../i18n-shared/src/testing/conformance.md | 129 +++ docs/localization/i18n/i18n/README.md | 180 ++++ .../i18n/i18n/src/core/catalog/catalog.md | 127 +++ .../i18n/i18n/src/core/plugin/instance.md | 92 ++ .../src/locale/negotiation/negotiation.md | 78 ++ .../i18n/i18n/src/locale/resolver/resolver.md | 101 ++ .../i18n/i18n/src/middleware/server/server.md | 100 ++ .../i18n/src/observability/backend-metrics.md | 76 ++ .../src/observability/detector-metrics.md | 113 +++ .../i18n/i18n/src/observability/metrics.md | 59 ++ .../format-bridge-default.md | 123 +++ .../post-processors/missing-key-reporter.md | 144 +++ .../src/post-processors/pseudo-localize.md | 61 ++ .../i18n/i18n/src/schemas/i18n.schemas.md | 96 ++ .../localization/i18n/i18n/src/utils/utils.md | 120 +++ docs/localization/i18n/locale-data/README.md | 122 +++ .../src/countries/countries.data.md | 69 ++ .../locale-data/src/countries/countries.md | 120 +++ .../src/errors/locale-data-error.md | 100 ++ .../src/languages/languages.data.md | 78 ++ .../locale-data/src/languages/languages.md | 119 +++ .../i18n/locale-data/src/types/types.md | 112 +++ docs/localization/i18n/react-i18n/README.md | 656 +++++++++++++ .../i18n-suspense/fallback-bundle.md | 72 ++ .../components/i18n-suspense/i18n-suspense.md | 122 +++ .../language-switcher/language-switcher.md | 138 +++ .../missing-key-overlay.md | 106 +++ .../components/trans/stringify-children.md | 85 ++ .../react-i18n/src/components/trans/trans.md | 143 +++ .../src/config/create-i18n-config.md | 105 +++ .../src/config/to-i18n-instance-options.md | 98 ++ .../accept-language/accept-language.md | 82 ++ .../cloudflare-ip-geo/cloudflare-ip-geo.md | 83 ++ .../react-i18n/src/detector/cookie/cookie.md | 83 ++ .../detector/default-chain/default-chain.md | 91 ++ .../src/detector/fallback/fallback.md | 67 ++ .../src/detector/html-lang/html-lang.md | 67 ++ .../detector/local-storage/local-storage.md | 80 ++ .../src/detector/navigator/navigator.md | 72 ++ .../src/detector/querystring/querystring.md | 88 ++ .../user-preference/user-preference.md | 98 ++ .../i18n/react-i18n/src/errors/error-codes.md | 87 ++ .../hoc/with-translation/with-translation.md | 138 +++ .../src/hooks/use-currency/use-currency.md | 95 ++ .../react-i18n/src/hooks/use-date/use-date.md | 85 ++ .../src/hooks/use-direction/use-direction.md | 83 ++ .../use-error-message/use-error-message.md | 112 +++ .../src/hooks/use-formatter/use-formatter.md | 96 ++ .../react-i18n/src/hooks/use-i18n/use-i18n.md | 96 ++ .../react-i18n/src/hooks/use-list/use-list.md | 86 ++ .../use-locale-adapter/use-locale-adapter.md | 71 ++ .../detector-chain-context.md | 96 ++ .../use-locale-detection.md | 156 ++++ .../src/hooks/use-locale/use-locale.md | 94 ++ .../src/hooks/use-number/use-number.md | 88 ++ .../src/hooks/use-plural/use-plural.md | 104 +++ .../use-relative-time/use-relative-time.md | 86 ++ .../src/hooks/use-translate/use-translate.md | 96 ++ .../hooks/use-translation/use-translation.md | 114 +++ .../src/observability/react-i18n-metrics.md | 152 +++ .../src/provider/provider-context.md | 101 ++ .../i18n/react-i18n/src/provider/provider.md | 170 ++++ .../registry/formatters/built-in/built-in.md | 129 +++ .../locale-adapters/built-in/built-in.md | 78 ++ .../post-processors/post-processors.md | 90 ++ .../src/registry/registry-context.md | 54 ++ .../src/registry/registry-provider.md | 97 ++ .../i18n/react-i18n/src/registry/registry.md | 158 ++++ .../src/registry/registry.schemas.md | 68 ++ .../react-i18n/src/registry/use-registry.md | 59 ++ .../src/schemas/i18n-config.schemas.md | 147 +++ .../src/translation-key/t-dynamic.md | 135 +++ .../src/translation-key/translation-key.md | 129 +++ .../i18n/react-i18n/src/utils/env.md | 90 ++ .../react-i18n/src/utils/identity-instance.md | 114 +++ .../src/utils/warn-once-per-process.md | 119 +++ docs/media/README.md | 126 +++ docs/media/_intro.md | 3 + docs/media/audio-fx/README.md | 38 + docs/media/audio-fx/_intro.md | 1 + .../audio-fx-plugin-audio-analyzer/README.md | 31 + .../src/audio-analyzer.types.md | 84 ++ .../src/audio-analyzer/audio-analyzer.md | 91 ++ .../src/schemas/schemas.md | 58 ++ .../audio-fx-plugin-audio-player/README.md | 31 + .../src/audio-player.types.md | 78 ++ .../src/audio-player/audio-player.md | 91 ++ .../src/schemas/schemas.md | 58 ++ .../audio-fx-plugin-auto-filter/README.md | 31 + .../src/auto-filter.types.md | 61 ++ .../src/auto-filter/auto-filter.md | 71 ++ .../src/schemas/schemas.md | 58 ++ .../audio-fx/audio-fx-plugin-base/README.md | 83 ++ .../src/base/audio-fx-plugin.md | 151 +++ .../src/base/capabilities.md | 69 ++ .../src/base/parameter-schedule.md | 68 ++ .../base/plugin-internals/plugin-internals.md | 102 ++ .../src/base/plugin-io.md | 83 ++ .../audio-fx-plugin-base/src/base/preset.md | 83 ++ .../audio-fx-plugin-base/src/biquad/biquad.md | 75 ++ .../src/chain/ambient-state.md | 78 ++ .../src/chain/bus-registry.md | 77 ++ .../audio-fx-plugin-base/src/chain/chain.md | 110 +++ .../src/chain/context/context.md | 80 ++ .../src/chain/event-bus/event-bus.md | 68 ++ .../src/chain/insert/insert.md | 92 ++ .../src/chain/lifecycle/lifecycle.md | 79 ++ .../src/chain/snapshot/snapshot.md | 94 ++ .../src/error-codes/error-codes.md | 74 ++ .../src/registry/registry.md | 82 ++ .../audio-fx/audio-fx-plugin-chorus/README.md | 31 + .../src/chorus.types.md | 50 + .../src/chorus/chorus.md | 70 ++ .../src/schemas/schemas.md | 57 ++ .../audio-fx-plugin-compressor/README.md | 31 + .../src/compressor/compressor.md | 85 ++ .../src/schemas/schemas.md | 61 ++ .../audio-fx/audio-fx-plugin-delay/README.md | 31 + .../audio-fx-plugin-delay/src/delay/delay.md | 72 ++ .../src/schemas/schemas.md | 64 ++ .../audio-fx-plugin-distortion/README.md | 31 + .../src/distortion.types.md | 69 ++ .../src/distortion/distortion.md | 76 ++ .../src/schemas/schemas.md | 66 ++ .../audio-fx/audio-fx-plugin-eq/README.md | 46 + .../audio-fx/audio-fx-plugin-eq/src/eq/eq.md | 82 ++ .../audio-fx-plugin-eq/src/schemas/schemas.md | 71 ++ .../audio-fx/audio-fx-plugin-filter/README.md | 31 + .../src/filter/filter.md | 80 ++ .../src/schemas/schemas.md | 63 ++ .../audio-fx-plugin-flanger/README.md | 31 + .../src/flanger.types.md | 50 + .../src/flanger/flanger.md | 69 ++ .../src/schemas/schemas.md | 56 ++ .../audio-fx-plugin-game-audio/README.md | 31 + .../src/game-audio.types.md | 83 ++ .../src/game-audio/game-audio.md | 83 ++ .../src/schemas/schemas.md | 72 ++ .../audio-fx/audio-fx-plugin-gate/README.md | 31 + .../audio-fx-plugin-gate/src/gate/gate.md | 74 ++ .../src/schemas/schemas.md | 61 ++ .../audio-fx/audio-fx-plugin-glados/README.md | 31 + .../src/glados.types.md | 78 ++ .../src/glados/glados.md | 76 ++ .../src/schemas/schemas.md | 60 ++ .../audio-fx-plugin-limiter/README.md | 31 + .../src/limiter.types.md | 51 + .../src/limiter/limiter.md | 70 ++ .../src/schemas/schemas.md | 48 + .../audio-fx-plugin-microphone/README.md | 31 + .../src/microphone.types.md | 70 ++ .../src/microphone/microphone.md | 89 ++ .../src/schemas/schemas.md | 68 ++ .../audio-fx/audio-fx-plugin-mixer/README.md | 31 + .../audio-fx-plugin-mixer/src/mixer.types.md | 85 ++ .../audio-fx-plugin-mixer/src/mixer/mixer.md | 84 ++ .../src/schemas/schemas.md | 65 ++ .../audio-fx/audio-fx-plugin-phaser/README.md | 31 + .../src/phaser.types.md | 51 + .../src/phaser/phaser.md | 70 ++ .../src/schemas/schemas.md | 57 ++ .../audio-fx-plugin-pitch-shifter/README.md | 31 + .../src/pitch-shifter.types.md | 49 + .../src/pitch-shifter/pitch-shifter.md | 66 ++ .../src/schemas/schemas.md | 57 ++ .../audio-fx/audio-fx-plugin-reverb/README.md | 33 + .../src/engines/engines.md | 97 ++ .../src/reverb/reverb.md | 83 ++ .../src/schemas/schemas.md | 70 ++ .../audio-fx-plugin-sampler/README.md | 31 + .../src/sampler.types.md | 67 ++ .../src/sampler/sampler.md | 90 ++ .../src/schemas/schemas.md | 54 ++ .../audio-fx-plugin-spatial/README.md | 31 + .../src/schemas/schemas.md | 66 ++ .../src/spatial.types.md | 74 ++ .../src/spatial/spatial.md | 75 ++ .../audio-fx-plugin-spessasynth/README.md | 119 +++ .../src/error-codes/error-codes.md | 69 ++ .../src/loader/soundfont-loader.md | 62 ++ .../src/midi-router/midi-router.md | 68 ++ .../src/parameters/parameters.md | 67 ++ .../src/plugin/spessasynth-plugin.md | 91 ++ .../src/register/register.md | 58 ++ .../src/telemetry/telemetry.md | 68 ++ .../src/types/midi.types.md | 85 ++ .../src/voice-manager/voice-manager.md | 66 ++ .../audio-fx-plugin-synthesizer/README.md | 31 + .../src/schemas/schemas.md | 59 ++ .../src/synthesizer.types.md | 77 ++ .../src/synthesizer/synthesizer.md | 87 ++ .../audio-fx-plugin-tremolo/README.md | 31 + .../src/schemas/schemas.md | 66 ++ .../src/tremolo.types.md | 64 ++ .../src/tremolo/tremolo.md | 72 ++ .../audio-fx-plugin-widener/README.md | 31 + .../src/schemas/schemas.md | 56 ++ .../src/widener.types.md | 47 + .../src/widener/widener.md | 61 ++ docs/media/audio-ir/README.md | 16 + docs/media/audio-ir/_intro.md | 1 + docs/media/audio-ir/audio-ir-core/README.md | 110 +++ .../src/error-codes/error-codes.md | 85 ++ .../audio-ir/audio-ir-core/src/otel/otel.md | 107 +++ .../audio-ir-core/src/registrar/registrar.md | 110 +++ .../src/registry/register-manifest.md | 86 ++ .../audio-ir-core/src/registry/registry.md | 115 +++ .../src/types/impulse-response.md | 98 ++ .../audio-ir-core/src/types/manifest-entry.md | 91 ++ .../audio-ir-core/src/types/manifest.md | 97 ++ docs/media/audio-ir/audio-ir-loader/README.md | 79 ++ .../audio-ir-loader/src/cache/cache.md | 101 ++ .../src/error-codes/error-codes.md | 102 ++ .../audio-ir-loader/src/loader/extension.md | 90 ++ .../audio-ir-loader/src/loader/loader.md | 105 +++ .../src/loader/manifest-validation.md | 88 ++ .../audio-ir-loader/src/loader/preload.md | 82 ++ .../audio-ir/audio-ir-loader/src/otel/otel.md | 114 +++ .../audio-ir-room-plugin-club/README.md | 86 ++ .../src/manifest/manifest.md | 65 ++ .../src/register/register.md | 130 +++ .../audio-ir-room-plugin-pool/README.md | 74 ++ .../src/manifest/manifest.md | 89 ++ .../src/register/register.md | 124 +++ docs/media/audio/README.md | 36 + docs/media/audio/_intro.md | 1 + .../media/audio/audio-analysis-beat/README.md | 68 ++ .../src/algorithms/beat-grid.md | 87 ++ .../src/algorithms/comb-tempo.md | 91 ++ .../src/algorithms/energy-odf.md | 91 ++ .../src/algorithms/spectral-flux.md | 98 ++ .../src/detector/beat-detector.md | 123 +++ .../src/error-codes/error-codes.md | 95 ++ .../audio/audio-analysis-loudness/README.md | 56 ++ .../src/algorithms/loudness-range.md | 66 ++ .../src/algorithms/lufs.md | 57 ++ .../src/algorithms/true-peak.md | 56 ++ .../src/error-codes/error-codes.md | 77 ++ .../src/filters/k-weighting.md | 71 ++ .../src/meter/loudness-meter.md | 85 ++ .../audio/audio-analysis-pitch/README.md | 63 ++ .../src/algorithms/chord-matching.md | 54 ++ .../src/algorithms/chromagram.md | 51 + .../src/algorithms/downmix.md | 48 + .../src/algorithms/key-finding.md | 47 + .../src/algorithms/yin.md | 57 ++ .../src/detector/chord-detector.md | 49 + .../src/detector/key-detector.md | 51 + .../src/detector/pitch-detector.md | 51 + .../src/error-codes/error-codes.md | 64 ++ .../audio/audio-analysis-spectrum/README.md | 62 ++ .../src/algorithms/dct.md | 44 + .../src/algorithms/fft.md | 50 + .../src/algorithms/mel-scale.md | 58 ++ .../src/algorithms/window.md | 56 ++ .../src/analyzer/dsp.md | 69 ++ .../src/analyzer/mfcc.md | 51 + .../src/analyzer/runtime.md | 57 ++ .../src/analyzer/spectrogram.md | 48 + .../src/analyzer/spectrum-analyzer.md | 62 ++ .../src/error-codes/error-codes.md | 57 ++ docs/media/audio/audio-cli/README.md | 104 +++ docs/media/audio/audio-cli/src/bin/bin.md | 59 ++ docs/media/audio/audio-cli/src/cli/cli.md | 76 ++ .../audio/audio-cli/src/commands/analyze.md | 63 ++ .../audio/audio-cli/src/commands/batch.md | 70 ++ .../audio/audio-cli/src/commands/convert.md | 63 ++ .../audio/audio-cli/src/commands/info.md | 70 ++ .../audio/audio-cli/src/commands/play.md | 60 ++ .../audio/audio-cli/src/commands/process.md | 66 ++ .../audio/audio-cli/src/commands/record.md | 62 ++ .../audio-cli/src/error-codes/error-codes.md | 79 ++ .../audio/audio-cli/src/pipeline/parser.md | 69 ++ .../audio/audio-codec-ffmpeg-native/README.md | 81 ++ .../src/binary/binary.md | 79 ++ .../src/codec/codec.md | 96 ++ .../src/codec/pcm.md | 79 ++ .../src/error-codes/error-codes.md | 90 ++ .../src/register/register.md | 77 ++ .../src/runner/runner.md | 99 ++ .../src/stream/stream-decoder.md | 80 ++ .../src/stream/stream-encoder.md | 75 ++ .../audio/audio-codec-ffmpeg-wasm/README.md | 127 +++ .../src/codec/ffmpeg-wasm-codec.md | 88 ++ .../src/core-loader/core-loader.md | 78 ++ .../src/decode/decode-pipeline.md | 82 ++ .../src/encode/encode-pipeline.md | 84 ++ .../src/error-codes/error-codes.md | 77 ++ .../src/register/register.md | 70 ++ .../src/streaming/streaming-decoder.md | 73 ++ .../src/streaming/streaming-encoder.md | 71 ++ .../src/worker/worker-host.md | 99 ++ docs/media/audio/audio-codecs/README.md | 144 +++ .../audio/audio-codecs/src/codecs/aac.md | 72 ++ .../audio/audio-codecs/src/codecs/aiff.md | 117 +++ .../audio/audio-codecs/src/codecs/caf.md | 109 +++ .../audio/audio-codecs/src/codecs/flac.md | 80 ++ .../audio/audio-codecs/src/codecs/mp3.md | 100 ++ .../audio-codecs/src/codecs/ogg-vorbis.md | 82 ++ .../audio/audio-codecs/src/codecs/opus.md | 73 ++ .../audio/audio-codecs/src/codecs/qoa.md | 74 ++ .../audio-codecs/src/codecs/wasm-base.md | 136 +++ .../audio/audio-codecs/src/codecs/wav.md | 150 +++ .../audio/audio-codecs/src/codecs/webm.md | 74 ++ .../audio-codecs/src/decode/decode-source.md | 123 +++ .../audio-codecs/src/detect/detect-format.md | 131 +++ .../audio-codecs/src/encode/encode-to.md | 128 +++ .../src/error-codes/error-codes.md | 129 +++ .../audio-codecs/src/registry/registry.md | 141 +++ .../audio-codecs/src/stream/stream-decoder.md | 100 ++ .../audio-codecs/src/stream/stream-encoder.md | 110 +++ docs/media/audio/audio-controllers/README.md | 75 ++ .../src/arpeggiator/arpeggiator.md | 60 ++ .../src/base/connection-fsm.md | 63 ++ .../src/base/midi-controller-plugin.md | 79 ++ .../audio/audio-controllers/src/base/otel.md | 65 ++ .../src/binding/bind-parameter.md | 73 ++ .../src/error-codes/error-codes.md | 72 ++ .../audio-controllers/src/learn/learn-mode.md | 61 ++ .../src/plugins/kontrol-s88/kontrol-s88.md | 68 ++ .../src/plugins/maschine/maschine.md | 70 ++ .../src/plugins/traktor-s4/traktor-s4.md | 70 ++ .../src/sequencer/sequencer.md | 65 ++ docs/media/audio/audio-core/README.md | 101 ++ .../audio-core/src/analysis/analysis-op.md | 107 +++ .../audio/audio-core/src/document/document.md | 262 ++++++ .../audio-core/src/error-codes/error-codes.md | 115 +++ docs/media/audio/audio-core/src/page/page.md | 141 +++ .../audio/audio-core/src/plan/plan-engine.md | 132 +++ .../audio/audio-core/src/plan/segment.md | 108 +++ .../audio-core/src/process/block-processor.md | 190 ++++ .../src/process/process-pipeline.md | 126 +++ .../audio-core/src/registry/built-in/crop.md | 78 ++ .../src/registry/built-in/dither.md | 79 ++ .../audio-core/src/registry/built-in/fade.md | 73 ++ .../audio-core/src/registry/built-in/gain.md | 73 ++ .../src/registry/built-in/insert.md | 78 ++ .../audio-core/src/registry/built-in/mix.md | 73 ++ .../src/registry/built-in/normalize.md | 72 ++ .../audio-core/src/registry/built-in/pad.md | 74 ++ .../audio-core/src/registry/built-in/pan.md | 79 ++ .../src/registry/built-in/remove.md | 78 ++ .../src/registry/built-in/repeat.md | 77 ++ .../src/registry/built-in/resample.md | 73 ++ .../src/registry/built-in/reverse.md | 79 ++ .../audio-core/src/registry/built-in/speed.md | 73 ++ .../src/registry/built-in/stretch.md | 77 ++ .../src/registry/built-in/transform.md | 76 ++ .../audio-core/src/registry/built-in/trim.md | 78 ++ .../audio-core/src/registry/op-registry.md | 110 +++ .../audio/audio-core/src/render/render.md | 66 ++ .../media/audio/audio-core/src/stats/stats.md | 72 ++ .../audio/audio-core/src/stream/stream.md | 82 ++ .../audio-core/src/telemetry/telemetry.md | 90 ++ docs/media/audio/audio-decode-wav/README.md | 81 ++ .../src/decode-wav/decode-wav.md | 65 ++ .../src/error-codes/error-codes.md | 66 ++ .../audio/audio-decode-wav/src/otel/otel.md | 68 ++ .../audio-decode-wav/src/stream/stream.md | 68 ++ .../src/types/decoded-audio.md | 57 ++ .../audio-decode-wav/src/types/options.md | 46 + .../audio-decode-wav/src/utils/inspect.md | 60 ++ .../audio/audio-engine-browser/README.md | 114 +++ .../src/adapter/adapter-introspection.md | 87 ++ .../src/adapter/adapter-lifecycle.md | 107 +++ .../src/adapter/adapter-track-ops.md | 106 +++ .../src/adapter/browser-adapter.md | 161 ++++ .../src/adapter/bus-orchestrator.md | 113 +++ .../src/adapter/fx-host.md | 95 ++ .../src/adapter/mixer-state.md | 100 ++ .../standardized-audio-context-bridge.md | 81 ++ .../src/adapter/track-subgraph.md | 101 ++ .../audio-engine-browser/src/decode/decode.md | 65 ++ .../src/error-codes/error-codes.md | 112 +++ .../src/fallback/html5-fallback.md | 122 +++ .../src/graph/web-audio-graph.md | 131 +++ .../src/offline/offline-render.md | 102 ++ .../src/worklet/worklet-manager.md | 127 +++ .../media/audio/audio-engine-server/README.md | 72 ++ .../src/adapter/bus-orchestrator.md | 64 ++ .../src/adapter/server-adapter.md | 97 ++ .../src/fx/plugin-chain.md | 98 ++ .../src/internal/fs-like.md | 62 ++ .../src/internal/sanitize-path.md | 58 ++ .../audio-engine-server/src/sink/file-sink.md | 76 ++ .../src/source/file-source.md | 83 ++ docs/media/audio/audio-fingerprint/README.md | 88 ++ .../audio/audio-fingerprint/src/api/app.md | 83 ++ .../src/client/python-audio-service.md | 109 +++ .../audio-fingerprint/src/fingerprint.md | 64 ++ docs/media/audio/audio-metadata/README.md | 132 +++ .../src/core/extractor/extractor.md | 90 ++ .../src/errors/metadata-error.md | 87 ++ .../src/parsers/aiff-id3/aiff-id3.md | 73 ++ .../src/parsers/flac-vorbis/flac-vorbis.md | 77 ++ .../format-detector/format-detector.md | 65 ++ .../audio-metadata/src/parsers/id3v1/id3v1.md | 78 ++ .../audio-metadata/src/parsers/id3v2/id3v2.md | 103 ++ .../src/parsers/mp4-atom/mp4-atom.md | 72 ++ .../src/parsers/ogg-vorbis/ogg-vorbis.md | 61 ++ .../src/parsers/wav-riff/wav-riff.md | 65 ++ .../src/types/metadata.types.md | 127 +++ .../audio-metadata/src/utils/buffer-utils.md | 97 ++ .../media/audio/audio-sprite-packer/README.md | 54 ++ .../audio-sprite-packer.bench.md | 32 + .../src/adapters/null-adapter/null-adapter.md | 114 +++ .../audio-sprite-packer.md | 140 +++ .../src/error-codes/error-codes.md | 122 +++ .../audio-sprite-packer/src/types/common.md | 174 ++++ .../src/utils/manifest/manifest.md | 90 ++ .../media/audio/audio-sprite-player/README.md | 80 ++ .../src/adapter/adapter.md | 112 +++ .../src/adapter/null/null.md | 94 ++ .../src/error-codes/error-codes.md | 97 ++ .../audio-sprite-player/src/events/events.md | 78 ++ .../src/schemas/schemas.md | 82 ++ .../src/sprite-player/sprite-player.md | 90 ++ .../src/telemetry/telemetry.md | 93 ++ .../src/voice-manager/voice-manager.md | 89 ++ docs/media/audio/audio-timeline/README.md | 41 + .../audio/audio-timeline/SPEC_CHECKLIST.md | 62 ++ .../audio-timeline/src/adapter/adapter.md | 47 + .../audio/audio-timeline/src/clip/clip.md | 49 + .../audio-timeline/src/engine/clip/clip.md | 35 + .../audio/audio-timeline/src/engine/engine.md | 52 ++ .../audio-timeline/src/engine/mixer/mixer.md | 35 + .../audio-timeline/src/engine/state/state.md | 28 + .../src/engine/transport-fsm/transport-fsm.md | 34 + .../src/engine/transport/transport.md | 33 + .../audio-timeline/src/engine/undo/undo.md | 31 + .../audio-timeline/src/engine/zoom/zoom.md | 36 + .../src/error-codes/error-codes.md | 46 + .../audio/audio-timeline/src/mixer/mixer.md | 54 ++ .../clip-operations/clip-operations.md | 50 + .../timeline-operations.md | 50 + .../audio/audio-timeline/src/track/track.md | 49 + .../audio/audio-timeline/src/zoom/zoom.md | 52 ++ docs/media/audio/audio-transport/README.md | 58 ++ .../src/error-codes/error-codes.md | 57 ++ .../src/scheduler/scheduler.md | 58 ++ .../src/scheduler/scheduler.schemas.md | 32 + .../audio-transport/src/signal/signal.md | 63 ++ .../src/signal/signal.schemas.md | 27 + .../src/tick-source/tick-source.md | 67 ++ .../src/tick-source/tick-source.schemas.md | 28 + .../audio/audio-transport/src/time/time.md | 59 ++ .../audio-transport/src/time/time.schemas.md | 36 + .../src/transport/transport.md | 92 ++ .../src/transport/transport.schemas.md | 33 + .../audio/control-surface-schema/README.md | 210 +++++ .../src/constants/constants.md | 84 ++ .../src/error-codes/error-codes.md | 93 ++ .../src/identity/identity.md | 84 ++ .../src/schemas/control-surface-schema.md | 84 ++ .../src/types/action.types.md | 60 ++ .../src/types/appearance.types.md | 71 ++ .../src/types/behaviour.types.md | 66 ++ .../src/types/binding.types.md | 74 ++ .../src/types/control-kind.types.md | 61 ++ .../src/types/control-node.types.md | 77 ++ .../src/types/control-surface.types.md | 79 ++ .../src/types/group-layout.types.md | 57 ++ .../src/types/range.types.md | 56 ++ .../src/types/transform.types.md | 59 ++ .../src/upgrade/upgrade.md | 85 ++ .../src/validate/validate.md | 76 ++ .../control-surface-schema/src/walk/walk.md | 67 ++ docs/media/audio/midi/README.md | 90 ++ docs/media/audio/midi/src/clock/clock.md | 67 ++ docs/media/audio/midi/src/dispatch/cc14.md | 53 ++ docs/media/audio/midi/src/dispatch/nrpn.md | 59 ++ docs/media/audio/midi/src/dispatch/rpn.md | 58 ++ .../audio/midi/src/dispatch/running-status.md | 53 ++ .../audio/midi/src/error-codes/error-codes.md | 57 ++ docs/media/audio/midi/src/gm/gs.md | 49 + docs/media/audio/midi/src/gm/level1.md | 51 + docs/media/audio/midi/src/gm/level2.md | 51 + docs/media/audio/midi/src/gm/xg.md | 48 + docs/media/audio/midi/src/message/decode.md | 57 ++ docs/media/audio/midi/src/message/encode.md | 61 ++ .../audio/midi/src/sysex/manufacturers.md | 63 ++ docs/media/audio/midi/src/sysex/sysex.md | 56 ++ .../audio/midi/src/telemetry/telemetry.md | 63 ++ docs/media/audio/midi/src/ump/ump.md | 63 ++ .../audio/third-party-elevenlabs/README.md | 17 + .../src/client/client.md | 109 +++ .../src/client/headers.md | 89 ++ .../src/client/internals.md | 96 ++ .../src/client/socket.md | 108 +++ .../third-party-elevenlabs/src/client/url.md | 74 ++ .../src/errors/errors.md | 148 +++ .../third-party-elevenlabs/src/types/types.md | 153 +++ docs/media/audio/voice-elevenlabs/README.md | 143 +++ .../src/factory/create-elevenlabs-voice.md | 116 +++ .../voice-elevenlabs/src/models/models.md | 89 ++ .../src/sound-effects/sound-effects.md | 93 ++ .../src/speech-to-speech/speech-to-speech.md | 104 +++ .../audio/voice-elevenlabs/src/stt/stt.md | 105 +++ .../audio/voice-elevenlabs/src/tts/tts.md | 122 +++ .../src/voice-isolation/voice-isolation.md | 92 ++ .../voice-elevenlabs/src/voices/voices.md | 100 ++ docs/media/audio/voice/README.md | 88 ++ docs/media/audio/voice/src/effects/effects.md | 98 ++ docs/media/audio/voice/src/errors/errors.md | 122 +++ .../audio/voice/src/isolation/isolation.md | 96 ++ docs/media/audio/voice/src/stt/stt.md | 125 +++ docs/media/audio/voice/src/tts/tts.md | 109 +++ docs/media/audio/voice/src/types/types.md | 121 +++ docs/media/audio/voice/src/voices/voices.md | 111 +++ docs/media/fonts/README.md | 16 + docs/media/fonts/_intro.md | 1 + docs/media/fonts/font-compress/README.md | 111 +++ .../fonts/font-compress/src/bin/auto-boot.md | 69 ++ .../fonts/font-compress/src/bin/dispatch.md | 77 ++ .../font-compress/src/bin/format-utils.md | 86 ++ .../fonts/font-compress/src/bin/parser.md | 74 ++ .../fonts/font-compress/src/bin/printer.md | 79 ++ .../src/bin/suaveplan-font-compress.md | 123 +++ .../src/error-codes/error-codes.md | 78 ++ .../binary-font-packer/binary-font-packer.md | 99 ++ .../font-compress/src/utils/encode-string.md | 60 ++ .../font-compress/src/utils/parse-path.md | 67 ++ docs/media/fonts/font-convert/README.md | 56 ++ .../core/batch-converter/batch-converter.md | 102 ++ .../src/core/font-converter/font-converter.md | 97 ++ .../fonts/font-convert/src/types/typeface.md | 125 +++ .../src/utils/outline-to-string.md | 76 ++ .../font-convert/src/utils/reverse-winding.md | 66 ++ docs/media/fonts/font-decompress/README.md | 131 +++ .../src/error-codes/error-codes.md | 115 +++ .../binary-font-unpacker.md | 134 +++ .../src/utils/decode-string.md | 96 ++ docs/media/fonts/font-subset/README.md | 125 +++ .../font-subset/src/adapters/null/null.md | 76 ++ .../core/font-compressor/font-compressor.md | 103 ++ .../fonts/font-subset/src/types/common.md | 107 +++ .../font-subset/src/utils/format-detect.md | 56 ++ .../font-subset/src/utils/unicode-ranges.md | 65 ++ docs/media/image/README.md | 27 + docs/media/image/_intro.md | 1 + docs/media/image/caddy-imgproxy/README.md | 101 ++ .../image/caddy-imgproxy/src/config/config.md | 86 ++ .../src/dimensions/calculate-dimensions.md | 77 ++ .../src/domain/extract-domain.md | 67 ++ .../src/error-codes/error-codes.md | 101 ++ .../caddy-imgproxy/src/gravity/gravity.md | 74 ++ .../caddy-imgproxy/src/handler/handler.md | 121 +++ .../caddy-imgproxy/src/operation/operation.md | 76 ++ .../caddy-imgproxy/src/parse/parse-url.md | 98 ++ .../caddy-imgproxy/src/signing/sign-path.md | 95 ++ .../caddy-imgproxy/src/telemetry/telemetry.md | 89 ++ .../image/caddy-imgproxy/src/types/types.md | 98 ++ .../src/url-builder/url-builder.md | 92 ++ .../image/colour-convert-adapt/README.md | 29 + .../colour-convert-adapt/src/adapt/adapt.md | 48 + .../image/colour-convert-cieluv/README.md | 32 + .../colour-convert-cieluv.md | 67 ++ .../media/image/colour-convert-cmyk/README.md | 32 + .../colour-convert-cmyk/src/cmyk/cmyk.md | 47 + .../image/colour-convert-hsluv/README.md | 32 + .../colour-convert-hsluv.md | 53 ++ docs/media/image/colour-filter-cct/README.md | 32 + .../colour-filter-cct/colour-filter-cct.md | 52 ++ docs/media/image/colour-filter-cmc/README.md | 29 + .../colour-filter-cmc/colour-filter-cmc.md | 43 + .../image/colour-filter-greyscale/README.md | 29 + .../src/greyscale/greyscale.md | 44 + .../media/image/colour-filter-sepia/README.md | 29 + .../colour-filter-sepia/src/sepia/sepia.md | 49 + docs/media/image/colours/README.md | 65 ++ .../src/colour-factories/colour-factories.md | 68 ++ .../colours/src/colour/colour-formatters.md | 58 ++ docs/media/image/colours/src/colour/colour.md | 88 ++ .../colours/src/conversions/conversions.md | 76 ++ .../colours/src/error-codes/error-codes.md | 61 ++ docs/media/image/colours/src/errors/errors.md | 65 ++ docs/media/image/colours/src/parser/parser.md | 51 + .../src/types/colour-types/colour-types.md | 61 ++ docs/media/image/colours/src/utils/utils.md | 56 ++ docs/media/image/compress-image/README.md | 65 ++ .../src/adapters/memory/memory.md | 81 ++ .../src/adapters/sharp/sharp.md | 102 ++ .../src/core/compressor/compressor.md | 105 +++ .../src/errors/compress-image-error.md | 82 ++ .../src/schemas/compress-options.schema.md | 103 ++ .../src/types/compress-image.types.md | 149 +++ .../compress-image/src/utils/image-utils.md | 89 ++ docs/media/image/emblem-solver/README.md | 134 +++ .../emblem-solver/src/converter/converter.md | 98 ++ .../image/emblem-solver/src/errors/errors.md | 83 ++ .../emblem-solver/src/fixtures/fixtures.md | 73 ++ .../emblem-solver/src/grid/analyse/analyse.md | 75 ++ .../emblem-solver/src/helpers/helpers.md | 85 ++ .../image/emblem-solver/src/io/parse/parse.md | 71 ++ .../src/optimizer/merge/merge.md | 67 ++ .../src/optimizer/overlap/overlap.md | 73 ++ .../src/optimizer/redundancy/redundancy.md | 61 ++ .../emblem-solver/src/schemas/schemas.md | 79 ++ .../emblem-solver/src/solver/greedy/greedy.md | 72 ++ .../src/solver/histogram/histogram.md | 67 ++ .../emblem-solver/src/solver/layer/layer.md | 84 ++ .../src/solver/ordering/ordering.md | 74 ++ .../emblem-solver/src/solver/strip/strip.md | 64 ++ .../emblem-solver/src/svg/build/build.md | 61 ++ .../emblem-solver/src/telemetry/telemetry.md | 69 ++ .../image/emblem-solver/src/types/types.md | 92 ++ docs/media/image/exif/README.md | 86 ++ .../image/exif/src/binary/crc32/crc32.md | 55 ++ .../exif/src/binary/rational/rational.md | 67 ++ .../exif/src/binary/reader/byte-reader.md | 117 +++ .../exif/src/binary/writer/byte-writer.md | 100 ++ .../image/exif/src/core/read-metadata.md | 65 ++ .../image/exif/src/core/strip-metadata.md | 60 ++ .../image/exif/src/core/write-metadata.md | 64 ++ .../media/image/exif/src/errors/exif-error.md | 99 ++ docs/media/image/exif/src/exif/read-exif.md | 74 ++ docs/media/image/exif/src/format/detect.md | 66 ++ docs/media/image/exif/src/ifd/parse.md | 86 ++ docs/media/image/exif/src/iptc/read-iptc.md | 73 ++ docs/media/image/exif/src/jpeg/segments.md | 83 ++ docs/media/image/exif/src/xmp/read-xmp.md | 93 ++ docs/media/image/image-quantisation/README.md | 88 ++ .../src/analysis/classify/classify.md | 66 ++ .../src/analysis/colour/colour.md | 70 ++ .../src/analysis/edges/edges.md | 53 ++ .../src/analysis/pools/pools.md | 56 ++ .../src/errors/image-quantisation-error.md | 70 ++ .../src/pipeline/pipeline.md | 67 ++ .../src/quantise/quantise.md | 66 ++ .../src/schemas/options.schema.md | 70 ++ .../src/spatial/cleanup/cleanup.md | 69 ++ .../image-quantisation/src/types/common.md | 114 +++ docs/media/image/image/README.md | 59 ++ .../image/src/error-codes/error-codes.md | 66 ++ docs/media/image/image/src/errors/errors.md | 75 ++ .../src/processor/dimensions/dimensions.md | 48 + .../src/processor/instruments/instruments.md | 54 ++ .../pipeline-builder/pipeline-builder.md | 63 ++ .../src/processor/processor/processor.md | 70 ++ .../src/types/image-detect/image-detect.md | 63 ++ .../src/types/image-types/image-types.md | 75 ++ docs/media/video/README.md | 14 + docs/media/video/_intro.md | 1 + docs/media/video/video-thumbnails/README.md | 85 ++ .../src/error-codes/error-codes.md | 80 ++ .../src/errors/video-thumbnails-error.md | 75 ++ .../src/runner/fluent-ffmpeg-runner.md | 81 ++ .../video-thumbnails/src/runner/runner.md | 91 ++ .../video-thumbnails/src/schemas/schemas.md | 76 ++ .../src/sprite-sheet/sprite-sheet.md | 81 ++ .../src/telemetry/telemetry.md | 83 ++ .../thumbnail-generator.md | 91 ++ docs/media/video/video/README.md | 109 +++ .../video/video/src/detection/detection.md | 78 ++ .../video/video/src/duration/duration.md | 73 ++ .../video/src/error-codes/error-codes.md | 96 ++ docs/media/video/video/src/errors/errors.md | 109 +++ docs/media/video/video/src/format/format.md | 64 ++ .../video/src/instruments/instruments.md | 83 ++ .../src/pipeline-builder/pipeline-builder.md | 105 +++ .../video/video/src/processor/processor.md | 117 +++ docs/media/video/video/src/resize/resize.md | 83 ++ docs/media/video/video/src/trim/trim.md | 73 ++ .../src/types/video-types/video-types.md | 111 +++ docs/money/README.md | 43 + docs/money/_intro.md | 3 + docs/money/finance/README.md | 25 + docs/money/finance/_intro.md | 1 + docs/money/finance/cryptocurrency/README.md | 147 +++ .../cryptocurrency/src/address/validator.md | 84 ++ .../cryptocurrency/src/chains/chain-data.md | 62 ++ .../src/chains/chain-registry.md | 126 +++ .../cryptocurrency/src/chains/registry.md | 71 ++ .../src/error-codes/error-codes.md | 94 ++ .../cryptocurrency/src/gas/gas-estimator.md | 119 +++ .../cryptocurrency/src/tokens/token-data.md | 64 ++ .../src/tokens/token-registry.md | 99 ++ .../src/transaction/tx-decoder.md | 108 +++ .../cryptocurrency/src/types/crypto.types.md | 95 ++ .../cryptocurrency/src/units/converter.md | 97 ++ .../currency-provider-binance/README.md | 84 ++ .../src/binance/binance.md | 159 ++++ .../currency-provider-coingecko/README.md | 79 ++ .../src/coin-ids/coin-ids.md | 88 ++ .../src/coingecko/coingecko.md | 114 +++ .../currency-provider-coinmarketcap/README.md | 91 ++ .../src/coinmarketcap/coinmarketcap.md | 160 ++++ .../currency-provider-cryptocompare/README.md | 75 ++ .../src/cryptocompare/cryptocompare.md | 146 +++ .../finance/currency-provider-ecb/README.md | 66 ++ .../currency-provider-ecb/src/ecb/ecb.md | 143 +++ .../finance/currency-provider-fixer/README.md | 89 ++ .../src/fixer/fixer.md | 154 +++ .../currency-provider-kraken/README.md | 87 ++ .../src/provider/provider.md | 130 +++ .../src/symbols/symbols.md | 90 ++ .../README.md | 67 ++ .../src/provider/provider.md | 148 +++ .../currency-provider-virtual/README.md | 92 ++ .../src/error-codes/error-codes.md | 104 +++ .../src/provider/provider.md | 160 ++++ .../finance/currency-providers/README.md | 126 +++ .../src/error-codes/error-codes.md | 110 +++ .../currency-providers/src/factory/factory.md | 132 +++ .../currency-providers/src/http/http.md | 155 ++++ .../src/registry/registry.md | 128 +++ .../currency-providers/src/types/configs.md | 98 ++ docs/money/finance/currency/README.md | 105 +++ .../currency/src/converter/converter.md | 185 ++++ .../currency/src/error-codes/error-codes.md | 105 +++ .../finance/currency/src/provider/provider.md | 108 +++ .../currency/src/rate-cache/rate-cache.md | 91 ++ .../finance/currency/src/schemas/schemas.md | 106 +++ .../finance/currency/src/types/common.md | 112 +++ docs/money/finance/money/README.md | 120 +++ .../finance/money/src/allocator/allocator.md | 144 +++ .../money/src/currencies/currencies.md | 119 +++ .../money/src/error-codes/error-codes.md | 107 +++ .../finance/money/src/formatter/formatter.md | 144 +++ docs/money/finance/money/src/money/money.md | 150 +++ docs/money/finance/money/src/types/common.md | 108 +++ docs/money/payment/README.md | 19 + docs/money/payment/_intro.md | 1 + .../payment/payment-provider-adyen/README.md | 94 ++ .../payment-provider-adyen/src/adyen/adyen.md | 216 +++++ .../src/adyen/mapping.md | 123 +++ .../payment-provider-adyen/src/types/adyen.md | 115 +++ .../payment/payment-provider-mollie/README.md | 72 ++ .../src/mollie/mollie.md | 185 ++++ .../payment/payment-provider-paypal/README.md | 107 +++ .../src/paypal/mapping.md | 146 +++ .../src/paypal/paypal.md | 203 ++++ .../payment/payment-provider-square/README.md | 104 +++ .../src/mapping/payment.md | 126 +++ .../src/mapping/refund.md | 120 +++ .../src/square/square.md | 175 ++++ .../src/types/config.md | 102 ++ .../payment/payment-provider-stripe/README.md | 111 +++ .../src/stripe/stripe.md | 201 ++++ .../money/payment/payment-providers/README.md | 213 +++++ .../src/error-codes/error-codes.md | 99 ++ .../payment-providers/src/http/http.md | 105 +++ .../payment-providers/src/registry/define.md | 119 +++ .../src/registry/registry.md | 117 +++ .../payment-providers/src/types/provider.md | 102 ++ docs/money/payment/payment/README.md | 189 ++++ .../payment/payment/src/engine/engine.md | 145 +++ .../payment/src/error-codes/error-codes.md | 115 +++ docs/money/payment/payment/src/fraud/fraud.md | 103 ++ .../payment/payment/src/gateway/paypal.md | 115 +++ .../payment/payment/src/gateway/stripe.md | 113 +++ .../money/payment/payment/src/gateway/test.md | 91 ++ .../payment/payment/src/gateway/types.md | 123 +++ docs/money/payment/payment/src/hooks/hooks.md | 108 +++ .../payment/payment/src/receipt/receipt.md | 126 +++ .../src/reconciliation/reconciliation.md | 145 +++ .../payment/payment/src/refund/refund.md | 120 +++ docs/money/payment/payment/src/retry/retry.md | 99 ++ docs/money/payment/payment/src/tax/tax.md | 125 +++ .../payment/src/tokenization/tokenization.md | 103 ++ .../payment/payment/src/types/payment.md | 96 ++ .../payment/payment/src/webhook/webhook.md | 116 +++ docs/networking/README.md | 95 ++ docs/networking/_intro.md | 3 + docs/networking/drive/README.md | 26 + docs/networking/drive/_intro.md | 1 + .../drive/drive-mesh-protocol/README.md | 98 ++ .../src/codec/advertise.md | 67 ++ .../drive-mesh-protocol/src/codec/bitset.md | 66 ++ .../drive-mesh-protocol/src/codec/common.md | 53 ++ .../drive-mesh-protocol/src/codec/error.md | 62 ++ .../drive-mesh-protocol/src/codec/request.md | 62 ++ .../drive-mesh-protocol/src/codec/response.md | 64 ++ .../drive-mesh-protocol/src/error-codes.md | 78 ++ .../src/generation/monotonic.md | 62 ++ .../src/generation/throttle.md | 64 ++ .../src/schemas/envelope.schema.md | 61 ++ .../drive-mesh-protocol/src/select/form.md | 103 ++ .../drive-mesh-protocol/src/trust/decay.md | 53 ++ .../drive-mesh-protocol/src/trust/sample.md | 68 ++ .../drive-mesh-protocol/src/trust/score.md | 64 ++ .../src/types/protocol.types.md | 59 ++ docs/networking/drive/drive-mesh/README.md | 158 ++++ .../drive-mesh/src/error-codes/error-codes.md | 93 ++ .../src/gossip/gossip-engine/gossip-engine.md | 116 +++ .../typed-event-emitter.md | 74 ++ .../src/mesh/drive-mesh/drive-mesh.md | 144 +++ .../peer-registry/peer-registry.md | 112 +++ .../parallel-puller/parallel-puller.md | 126 +++ .../server-fallback/server-fallback.md | 105 +++ .../drive-mesh/src/types/config.types.md | 86 ++ .../src/types/drive-transport.types.md | 118 +++ .../drive-mesh/src/types/events.types.md | 105 +++ .../drive/drive-mesh/src/types/peer.types.md | 108 +++ .../drive/drive-plugin-cache/README.md | 129 +++ .../src/error-codes/error-codes.md | 60 ++ .../drive-plugin-cache/src/handle/handle.md | 59 ++ .../src/middleware/middleware.invalidation.md | 53 ++ .../src/middleware/middleware.md | 57 ++ .../src/middleware/middleware.signal.md | 46 + .../drive/drive-plugin-cache/src/otel/otel.md | 64 ++ .../drive-plugin-cache/src/plugin/plugin.md | 66 ++ .../src/types/options.types.md | 52 ++ .../drive/drive-plugin-chunks/README.md | 129 +++ .../drive-plugin-chunks/src/codec/chunk.md | 51 + .../drive-plugin-chunks/src/codec/header.md | 67 ++ .../drive-plugin-chunks/src/error-codes.md | 59 ++ .../src/inline/inline-hint.md | 81 ++ .../drive-plugin-chunks/src/layout/auto.md | 46 + .../src/layout/chunk-keys.md | 54 ++ .../src/layout/sparse-file.md | 51 + .../drive-plugin-chunks/src/manifest/build.md | 48 + .../drive-plugin-chunks/src/manifest/load.md | 54 ++ .../src/manifest/source.md | 44 + .../src/pipeline/decrypt-chunk.md | 57 ++ .../src/pipeline/encrypt-stream.md | 54 ++ .../src/pipeline/sign-chunk.md | 50 + .../src/pipeline/verify-chunk.md | 52 ++ .../drive/drive-plugin-chunks/src/plugin.md | 63 ++ .../src/schemas/manifest.schema.md | 61 ++ .../src/types/chunks.types.md | 60 ++ .../drive/drive-react-sharing/README.md | 127 +++ .../file-access-list/file-access-list.md | 72 ++ .../partition-badge/partition-badge.md | 69 ++ .../components/share-dialog/share-dialog.md | 108 +++ .../drive-react-sharing/src/error-codes.md | 84 ++ .../src/hooks/use-sharing/use-sharing.md | 126 +++ .../src/otel/instruments.md | 75 ++ .../src/types/sharing.types.md | 79 ++ docs/networking/drive/drive-sharing/README.md | 132 +++ .../src/encryption/envelope/envelope.md | 105 +++ .../src/encryption/key-ring/key-ring.md | 90 ++ .../src/error-codes/error-codes.md | 91 ++ .../drive-sharing/src/otel/instruments.md | 94 ++ .../partition-manager/partition-manager.md | 120 +++ .../partition-policy/partition-policy.md | 108 +++ .../partition-store/partition-store.md | 85 ++ .../src/sharing/grants/grants.md | 110 +++ .../src/sharing/tokens/tokens.md | 105 +++ .../src/transfer/transfer/transfer.md | 110 +++ .../drive/drive-sharing/src/types/common.md | 92 ++ .../drive/drive-sharing/src/types/schemas.md | 70 ++ .../drive-storage-archive-core/README.md | 78 ++ .../src/errors/error-codes.md | 67 ++ .../src/factory/open-archive-storage.md | 71 ++ .../src/modes/pending-mutations.md | 81 ++ .../src/modes/validate-mode.md | 64 ++ .../src/password/password-hook.md | 72 ++ .../src/resolvers/rar-sibling-resolver.md | 44 + .../resolvers/seven-zip-sibling-resolver.md | 49 + .../src/resolvers/sibling-host.md | 57 ++ .../src/resolvers/zip-sibling-resolver.md | 56 ++ .../src/sniff/sniff-format.md | 52 ++ .../src/testing/run-archive-conformance.md | 84 ++ .../src/types/archive-capabilities.md | 61 ++ .../src/types/archive-codec.md | 61 ++ .../src/types/archive-format.md | 53 ++ .../src/types/archive-mode.md | 49 + .../src/types/entry-reader.md | 61 ++ .../src/types/open-archive-storage-options.md | 60 ++ .../src/types/password-hook.md | 49 + .../src/types/resolve-sibling.md | 49 + .../drive/drive-storage-zip/README.md | 38 + .../src/errors/error-codes.md | 52 ++ .../central-directory/parse-cdr-entry.md | 42 + .../src/parser/central-directory/walk-cdr.md | 37 + .../src/parser/compression/compress.md | 45 + .../src/parser/compression/decompress.md | 44 + .../drive-storage-zip/src/parser/crc32.md | 38 + .../src/parser/crypto/aes/aes-decrypt.md | 42 + .../src/parser/crypto/aes/aes-write-block.md | 59 ++ .../src/parser/eocd/find-eocd.md | 41 + .../src/parser/eocd/parse-eocd.md | 44 + .../src/parser/eocd/parse-eocd64.md | 55 ++ .../parser/local-header/parse-local-header.md | 38 + .../parser/local-header/read-entry-bytes.md | 38 + .../src/parser/signatures.md | 50 + .../src/storage/encode-zip.md | 42 + .../src/storage/normalize-path.md | 51 + .../src/storage/zip-archive-storage.md | 62 ++ .../src/types/parser.types.md | 45 + .../src/types/storage.types.md | 54 ++ .../networking/drive/drive-template/README.md | 106 +++ .../drive-template/src/cdn/upload-token.md | 70 ++ .../drive-template/src/cdn/url-builder.md | 94 ++ .../drive-template/src/codec/canonical.md | 50 + .../drive/drive-template/src/codec/sign.md | 59 ++ .../drive/drive-template/src/codec/verify.md | 51 + .../drive/drive-template/src/error-codes.md | 95 ++ .../drive-template/src/key/grant-validator.md | 63 ++ .../src/schemas/template.schema.md | 60 ++ .../src/types/template.types.md | 65 ++ .../drive-template/src/validate/depth.md | 53 ++ .../drive/drive-template/src/validate/file.md | 54 ++ .../drive-template/src/validate/order.md | 74 ++ .../drive-template/src/validate/replay.md | 51 + .../drive/drive-transport-https/README.md | 44 + .../drive-transport-https/src/error-codes.md | 61 ++ .../src/schemas/transport.schema.md | 55 ++ .../src/transport/defaults.md | 52 ++ .../src/transport/https-transport.md | 96 ++ .../src/types/transport.types.md | 68 ++ .../drive/drive-transport-webrtc/README.md | 180 ++++ .../src/error-codes/error-codes.md | 91 ++ .../src/framing/frame/frame.md | 96 ++ .../src/schemas/frame.schemas.md | 84 ++ .../webrtc-transport/bitset-codec.md | 77 ++ .../src/transport/webrtc-transport/hex.md | 74 ++ .../webrtc-transport/payload-codec.md | 97 ++ .../webrtc-transport/webrtc-transport.md | 152 +++ docs/networking/drive/drive-uri/README.md | 159 ++++ .../src/adapter/drive-storage-like.md | 90 ++ .../drive-uri/src/conformance/conformance.md | 106 +++ .../drive-uri/src/error-codes/error-codes.md | 98 ++ .../drive/drive-uri/src/otel/otel.md | 92 ++ .../src/plugins/drive-mesh/drive-mesh.md | 91 ++ .../plugins/drive-template/drive-template.md | 112 +++ .../drive-uri/src/plugins/drive/drive.md | 103 ++ .../src/plugins/drive/drive.streams.md | 84 ++ .../src/types/plugin-options.types.md | 95 ++ docs/networking/drive/drive-webrtc/README.md | 395 ++++++++ .../chunk-source/chunk-source/chunk-source.md | 99 ++ .../drive-webrtc/src/client/client/client.md | 157 ++++ .../drive/drive-webrtc/src/client/ice/ice.md | 116 +++ .../src/client/offer-answer/offer-answer.md | 111 +++ .../src/client/reconnect/reconnect.md | 114 +++ .../data-channel-manager.md | 115 +++ .../chunk-discovery-manager.md | 113 +++ .../src/error-codes/error-codes.md | 115 +++ .../typed-event-emitter.md | 107 +++ .../chunk-integrity/chunk-integrity.md | 117 +++ .../chunk-integrity/chunk-integrity.types.md | 77 ++ .../src/lru-cache/lru-cache/lru-cache.md | 101 ++ .../lru-cache/lru-cache/lru-cache.types.md | 73 ++ .../peer-bandwidth-tracker.md | 132 +++ .../peer-bandwidth-tracker.types.md | 94 ++ .../peer-manager/peer-manager/peer-manager.md | 122 +++ .../src/peer-manager/topology/full-mesh.md | 79 ++ .../peer-manager/topology/hub-and-spoke.md | 72 ++ .../src/peer-manager/topology/super-peer.md | 78 ++ .../topology/topology-strategy.md | 94 ++ .../src/plugin/webrtc-plugin/webrtc-plugin.md | 185 ++++ .../rate-limiter/rate-limiter/rate-limiter.md | 122 +++ .../rate-limiter/rate-limiter.types.md | 70 ++ .../src/schemas/config.schemas.md | 126 +++ .../src/schemas/signaling.schemas.md | 95 ++ .../security-validator/security-validator.md | 105 +++ .../signaling-client/signaling-client.md | 165 ++++ .../src/sub-chunk/sub-chunk/sub-chunk.md | 123 +++ .../sub-chunk/sub-chunk/sub-chunk.types.md | 69 ++ .../drive-webrtc/src/types/config.types.md | 103 ++ .../drive-webrtc/src/types/drive.types.md | 151 +++ .../drive-webrtc/src/types/events.types.md | 120 +++ .../drive-webrtc/src/types/messages.types.md | 103 ++ .../drive-webrtc/src/types/peer.types.md | 95 ++ .../drive-webrtc/src/types/stats.types.md | 80 ++ docs/networking/drive/drive/README.md | 67 ++ .../networking/drive/drive/src/drive/drive.md | 115 +++ .../drive/src/drive/file-location-index.md | 58 ++ .../drive/drive/src/drive/get-key-status.md | 53 ++ .../drive/drive/src/drive/get-presence.md | 56 ++ .../drive/drive/src/drive/hydrate-from.md | 46 + .../drive/src/error-codes/error-codes.md | 59 ++ .../drive/drive/src/file-operations/delete.md | 44 + .../drive/drive/src/file-operations/list.md | 39 + .../drive/drive/src/file-operations/read.md | 47 + .../drive/drive/src/file-operations/stat.md | 47 + .../drive/src/file-operations/streams.md | 52 ++ .../drive/drive/src/file-operations/write.md | 47 + .../drive/drive/src/plugins/registry.md | 60 ++ .../drive/src/schemas/drive-options.schema.md | 48 + .../drive/drive/src/types/drive.types.md | 59 ++ docs/networking/events/README.md | 19 + docs/networking/events/_intro.md | 1 + .../events/broadcast-channel/README.md | 114 +++ .../events/broadcast-channel/src/ask/ask.md | 130 +++ .../broadcast-channel/src/ask/responder.md | 102 ++ .../broadcast-channel/src/channel/channel.md | 122 +++ .../src/channel/heartbeat.md | 92 ++ .../broadcast-channel/src/errors/codes.md | 99 ++ .../events/broadcast-channel/src/id/id.md | 79 ++ .../broadcast-channel/src/logger/noop.md | 66 ++ .../broadcast-channel/src/otel/metrics.md | 104 +++ .../broadcast-channel/src/schemas/messages.md | 80 ++ .../src/transport/local-storage.md | 101 ++ .../broadcast-channel/src/transport/native.md | 78 ++ .../events/event-sourcing/README.md | 67 ++ .../aggregate-repository.md | 69 ++ .../src/core/aggregate/aggregate.md | 103 ++ .../core/event-store/memory-event-store.md | 82 ++ .../src/errors/event-sourcing-error.md | 79 ++ .../src/projection/builder/builder.md | 72 ++ .../src/schemas/event-sourcing.schemas.md | 66 ++ .../src/types/event-sourcing.types.md | 79 ++ .../src/upcasting/upcaster/upcaster.md | 69 ++ .../events/events-metrics/README.md | 32 + .../attach-event-metrics.md | 98 ++ .../src/metrics/metric-names/metric-names.md | 61 ++ docs/networking/events/events-otel/README.md | 33 + .../attach-event-tracing.md | 87 ++ .../trace-context/trace-context.md | 70 ++ .../sampling/sampling-rule/sampling-rule.md | 75 ++ .../networking/events/events-schema/README.md | 31 + .../attach-event-schemas.md | 97 ++ .../events/events-transport/README.md | 53 ++ .../src/core/envelope/envelope.md | 77 ++ .../src/core/nonce-window/nonce-window.md | 66 ++ .../transport-interface.md | 79 ++ .../broadcast-channel-transport.md | 124 +++ .../message-channel-transport.md | 127 +++ .../src/utils/structured-clone-check.md | 64 ++ docs/networking/events/events/README.md | 121 +++ .../events/events/src/bus/event-bus.md | 100 ++ .../events/events/src/clock/default-clock.md | 51 + .../events/events/src/envelope/envelope.md | 80 ++ .../events/events/src/errors/codes.md | 56 ++ .../events/events/src/errors/events-error.md | 57 ++ .../events/events/src/id/id-generator.md | 56 ++ .../events/src/idempotent/idempotent.md | 76 ++ .../events/events/src/interceptor/compose.md | 89 ++ .../src/observability/with-observability.md | 76 ++ .../events/events/src/queue/bounded-queue.md | 87 ++ docs/networking/network/README.md | 56 ++ docs/networking/network/_intro.md | 1 + .../network/network-bootstrap/README.md | 123 +++ .../core/discovery-chain/discovery-chain.md | 103 ++ .../src/core/peer-cache/peer-cache.md | 97 ++ .../network-bootstrap/src/errors/errors.md | 79 ++ .../network-bootstrap/src/otel/otel.md | 82 ++ .../bootstrap-middleware.md | 81 ++ .../bootstrap-plugin/bootstrap-plugin.md | 109 +++ .../network-bootstrap/src/types/types.md | 119 +++ .../network/network-discovery-crdt/README.md | 149 +++ .../automerge-provider/automerge-provider.md | 81 ++ .../src/core/crdt-discovery/crdt-discovery.md | 81 ++ .../src/core/crdt-intervals/crdt-intervals.md | 73 ++ .../crdt-peer-manager/crdt-peer-manager.md | 80 ++ .../src/core/yjs-provider/yjs-provider.md | 79 ++ .../src/errors/errors.md | 62 ++ .../network-discovery-crdt/src/otel/otel.md | 56 ++ .../network-discovery-crdt/src/types/types.md | 70 ++ .../network/network-discovery-gundb/README.md | 153 +++ .../core/gundb-discovery/gundb-discovery.md | 198 ++++ .../src/errors/errors.md | 108 +++ .../network-discovery-gundb/src/otel/otel.md | 115 +++ .../src/plugin/plugin.md | 84 ++ .../src/signing/signing.md | 156 ++++ .../src/transport/envelope-signing.md | 61 ++ .../src/transport/transport.md | 120 +++ .../src/types/types.md | 132 +++ .../network-discovery-hybrid/README.md | 137 +++ .../hybrid-discovery-manager.md | 108 +++ .../src/core/lifecycle/lifecycle.md | 73 ++ .../src/core/peer-tracker/peer-tracker.md | 84 ++ .../core/strategy-loader/strategy-loader.md | 55 ++ .../core/strategy-manager/strategy-manager.md | 81 ++ .../src/errors/errors.md | 74 ++ .../network-discovery-hybrid/src/otel/otel.md | 72 ++ .../src/types/types.md | 78 ++ .../network-discovery-peerjs/README.md | 114 +++ .../peer-connection-manager.md | 86 ++ .../peerjs-connection/peerjs-connection.md | 88 ++ .../core/peerjs-discovery/peerjs-discovery.md | 101 ++ .../core/peerjs-intervals/peerjs-intervals.md | 87 ++ .../peerjs-message-handlers.md | 90 ++ .../src/core/room-manager/room-manager.md | 80 ++ .../src/errors/errors.md | 78 ++ .../network-discovery-peerjs/src/otel/otel.md | 101 ++ .../src/plugin/plugin.md | 107 +++ .../src/transport/transport.md | 147 +++ .../src/types/types.md | 87 ++ .../network-discovery-trystero/README.md | 136 +++ .../src/core/ipfs-transport/ipfs-transport.md | 109 +++ .../src/core/mqtt-transport/mqtt-transport.md | 107 +++ .../core/nostr-transport/nostr-transport.md | 105 +++ .../torrent-transport/torrent-transport.md | 105 +++ .../trystero-discovery/trystero-discovery.md | 129 +++ .../trystero-fallback/trystero-fallback.md | 105 +++ .../trystero-intervals/trystero-intervals.md | 110 +++ .../trystero-message-handlers.md | 121 +++ .../trystero-peer-manager.md | 110 +++ .../src/errors/errors.md | 95 ++ .../src/otel/otel.md | 107 +++ .../src/plugin/plugin.md | 129 +++ .../src/transport/transport.md | 148 +++ .../src/types/types.md | 106 +++ .../network-discovery-webtorrent/README.md | 114 +++ .../webtorrent-discovery.md | 170 ++++ .../src/errors/errors.md | 107 +++ .../src/otel/otel.md | 105 +++ .../src/plugin/plugin.md | 105 +++ .../src/transport/transport.md | 147 +++ .../src/types/types.md | 122 +++ .../network/network-gundb-server/README.md | 108 +++ .../network-gundb-server/src/errors/errors.md | 84 ++ .../network-gundb-server/src/health/health.md | 89 ++ .../network-gundb-server/src/otel/otel.md | 95 ++ .../src/server/listen-http.md | 54 ++ .../network-gundb-server/src/server/server.md | 114 +++ .../network-gundb-server/src/types/types.md | 100 ++ .../src/validation/validation.md | 85 ++ .../network/network-libp2p-server/README.md | 129 +++ .../src/errors/errors.md | 89 ++ .../src/health/health.md | 72 ++ .../network-libp2p-server/src/otel/otel.md | 75 ++ .../src/server/health-listener.md | 62 ++ .../src/server/peer-events.md | 70 ++ .../src/server/server.md | 105 +++ .../network-libp2p-server/src/types/types.md | 75 ++ .../network-plugin-assignment/README.md | 22 + .../src/balancer/mesh-balancer.md | 78 ++ .../src/controller/admission-controller.md | 89 ++ .../src/engine/assignment-engine.md | 93 ++ .../src/error-codes.md | 62 ++ .../src/tracker/mesh-capacity-tracker.md | 59 ++ .../network-plugin-audit-mesh/README.md | 28 + .../src/compaction/log-compaction.md | 75 ++ .../src/conflict/conflict-resolver.md | 63 ++ .../src/error-codes.md | 53 ++ .../src/integrity/integrity-checker.md | 74 ++ .../src/log/signed-log.md | 86 ++ .../src/plugin/audit-mesh-plugin.md | 88 ++ .../src/replicator/log-replicator.md | 80 ++ .../src/retriever/log-retriever.md | 75 ++ .../src/types/conflict.types.md | 48 + .../src/types/log.types.md | 66 ++ .../src/types/replication.types.md | 65 ++ .../network/network-plugin-auth/README.md | 20 + .../network-plugin-auth/src/error-codes.md | 61 ++ .../src/issuer/capability-token-issuer.md | 79 ++ .../src/trust/cross-mesh-trust-validator.md | 83 ++ .../src/verifier/mesh-membership-verifier.md | 86 ++ .../network-plugin-circuit-breaker/README.md | 22 + .../src/breaker/mesh-circuit-breaker.md | 77 ++ .../src/error-codes.md | 57 ++ .../middleware/circuit-breaker-middleware.md | 75 ++ .../src/probe/half-open-probe.md | 80 ++ .../src/registry/circuit-breaker-registry.md | 68 ++ .../network-plugin-content-delivery/README.md | 44 + .../src/error-codes.md | 53 ++ .../src/index/chunk-index.md | 72 ++ .../src/integrity/integrity-verifier.md | 79 ++ .../src/packer/packer-integration.md | 98 ++ .../src/plugin/content-delivery-plugin.md | 80 ++ .../src/prefetch/prefetch-engine.md | 125 +++ .../src/redundancy/redundancy-manager.md | 81 ++ .../src/router/chunk-request-router.md | 74 ++ .../src/store/chunk-store.md | 108 +++ .../src/throttle/bandwidth-throttler.md | 113 +++ .../src/types/chunk.types.md | 75 ++ .../src/types/redundancy.types.md | 58 ++ .../network-plugin-crypto-messages/README.md | 34 + .../src/error-codes.md | 55 ++ .../src/identity/peer-identity-verifier.md | 72 ++ .../src/key-rotation/key-rotation-manager.md | 70 ++ .../src/log-chain/log-chain-signer.md | 61 ++ .../src/plugin/crypto-messages-plugin.md | 68 ++ .../src/signer/message-signer.md | 66 ++ .../src/token/mesh-token-authority.md | 72 ++ .../src/token/session-token-authority.md | 71 ++ .../src/types/identity.types.md | 59 ++ .../src/types/signature.types.md | 61 ++ .../src/types/token.types.md | 58 ++ .../network/network-plugin-devtools/README.md | 106 +++ .../src/error-codes.md | 68 ++ .../src/inspector/state-inspector.md | 97 ++ .../src/plugin/devtools-plugin.md | 96 ++ .../src/profiler/performance-profiler.md | 92 ++ .../performance-profiler.suggestions.md | 74 ++ .../src/simulator/simulation-config-tool.md | 117 +++ .../src/types/inspector.types.md | 73 ++ .../src/types/profiler.types.md | 80 ++ .../src/types/simulator.types.md | 98 ++ .../src/types/visualizer.types.md | 100 ++ .../src/visualizer/network-visualizer.md | 82 ++ .../src/visualizer/svg-renderer.md | 82 ++ .../network/network-plugin-failover/README.md | 24 + .../src/error-codes.md | 60 ++ .../src/failover/failover-coordinator.md | 78 ++ .../src/health/health-monitor.md | 66 ++ .../src/heartbeat/heartbeat-manager.md | 70 ++ .../src/plugin/failover-plugin.md | 70 ++ .../src/promoter/promoter-manager.md | 62 ++ .../network-plugin-governance/README.md | 28 + .../src/election/election-engine.md | 70 ++ .../src/error-codes.md | 59 ++ .../src/plugin/governance-plugin.md | 71 ++ .../src/reputation/reputation-tracker.md | 58 ++ .../src/scoring/candidate-scorer.md | 65 ++ .../src/transition/transition-manager.md | 73 ++ .../src/voting/voting-manager.md | 74 ++ .../network-plugin-intra-relay/README.md | 44 + .../connection/relay-connection-manager.md | 71 ++ .../src/discovery/relay-discovery.md | 73 ++ .../src/envelope/relay-envelope.md | 72 ++ .../src/error-codes.md | 53 ++ .../src/loop/loop-prevention.md | 60 ++ .../src/monitor/relay-performance-monitor.md | 73 ++ .../src/plugin/intra-relay-plugin.md | 85 ++ .../src/security/relay-security-manager.md | 94 ++ .../src/selector/relay-selector.md | 58 ++ .../src/types/relay.types.md | 74 ++ .../src/types/security.types.md | 73 ++ .../network-plugin-middleware/README.md | 32 + .../src/error-codes.md | 56 ++ .../src/i18n/i18n-middleware.md | 59 ++ .../src/logging/logging-middleware.md | 77 ++ .../src/manager/middleware-manager.md | 94 ++ .../src/metrics/metrics-middleware.md | 78 ++ .../src/plugin/middleware-plugin.md | 85 ++ .../src/security/security-middleware.md | 86 ++ .../src/throttling/throttling-middleware.md | 68 ++ .../transformation-middleware.md | 83 ++ .../src/types/chain.types.md | 56 ++ .../src/types/middleware.types.md | 69 ++ .../src/validation/validation-middleware.md | 81 ++ .../network-plugin-migration/README.md | 20 + .../src/coordinator/migration-coordinator.md | 97 ++ .../src/error-codes.md | 63 ++ .../state-transfer/state-transfer-protocol.md | 79 ++ .../src/tunnel/forwarding-tunnel.md | 73 ++ .../network/network-plugin-monitor/README.md | 52 ++ .../src/alert/alert-engine.md | 86 ++ .../src/collector/metric-collector.md | 73 ++ .../network-plugin-monitor/src/error-codes.md | 55 ++ .../src/grafana/dashboard-generator.md | 145 +++ .../src/history/historical-data-store.md | 78 ++ .../src/monitor/network-monitor.md | 67 ++ .../src/plugin/monitor-plugin.md | 75 ++ .../src/prometheus/prometheus-exposition.md | 120 +++ .../src/quality/bandwidth-monitor.md | 79 ++ .../src/quality/degradation-manager.md | 86 ++ .../src/quality/quality-middleware.md | 80 ++ .../src/quality/quality-types.md | 65 ++ .../src/sampler/adaptive-sampler.md | 65 ++ .../src/tracer/network-tracer.md | 77 ++ .../src/types/alert.types.md | 66 ++ .../src/types/metric.types.md | 68 ++ .../src/types/trace.types.md | 70 ++ .../network-plugin-partition/README.md | 20 + .../src/detector/partition-detector.md | 73 ++ .../src/error-codes.md | 60 ++ .../src/merge/merge-protocol.md | 78 ++ .../src/quorum/quorum-resolver.md | 54 ++ .../network/network-plugin-protocol/README.md | 89 ++ .../src/batcher/batcher.md | 55 ++ .../src/decoder/decoder.md | 45 + .../src/encoder/encoder.md | 46 + .../src/error-codes.md | 51 + .../src/pipeline/pipeline.md | 52 ++ .../src/protocol/protocol-plugin.md | 58 ++ .../src/protocol/protocol.md | 55 ++ .../src/queue/queue.md | 55 ++ .../src/serializer/serializer.md | 52 ++ .../network-plugin-protocol/src/ttl/ttl.md | 52 ++ .../src/types/protocol.types.md | 55 ++ .../network/network-plugin-qos/README.md | 22 + .../classifier/message-priority-classifier.md | 60 ++ .../src/enforcer/bandwidth-quota-enforcer.md | 78 ++ .../network-plugin-qos/src/error-codes.md | 53 ++ .../src/monitor/congestion-monitor.md | 65 ++ .../src/router/qos-router.md | 82 ++ .../network/network-plugin-registry/README.md | 72 ++ .../src/encoder/encoder.md | 46 + .../src/error-codes.md | 51 + .../src/registry-plugin.md | 50 + .../src/registry/registry.md | 54 ++ .../network-plugin-registry/src/sync/sync.md | 48 + .../network/network-plugin-relay/README.md | 26 + .../src/backbone/host-backbone-transport.md | 85 ++ .../src/directory/mesh-directory.md | 73 ++ .../src/envelope/cross-mesh-envelope.md | 68 ++ .../network-plugin-relay/src/error-codes.md | 61 ++ .../src/loop-prevention/loop-guard.md | 67 ++ .../src/manager/relay-manager.md | 84 ++ .../src/router/relay-router.md | 58 ++ .../network-plugin-server-bridge/README.md | 125 +++ .../src/buffer/log-buffer.md | 80 ++ .../src/command/command-dispatcher.md | 79 ++ .../src/command/command-dispatcher.types.md | 68 ++ .../src/error-codes/error-codes.md | 56 ++ .../src/fsm/graceful-degradation-fsm.md | 70 ++ .../src/gateway/server-gateway.md | 83 ++ .../src/gateway/server-gateway.types.md | 81 ++ .../src/hosting/backup-coordinator.md | 61 ++ .../src/hosting/failover-coordinator.md | 67 ++ .../src/hosting/hosting-model-config.md | 61 ++ .../src/hosting/pure-client-coordinator.md | 78 ++ .../src/hosting/server-based-coordinator.md | 67 ++ .../src/multiplexer/heartbeat-multiplexer.md | 80 ++ .../src/offline/offline-mode-coordinator.md | 78 ++ .../src/plugin/server-bridge-plugin.md | 95 ++ .../reconciliation/reconciliation-protocol.md | 77 ++ .../reconciliation-protocol.types.md | 72 ++ .../src/types/buffer.types.md | 56 ++ .../src/types/command.types.md | 60 ++ .../src/types/state.types.md | 52 ++ .../network/network-plugin-session/README.md | 32 + .../src/bridge/parent-state-bridge.md | 99 ++ .../src/capacity/session-capacity-enforcer.md | 81 ++ .../src/election/session-host-election.md | 96 ++ .../network-plugin-session/src/error-codes.md | 55 ++ .../src/plugin/session-plugin.md | 76 ++ .../src/registry/session-registry.md | 84 ++ .../src/router/session-router.md | 97 ++ .../src/session/session-manager.md | 84 ++ .../transition/session-transition-manager.md | 88 ++ .../src/tree/session-tree.md | 72 ++ .../src/types/message.types.md | 61 ++ .../src/types/session.types.md | 66 ++ .../src/types/transition.types.md | 65 ++ .../src/types/tree.types.md | 59 ++ .../network-plugin-simulation/README.md | 26 + .../src/chaos/chaos-engine.md | 81 ++ .../conditions/network-condition-injector.md | 83 ++ .../src/error-codes.md | 55 ++ .../src/plugin/simulation-plugin.md | 62 ++ .../src/scenario/scenario-runner.md | 102 ++ .../src/simulator/network-simulator.md | 73 ++ .../src/types/condition.types.md | 67 ++ .../src/types/scenario.types.md | 68 ++ .../src/types/simulation.types.md | 68 ++ .../src/virtual-node/virtual-node.md | 75 ++ .../network/network-plugin-state/README.md | 32 + .../src/bloom/bloom-filter-comparator.md | 65 ++ .../src/delta/delta-compressor.md | 59 ++ .../network-plugin-state/src/error-codes.md | 56 ++ .../src/plugin/state-plugin.md | 67 ++ .../src/pruner/state-history-pruner.md | 67 ++ .../src/reconciler/state-reconciler.md | 71 ++ .../src/resource/resource-adapter.md | 62 ++ .../src/state/state-manager.md | 66 ++ .../src/strategy/path-strategy-registry.md | 71 ++ .../src/sync/state-sync-engine.md | 82 ++ .../src/types/reconciliation.types.md | 63 ++ .../src/types/state.types.md | 61 ++ .../src/types/sync.types.md | 60 ++ .../network/network-plugin-topology/README.md | 22 + .../src/error-codes.md | 62 ++ .../src/group/group-manager.md | 78 ++ .../src/latency/latency-assigner.md | 75 ++ .../src/plugin/topology-plugin.md | 75 ++ .../src/topology/hierarchical-topology.md | 71 ++ .../README.md | 60 ++ .../src/analyzer/quality-trend-analyzer.md | 73 ++ .../src/balancer/round-robin-balancer.md | 70 ++ .../src/error-codes.md | 56 ++ .../src/health/transport-health-monitor.md | 81 ++ .../src/negotiator/capability-negotiator.md | 74 ++ .../persistence/session-persistence-buffer.md | 70 ++ .../src/plugin/transport-manager-plugin.md | 81 ++ .../src/pool/transport-pool.md | 73 ++ .../src/priority/priority-router.md | 63 ++ .../recovery/connection-recovery-manager.md | 60 ++ .../src/recovery/session-continuity-guard.md | 80 ++ .../src/scheduler/bandwidth-conservator.md | 63 ++ .../src/scheduler/battery-aware-scheduler.md | 68 ++ .../src/selector/preemptive-selector.md | 70 ++ .../src/selector/transport-selector.md | 87 ++ .../src/types/priority.types.md | 44 + .../src/types/selector.types.md | 55 ++ .../src/types/transport.types.md | 71 ++ .../network/network-testing/README.md | 20 + .../assertions/event-capture/event-capture.md | 58 ++ .../network-testing/src/error-codes.md | 56 ++ .../src/factories/test-peer/test-peer.md | 60 ++ .../condition-simulator.md | 64 ++ .../fake-websocket/fake-websocket.md | 63 ++ .../memory-transport/memory-transport.md | 64 ++ .../network-testing/src/types/common.md | 71 ++ .../network-transport-hyperswarm/README.md | 79 ++ .../src/connections/connections.md | 86 ++ .../src/discovery/discovery.md | 70 ++ .../src/errors/errors.md | 62 ++ .../src/messaging/messaging.md | 93 ++ .../src/otel/otel.md | 67 ++ .../src/plugin/plugin.md | 91 ++ .../src/reputation/reputation.md | 75 ++ .../src/security/security.md | 77 ++ .../src/transport/transport.md | 119 +++ .../src/types/types.md | 83 ++ .../network-transport-libp2p/README.md | 138 +++ .../src/connection/connection.md | 78 ++ .../src/errors/errors.md | 63 ++ .../src/messaging/frame.md | 60 ++ .../src/messaging/peer-message.md | 66 ++ .../src/messaging/send.md | 66 ++ .../network-transport-libp2p/src/otel/otel.md | 74 ++ .../src/plugin/plugin.md | 77 ++ .../src/streams/streams.md | 66 ++ .../src/transport/transport.md | 95 ++ .../src/types/types.md | 91 ++ .../network-transport-standby/README.md | 71 ++ .../src/errors/errors.md | 79 ++ .../src/health/monitor.md | 72 ++ .../src/otel/otel.md | 79 ++ .../src/plugin/plugin.md | 85 ++ .../src/pool/pool.md | 103 ++ .../src/reconnect/reconnect.md | 86 ++ .../src/transport/transport.md | 96 ++ .../src/types/types.md | 99 ++ .../network-transport-webrtc/README.md | 91 ++ .../src/data-channel/data-channel-manager.md | 67 ++ .../src/error-codes.md | 51 + .../src/ice/ice-manager.md | 66 ++ .../src/mesh/webrtc-mesh.md | 68 ++ .../src/ping/ping-manager.md | 67 ++ .../src/plugin/plugin.md | 52 ++ .../src/signaling/signaling-client.md | 82 ++ .../signaling/websocket-signaling-client.md | 92 ++ .../src/transport/transport.md | 63 ++ .../src/types/types.md | 55 ++ .../network-transport-websockets/README.md | 111 +++ .../src/adapters/native-adapter.md | 94 ++ .../src/core/client/client.md | 160 ++++ .../src/core/heartbeat/heartbeat.md | 98 ++ .../src/core/queue/queue.md | 100 ++ .../src/error-codes.md | 85 ++ .../src/otel/otel.md | 93 ++ .../src/plugin/plugin.md | 94 ++ .../src/transport/transport.md | 126 +++ .../src/types/common.md | 132 +++ .../network/network-trystero-server/README.md | 140 +++ .../src/errors/errors.md | 90 ++ .../src/health/health.md | 91 ++ .../network-trystero-server/src/otel/otel.md | 85 ++ .../src/server/broker-select.md | 74 ++ .../src/server/health-listener.md | 71 ++ .../src/server/peer-events.md | 86 ++ .../src/server/server.md | 119 +++ .../src/types/types.md | 103 ++ docs/networking/network/network/README.md | 124 +++ .../networking/network/network/src/bus/bus.md | 64 ++ .../network/network/src/envelope/envelope.md | 56 ++ .../network/network/src/error-codes.md | 53 ++ .../network/network/src/events/events.md | 52 ++ .../network/network/src/manager/manager.md | 64 ++ .../network/network/src/node/node.md | 70 ++ .../network/network/src/plugin/plugin.md | 79 ++ .../network/network/src/router/router.md | 62 ++ .../network/src/timestamp/timestamp.md | 63 ++ .../network/src/transport/transport.md | 63 ++ .../network/src/types/network.types.md | 51 + .../network/network/src/version/version.md | 53 ++ .../react-network-libp2p-demo/README.md | 99 ++ .../src/components/libp2p-demo/libp2p-demo.md | 84 ++ .../src/components/log-panel/log-panel.md | 77 ++ .../components/node-controls/node-controls.md | 83 ++ .../node-status-panel/node-status-panel.md | 77 ++ .../peer-interaction-panel.md | 85 ++ .../src/components/peer-list/peer-list.md | 80 ++ .../src/errors/errors.md | 88 ++ .../hooks/use-libp2p-demo/use-libp2p-demo.md | 116 +++ .../hooks/use-libp2p-demo/wire-peer-events.md | 74 ++ .../src/types/log-entry.types.md | 67 ++ .../src/types/peer-info.types.md | 65 ++ .../network/service-discovery/README.md | 95 ++ .../core/service-registry/service-registry.md | 118 +++ .../service-discovery/src/errors/errors.md | 70 ++ .../service-discovery/src/otel/otel.md | 68 ++ .../service-discovery/src/types/types.md | 92 ++ .../network/websocket-gateway/README.md | 192 ++++ .../websocket-gateway/src/channel/channel.md | 60 ++ .../websocket-gateway/src/errors/errors.md | 56 ++ .../src/gateway/access-gate.md | 51 + .../src/gateway/channel-manager.md | 52 ++ .../src/gateway/channel-ops.md | 49 + .../src/gateway/client-lifecycle.md | 42 + .../websocket-gateway/src/gateway/defaults.md | 62 ++ .../src/gateway/gateway-deps.md | 57 ++ .../websocket-gateway/src/gateway/gateway.md | 124 +++ .../src/gateway/heartbeat.md | 55 ++ .../src/gateway/lifecycle.md | 43 + .../src/gateway/message-factory.md | 44 + .../src/gateway/presence-fire.md | 55 ++ .../src/gateway/presence-webhook.md | 55 ++ .../websocket-gateway/src/gateway/room-ops.md | 52 ++ .../websocket-gateway/src/health/health.md | 59 ++ .../websocket-gateway/src/otel/otel.md | 63 ++ .../src/presence/presence.md | 59 ++ .../websocket-gateway/src/room/room.md | 65 ++ .../websocket-gateway/src/types/types.md | 69 ++ docs/observability/README.md | 21 + docs/observability/_intro.md | 3 + docs/observability/monitor/README.md | 17 + docs/observability/monitor/_intro.md | 1 + .../monitor/analytics-browser/README.md | 204 ++++ .../analytics-browser/src/consent/consent.md | 53 ++ .../src/error-codes/error-codes.md | 82 ++ .../analytics-browser/src/internal/id/id.md | 51 + .../monitor/analytics-browser/src/pii/pii.md | 62 ++ .../src/sampling/sampling.md | 56 ++ .../src/schema/analytics-event-schema.md | 52 ++ .../analytics-browser/src/session/session.md | 65 ++ .../analytics-browser/src/storage/storage.md | 54 ++ .../src/telemetry/telemetry.md | 58 ++ .../analytics-browser/src/tracker/tracker.md | 95 ++ .../analytics-browser/src/transport/batch.md | 51 + .../analytics-browser/src/transport/beacon.md | 50 + .../src/types/analytics.types.md | 64 ++ .../monitor/audit-logging/README.md | 94 ++ .../src/adapters/memory/memory.md | 116 +++ .../src/adapters/storage/storage.md | 101 ++ .../src/core/audit-logger/audit-logger.md | 127 +++ .../core/chain-integrity/chain-integrity.md | 97 ++ .../audit-logging/src/errors/audit-error.md | 91 ++ .../src/schemas/audit-logging.schemas.md | 110 +++ .../src/types/audit-logging.types.md | 148 +++ .../monitor/health-check/README.md | 67 ++ .../src/error-codes/error-codes.md | 57 ++ .../health-checker/health-checker.helpers.md | 49 + .../src/health-checker/health-checker.md | 65 ++ .../health-check/src/http-check/http-check.md | 54 ++ .../src/response-builder/response-builder.md | 64 ++ .../health-check/src/tcp-check/tcp-check.md | 53 ++ .../health-check/src/telemetry/telemetry.md | 47 + docs/observability/monitor/logger/README.md | 186 ++++ .../logger/src/abstract/abstract-logger.md | 109 +++ .../logger/src/console/console-logger.md | 70 ++ .../logger/src/error-bridge/error-bridge.md | 72 ++ .../monitor/logger/src/errors/logger-error.md | 81 ++ .../monitor/logger/src/event/event-logger.md | 89 ++ .../monitor/logger/src/factory/factory.md | 56 ++ .../monitor/logger/src/init/init.md | 65 ++ .../monitor/logger/src/otel/otel-context.md | 62 ++ .../monitor/logger/src/record/log-record.md | 88 ++ .../monitor/logger/src/redaction/redaction.md | 91 ++ .../monitor/logger/src/sampling/sampling.md | 89 ++ .../monitor/logger/src/sink/buffered-sink.md | 97 ++ .../monitor/logger/src/sink/console-sink.md | 89 ++ .../monitor/logger/src/sink/json-sink.md | 80 ++ .../monitor/logger/src/sink/sink.md | 90 ++ .../logger/src/storage/storage-logger.md | 100 ++ .../monitor/opentelemetry/README.md | 99 ++ .../src/core/propagation/propagation.md | 108 +++ .../opentelemetry/src/core/sdk/noop-sdk.md | 96 ++ .../opentelemetry/src/core/sdk/sdk-factory.md | 87 ++ .../src/errors/opentelemetry-error.md | 101 ++ .../src/schemas/otel-config.schema.md | 159 ++++ .../opentelemetry/src/utils/metrics-utils.md | 108 +++ .../opentelemetry/src/utils/resource.md | 66 ++ .../opentelemetry/src/utils/span-utils.md | 102 ++ docs/persistence/README.md | 60 ++ docs/persistence/_intro.md | 3 + docs/persistence/cache/README.md | 15 + docs/persistence/cache/_intro.md | 1 + docs/persistence/cache/cache-redis/README.md | 80 ++ .../cache/cache-redis/src/errors/errors.md | 76 ++ .../src/redis-cache/redis-cache.md | 105 +++ .../cache-redis/src/redis-like/redis-like.md | 98 ++ .../src/registry-augment/registry-augment.md | 64 ++ .../persistence/cache/cache-storage/README.md | 88 ++ .../cache/cache-storage/src/codec/identity.md | 66 ++ .../cache/cache-storage/src/codec/json.md | 79 ++ .../cache/cache-storage/src/errors/errors.md | 76 ++ .../cache/cache-storage/src/header/header.md | 81 ++ .../src/registry-augment/registry-augment.md | 63 ++ .../src/storage-cache/storage-cache.md | 108 +++ docs/persistence/cache/cache/README.md | 59 ++ .../abstract/abstract-cache/abstract-cache.md | 88 ++ .../namespaced-cache/namespaced-cache.md | 68 ++ .../cache/cache/src/errors/cache-error.md | 62 ++ .../cache/cache/src/factory/cache/cache.md | 81 ++ .../cache/src/factory/registry/registry.md | 42 + .../src/memory/memory-cache/memory-cache.md | 97 ++ .../cache/cache/src/types/common.md | 76 ++ .../cache/cache/src/types/schemas.md | 63 ++ docs/persistence/database/README.md | 17 + docs/persistence/database/_intro.md | 1 + docs/persistence/database/db-sqlite/README.md | 110 +++ .../db-sqlite/src/adapter/adapter.bun.md | 61 ++ .../database/db-sqlite/src/adapter/adapter.md | 113 +++ .../db-sqlite/src/adapter/adapter.wasm.md | 64 ++ .../database/db-sqlite/src/cache/cache.md | 88 ++ .../src/conformance/conformance-suite.md | 64 ++ .../db-sqlite/src/connection/connection.md | 83 ++ .../db-sqlite/src/drivers/bun-driver.md | 81 ++ .../db-sqlite/src/drivers/wasm-driver.md | 89 ++ .../db-sqlite/src/drivers/wasm-worker.md | 81 ++ .../database/db-sqlite/src/errors/errors.md | 93 ++ .../db-sqlite/src/migration/migration.md | 84 ++ .../database/db-sqlite/src/otel/otel.md | 65 ++ .../database/db-sqlite/src/schemas/schemas.md | 71 ++ .../database/db-sqlite/src/unsafe/unsafe.md | 68 ++ docs/persistence/database/db/README.md | 93 ++ .../db/src/adapter/database-adapter.md | 106 +++ .../database/db/src/connection/singleton.md | 120 +++ .../database/db/src/errors/database-error.md | 107 +++ .../db/src/migration/migration-runner.md | 101 ++ .../database/db/src/telemetry/instruments.md | 97 ++ .../database/db/src/telemetry/trace.md | 76 ++ .../database/db/src/types/database-config.md | 117 +++ docs/persistence/database/migration/README.md | 58 ++ .../src/adapters/surrealdb/surrealdb.md | 60 ++ .../batch/batch-migrator/batch-migrator.md | 64 ++ .../migration/src/errors/migration-error.md | 64 ++ .../lock/distributed-lock/distributed-lock.md | 61 ++ .../src/lock/memory-lock/memory-lock.md | 57 ++ .../src/lock/redis-lock/redis-lock.md | 68 ++ .../migration-planner/migration-planner.md | 56 ++ .../dry-run-reporter/dry-run-reporter.md | 56 ++ .../migration-executor/migration-executor.md | 61 ++ .../migration-runner/migration-runner.md | 84 ++ .../src/schemas/migration.schemas.md | 46 + .../migration-status/migration-status.md | 56 ++ .../store/database-store/database-store.md | 76 ++ .../src/store/memory-store/memory-store.md | 54 ++ .../migration/src/types/migration.types.md | 64 ++ .../database/migration/src/utils/checksum.md | 53 ++ docs/persistence/database/seed/README.md | 189 ++++ .../database/seed/src/builder/builder.md | 92 ++ .../seed/src/error-codes/error-codes.md | 128 +++ .../database/seed/src/fixtures/fixtures.md | 142 +++ .../database/seed/src/registry/registry.md | 113 +++ .../database/seed/src/runner/execute.md | 123 +++ .../database/seed/src/runner/runner.md | 215 +++++ .../database/seed/src/types/common.md | 151 +++ .../seed/src/utils/topo-sort/topo-sort.md | 109 +++ docs/persistence/database/surrealdb/README.md | 105 +++ .../surrealdb/src/adapter/adapter/adapter.md | 108 +++ .../surrealdb/src/adapter/crud/crud.md | 76 ++ .../adapter/query-helpers/query-helpers.md | 79 ++ .../src/adapter/transaction/transaction.md | 76 ++ .../surrealdb/src/connection/connection.md | 84 ++ .../database/surrealdb/src/errors/error.md | 73 ++ .../database/surrealdb/src/init/init.md | 70 ++ .../surrealdb/src/schema/discovery.md | 75 ++ .../database/surrealdb/src/schemas/schemas.md | 78 ++ .../surrealdb/src/singleton/singleton.md | 68 ++ .../database/surrealdb/src/types/types.md | 80 ++ .../surrealdb/src/utils/version-detector.md | 65 ++ docs/persistence/search/README.md | 13 + docs/persistence/search/_intro.md | 1 + docs/persistence/search/search/README.md | 54 ++ .../src/engine/memory-engine/memory-engine.md | 85 ++ .../search/search/src/errors/search-error.md | 55 ++ .../search/src/schemas/search.schemas.md | 63 ++ .../search/search/src/text/scorer/scorer.md | 69 ++ .../search/src/text/tokenizer/tokenizer.md | 59 ++ .../search/search/src/text/trigram/trigram.md | 51 + .../search/search/src/types/search.types.md | 70 ++ docs/persistence/storage/README.md | 26 + docs/persistence/storage/_intro.md | 1 + .../storage-browser-indexeddb/README.md | 93 ++ .../src/error-codes/error-codes.md | 72 ++ .../src/idb-adapter/idb-adapter.md | 62 ++ .../indexeddb-storage.config.md | 58 ++ .../indexeddb-storage.crud.md | 74 ++ .../indexeddb-storage.errors.md | 69 ++ .../indexeddb-storage/indexeddb-storage.md | 83 ++ .../indexeddb-storage.ops.md | 77 ++ .../src/key-sanitizer/key-sanitizer.md | 63 ++ .../src/otel/otel.md | 63 ++ .../src/registry/registry.md | 56 ++ .../src/types/idb-like.types.md | 60 ++ .../src/types/indexeddb-storage.types.md | 48 + .../storage-browser-localstorage/README.md | 101 ++ .../src/envelope/envelope.md | 84 ++ .../src/error-codes.md | 68 ++ .../in-memory-storage/in-memory-storage.md | 64 ++ .../src/key-sanitizer/key-sanitizer.md | 64 ++ .../local-storage-adapter.md | 66 ++ .../src/local-storage/local-storage.errors.md | 66 ++ .../src/local-storage/local-storage.md | 88 ++ .../src/local-storage/local-storage.ops.md | 60 ++ .../local-storage/local-storage.partial.md | 56 ++ .../src/local-storage/local-storage.slot.md | 59 ++ .../src/otel/otel.md | 72 ++ .../src/registry/registry.md | 62 ++ .../src/types/local-storage-storage.types.md | 48 + .../src/types/storage-like.types.md | 63 ++ .../storage/storage-browser-opfs/README.md | 95 ++ .../storage-browser-opfs/src/error-codes.md | 54 ++ .../src/filename-codec/filename-codec.md | 69 ++ .../src/in-memory-opfs/in-memory-opfs.md | 60 ++ .../src/key-sanitizer/key-sanitizer.md | 63 ++ .../src/opfs-adapter/opfs-adapter.md | 57 ++ .../src/opfs-storage/opfs-storage.errors.md | 58 ++ .../src/opfs-storage/opfs-storage.md | 83 ++ .../src/opfs-storage/opfs-storage.ops.md | 58 ++ .../src/opfs-storage/opfs-storage.streams.md | 49 + .../storage-browser-opfs/src/otel/otel.md | 56 ++ .../src/registry/registry.md | 50 + .../src/types/opfs-like.types.md | 48 + .../src/types/opfs-storage.types.md | 46 + .../storage/storage-cdn-bunnycdn/README.md | 112 +++ .../bunny-cdn-adapter.base.md | 61 ++ .../bunny-cdn-adapter.helpers.md | 91 ++ .../bunny-cdn-adapter/bunny-cdn-adapter.md | 79 ++ .../bunny-cdn-adapter.streams.md | 59 ++ .../src/error-codes/error-codes.md | 69 ++ .../src/key-sanitizer/key-sanitizer.md | 62 ++ .../storage-cdn-bunnycdn/src/otel/otel.md | 81 ++ .../src/pull-zone-client/pull-zone-client.md | 74 ++ .../src/registry/registry.md | 78 ++ .../src/retry-helper/retry-helper.md | 71 ++ .../src/storage-client/storage-client.md | 79 ++ .../src/token-auth/token-auth.md | 69 ++ .../src/types/adapter.types.md | 79 ++ .../storage/storage-cdn-rackspace/README.md | 114 +++ .../src/auth-client/auth-client.md | 74 ++ .../src/cdn-client/cdn-client.md | 66 ++ .../src/error-codes/error-codes.md | 69 ++ .../src/key-sanitizer/key-sanitizer.md | 62 ++ .../storage-cdn-rackspace/src/otel/otel.md | 81 ++ .../rackspace-cdn-adapter.base.md | 62 ++ .../rackspace-cdn-adapter.cdn-methods.md | 71 ++ .../rackspace-cdn-adapter.helpers.md | 84 ++ .../rackspace-cdn-adapter.md | 80 ++ .../rackspace-cdn-adapter.ops.md | 89 ++ .../rackspace-cdn-adapter.streams.md | 65 ++ .../src/registry/registry.md | 78 ++ .../src/retry-helper/retry-helper.md | 71 ++ .../src/temp-url/temp-url.md | 70 ++ .../src/types/adapter.types.md | 83 ++ .../src/types/auth.types.md | 78 ++ .../persistence/storage/storage-cdn/README.md | 93 ++ .../src/cdn-adapter/cdn-adapter.md | 99 ++ .../src/error-codes/error-codes.md | 75 ++ .../storage/storage-cdn/src/guards/guards.md | 89 ++ .../storage-cdn/src/sign-url/sign-url.md | 91 ++ .../storage-cdn/src/storage-augment.md | 88 ++ .../src/types/cdn-adapter.types.md | 83 ++ .../src/types/cdn-capabilities.types.md | 93 ++ .../storage-cdn/src/types/sign-url.types.md | 86 ++ .../storage/storage-file/README.md | 88 ++ .../storage/storage-file/src/bun-fs/bun-fs.md | 126 +++ .../storage/storage-file/src/error-codes.md | 65 ++ .../src/key-sanitizer/key-sanitizer.md | 59 ++ .../node-fs-storage.helpers.md | 52 ++ .../src/node-fs-storage/node-fs-storage.md | 77 ++ .../node-fs-storage/node-fs-storage.ops.md | 44 + .../storage-file/src/node-fs/node-fs.md | 60 ++ .../storage/storage-file/src/otel/otel.md | 64 ++ .../storage-file/src/registry/registry.md | 49 + .../src/retry-helper/retry-helper.md | 60 ++ .../storage-file/src/streams/streams.md | 63 ++ .../src/types/fs-adapter.types.md | 64 ++ .../src/types/node-fs-storage.types.md | 55 ++ .../storage/storage-http/README.md | 135 +++ .../storage-http/src/constants/constants.md | 60 ++ .../src/error-codes/error-codes.md | 71 ++ .../storage-http/src/etag-cache/etag-cache.md | 75 ++ .../src/fetch-adapter/fetch-adapter.md | 63 ++ .../src/http-storage/http-storage.helpers.md | 82 ++ .../src/http-storage/http-storage.md | 94 ++ .../src/http-storage/http-storage.ops.md | 92 ++ .../src/http-storage/http-storage.streams.md | 67 ++ .../src/key-sanitizer/key-sanitizer.md | 72 ++ .../storage/storage-http/src/otel/otel.md | 84 ++ .../storage/storage-http/src/range/range.md | 63 ++ .../storage-http/src/registry/registry.md | 77 ++ .../src/retry-helper/retry-helper.md | 79 ++ .../src/types/etag-cache.types.md | 74 ++ .../storage-http/src/types/fetch.types.md | 74 ++ .../src/types/http-storage.types.md | 91 ++ .../storage-http/src/types/retry.types.md | 72 ++ .../storage-http/src/types/uploader.types.md | 82 ++ .../storage-http/src/uploader/uploader.md | 71 ++ .../storage/storage-plugin-cache/README.md | 190 ++++ .../cached-storage/cached-storage.clear.md | 87 ++ .../cached-storage/cached-storage.context.md | 78 ++ .../cached-storage/cached-storage.delete.md | 69 ++ .../src/cached-storage/cached-storage.get.md | 76 ++ .../src/cached-storage/cached-storage.md | 108 +++ .../cached-storage.passthrough.md | 86 ++ .../cached-storage/cached-storage.signal.md | 67 ++ .../cached-storage/cached-storage.write.md | 77 ++ .../src/error-codes/error-codes.md | 91 ++ .../src/factory/factory.md | 85 ++ .../storage-plugin-cache/src/otel/otel.md | 89 ++ docs/persistence/storage/storage-s3/README.md | 44 + .../src/registry/registry/registry.md | 56 ++ .../storage/storage-s3/src/s3/s3.md | 140 +++ .../storage/storage-s3/src/types/s3.types.md | 92 ++ .../src/utils/credential-validator.md | 89 ++ .../storage-uri-plugin-bundle/README.md | 167 ++++ .../src/abort/abort.md | 77 ++ .../src/cache/cache.md | 78 ++ .../src/error-codes/error-codes.md | 91 ++ .../src/factory/factory.md | 71 ++ .../src/node-fetch/node-fetch.md | 109 +++ .../src/otel/otel.md | 91 ++ .../src/parse/parse.md | 80 ++ .../src/range/range.md | 92 ++ .../src/storage-shim/storage-shim.fetch.md | 62 ++ .../src/storage-shim/storage-shim.head.md | 64 ++ .../src/storage-shim/storage-shim.md | 88 ++ .../src/storage-shim/storage-shim.range.md | 75 ++ .../src/streaming/streaming.md | 67 ++ .../src/types/plugin-options.schemas.md | 69 ++ .../src/types/plugin-options.types.md | 73 ++ .../storage-uri-plugin-fallback/README.md | 187 ++++ .../src/classify/classify.md | 66 ++ .../src/conformance/fallback-conformance.md | 72 ++ .../src/error-codes/error-codes.md | 78 ++ .../src/observability/events.md | 73 ++ .../src/observability/otel.md | 79 ++ .../src/ops/delete.md | 68 ++ .../src/ops/list.md | 69 ++ .../src/ops/metadata.md | 60 ++ .../src/ops/read.md | 62 ++ .../src/ops/write.md | 69 ++ .../src/parse-uri/abort-any.md | 60 ++ .../src/parse-uri/parse-fallback-uri.md | 75 ++ .../src/plugin/plugin.md | 77 ++ .../src/recursion/depth-context.md | 84 ++ .../src/types/candidate.types.md | 67 ++ .../src/types/policy.types.md | 71 ++ .../src/walk/parallel.md | 68 ++ .../src/walk/sequential.md | 70 ++ .../persistence/storage/storage-uri/README.md | 146 +++ .../src/conformance/conformance.md | 72 ++ .../src/error-codes/error-codes.md | 82 ++ .../storage/storage-uri/src/otel/otel.md | 70 ++ .../storage-uri/src/parse-uri/parse-uri.md | 71 ++ .../storage-uri/src/resolver/resolver.list.md | 66 ++ .../storage-uri/src/resolver/resolver.md | 94 ++ .../src/resolver/resolver.streams.md | 61 ++ .../src/resolver/resolver.writes.md | 63 ++ .../storage-uri/src/types/plugin.types.md | 72 ++ .../storage-uri/src/types/resolver.types.md | 65 ++ docs/persistence/storage/storage/README.md | 173 ++++ .../storage/storage/src/abstract/abstract.md | 159 ++++ .../storage/storage/src/abstract/namespace.md | 93 ++ .../storage/storage/src/errors/errors.md | 119 +++ .../storage/storage/src/factory/factory.md | 93 ++ .../storage/storage/src/memory/memory.md | 107 +++ .../storage/storage/src/types/schemas.md | 109 +++ .../storage/storage/src/types/types.md | 121 +++ docs/security-stack/README.md | 51 + docs/security-stack/_intro.md | 3 + docs/security-stack/crypto/README.md | 25 + docs/security-stack/crypto/_intro.md | 1 + .../crypto/crypto-bin/README.md | 105 +++ .../crypto-bin/src/bin/hash-password.md | 107 +++ .../src/hash-password/hash-password.md | 63 ++ .../crypto/crypto-browser/CHANGELOG.md | 16 + .../crypto/crypto-browser/README.md | 89 ++ .../crypto-browser/src/aes-kw/aes-kw.md | 106 +++ .../src/availability/availability.md | 85 ++ .../crypto-browser/src/ecdh-p384/ecdh-p384.md | 105 +++ .../src/ecdsa-p384/ecdsa-p384.md | 117 +++ .../webcrypto-aead-engine.md | 108 +++ .../webcrypto-agree-engine.md | 118 +++ .../webcrypto-sign-engine.md | 119 +++ .../browser-crypto-error.md | 91 ++ .../crypto-browser/src/errors/codes/codes.md | 81 ++ .../non-extractable-key.md | 97 ++ .../crypto/crypto-browser/src/rsa/rsa.md | 138 +++ .../crypto/crypto-cipher/CHANGELOG.md | 8 + .../crypto/crypto-cipher/README.md | 71 ++ .../crypto-cipher/src/errors/codes/codes.md | 79 ++ .../crypto-cipher-error.md | 72 ++ .../src/primitives/aes-256-gcm/aes-256-gcm.md | 79 ++ .../aes-256-gcm.select/aes-256-gcm.select.md | 62 ++ .../aes-256-gcm.native/aes-256-gcm.native.md | 69 ++ .../aes-256-gcm.noble/aes-256-gcm.noble.md | 84 ++ .../chacha20-poly1305/chacha20-poly1305.md | 67 ++ .../chacha20-poly1305.select.md | 59 ++ .../chacha20-poly1305.native.md | 63 ++ .../chacha20-poly1305.noble.md | 79 ++ .../xchacha20-poly1305.native.md | 69 ++ .../xchacha20-poly1305.noble.md | 77 ++ .../xchacha20-poly1305/xchacha20-poly1305.md | 73 ++ .../xchacha20-poly1305.select.md | 56 ++ .../streaming-aead-aes-gcm.md | 75 ++ .../streaming-aead-xchacha20.md | 66 ++ .../streaming-aead/streaming-aead.md | 96 ++ .../crypto/crypto-cli/README.md | 1 + .../crypto/crypto-core/CHANGELOG.md | 41 + .../crypto/crypto-core/README.md | 199 ++++ .../crypto/crypto-core/src/aead/aead.md | 125 +++ .../noble-aead-engine/noble-aead-engine.md | 103 ++ .../noble-agree-engine/noble-agree-engine.md | 89 ++ .../crypto-core/src/agree/x25519/x25519.md | 83 ++ .../crypto-core/src/auth-box/auth-box.md | 103 ++ .../noble-auth-box-engine.md | 111 +++ .../crypto-core/src/errors/codes/codes.md | 89 ++ .../src/errors/crypto-error/crypto-error.md | 81 ++ .../constant-time-equal.md | 72 ++ .../primitives/random-bytes/random-bytes.md | 97 ++ .../src/primitives/zeroize/zeroize.md | 68 ++ .../noble-sealed-box-engine.md | 117 +++ .../crypto-core/src/sealed-box/sealed-box.md | 94 ++ .../src/sign/ecdsa-p256/ecdsa-p256.md | 89 ++ .../crypto-core/src/sign/ed25519/ed25519.md | 92 ++ .../noble-sign-engine/noble-sign-engine.md | 117 +++ .../crypto/crypto-curve/CHANGELOG.md | 7 + .../crypto/crypto-curve/README.md | 103 ++ .../crypto-curve/src/errors/codes/codes.md | 52 ++ .../crypto-curve-error/crypto-curve-error.md | 63 ++ .../src/primitives/ed25519/ed25519.md | 65 ++ .../ed25519/ed25519.select/ed25519.select.md | 57 ++ .../impl/ed25519.native/ed25519.native.md | 64 ++ .../impl/ed25519.noble/ed25519.noble.md | 83 ++ .../p256/impl/p256.native/p256.native.md | 73 ++ .../p256/impl/p256.noble/p256.noble.md | 83 ++ .../crypto-curve/src/primitives/p256/p256.md | 64 ++ .../p256/p256.select/p256.select.md | 59 ++ .../p384/impl/p384.native/p384.native.md | 88 ++ .../p384/impl/p384.noble/p384.noble.md | 92 ++ .../crypto-curve/src/primitives/p384/p384.md | 81 ++ .../p384/p384.select/p384.select.md | 70 ++ .../p521/impl/p521.native/p521.native.md | 89 ++ .../p521/impl/p521.noble/p521.noble.md | 92 ++ .../crypto-curve/src/primitives/p521/p521.md | 80 ++ .../p521/p521.select/p521.select.md | 70 ++ .../impl/secp256k1.native/secp256k1.native.md | 65 ++ .../impl/secp256k1.noble/secp256k1.noble.md | 91 ++ .../src/primitives/secp256k1/secp256k1.md | 88 ++ .../secp256k1.select/secp256k1.select.md | 55 ++ .../impl/x25519.native/x25519.native.md | 61 ++ .../x25519/impl/x25519.noble/x25519.noble.md | 71 ++ .../src/primitives/x25519/x25519.md | 74 ++ .../x25519/x25519.select/x25519.select.md | 54 ++ .../crypto/crypto-hash/CHANGELOG.md | 7 + .../crypto/crypto-hash/README.md | 128 +++ .../crypto-hash/src/encoding/base64/base64.md | 125 +++ .../crypto-hash/src/encoding/hex/hex.md | 107 +++ .../crypto-hash/src/errors/codes/codes.md | 75 ++ .../src/errors/hash-error/hash-error.md | 79 ++ .../crypto/crypto-hash/src/hash/sha2/sha2.md | 111 +++ .../crypto-hash/src/kdf/argon2id/argon2id.md | 151 +++ .../crypto/crypto-hash/src/kdf/hkdf/hkdf.md | 106 +++ .../crypto-hash/src/kdf/pbkdf2/pbkdf2.md | 128 +++ .../argon2id-password/argon2id-password.md | 69 ++ .../mac/blake2b-password/blake2b-password.md | 72 ++ .../crypto/crypto-hash/src/mac/hmac/hmac.md | 97 ++ .../argon2id.select/argon2id.select.md | 98 ++ .../impl/argon2id.native/argon2id.native.md | 83 ++ .../impl/argon2id.noble/argon2id.noble.md | 88 ++ .../src/primitives/blake2b/blake2b.md | 63 ++ .../impl/blake2b.noble/blake2b.noble.md | 50 + .../hkdf/hkdf.select/hkdf.select.md | 96 ++ .../hkdf/impl/hkdf.native/hkdf.native.md | 84 ++ .../hkdf/impl/hkdf.noble/hkdf.noble.md | 90 ++ .../hmac/hmac.select/hmac.select.md | 76 ++ .../hmac/impl/hmac.native/hmac.native.md | 73 ++ .../hmac/impl/hmac.noble/hmac.noble.md | 78 ++ .../impl/pbkdf2.native/pbkdf2.native.md | 80 ++ .../pbkdf2/impl/pbkdf2.noble/pbkdf2.noble.md | 89 ++ .../pbkdf2/pbkdf2.select/pbkdf2.select.md | 91 ++ .../scrypt/impl/scrypt.noble/scrypt.noble.md | 62 ++ .../src/primitives/scrypt/scrypt.md | 71 ++ .../impl/sha256.native/sha256.native.md | 65 ++ .../sha256/impl/sha256.noble/sha256.noble.md | 60 ++ .../sha256/sha256.select/sha256.select.md | 71 ++ .../impl/sha384.native/sha384.native.md | 64 ++ .../sha384/impl/sha384.noble/sha384.noble.md | 59 ++ .../sha384/sha384.select/sha384.select.md | 60 ++ .../impl/sha512.native/sha512.native.md | 68 ++ .../sha512/impl/sha512.noble/sha512.noble.md | 62 ++ .../sha512/sha512.select/sha512.select.md | 60 ++ .../crypto/crypto-keys/README.md | 192 ++++ .../crypto-keys/src/codecs/cbor/cbor.md | 94 ++ .../recursive-ed25519/recursive-ed25519.md | 83 ++ .../crypto/crypto-keys/src/codecs/tlv/tlv.md | 118 +++ .../src/error-codes/error-codes.md | 145 +++ .../crypto/crypto-keys/src/factory/factory.md | 147 +++ .../crypto-keys/src/hashers/domain/domain.md | 88 ++ .../crypto-keys/src/hashers/merkle/merkle.md | 89 ++ .../crypto/crypto-keys/src/hashers/raw/raw.md | 77 ++ .../crypto/crypto-keys/src/signer/signer.md | 188 ++++ .../crypto-keys/src/types/chain-level.md | 132 +++ .../crypto/crypto-keys/src/types/codec.md | 128 +++ .../crypto/crypto-keys/src/types/hasher.md | 96 ++ .../crypto/crypto-rsa/README.md | 464 ++++++++++ .../blinded_vs_unblinded_2048.md | 34 + .../src/__fixtures__/rsa-2048-key.md | 42 + .../crypto-rsa/src/__fixtures__/test-keys.md | 40 + .../crypto/crypto-rsa/src/asn1/reader.md | 88 ++ .../crypto/crypto-rsa/src/asn1/writer.md | 87 ++ .../crypto-rsa/src/blinding/blinding.md | 133 +++ .../crypto/crypto-rsa/src/decrypt/oaep.md | 86 ++ .../crypto/crypto-rsa/src/decrypt/pkcs1v15.md | 88 ++ .../src/encoding/emsa-pkcs1-v1_5.md | 84 ++ .../src/encoding/emsa-pss-encode.md | 78 ++ .../src/encoding/emsa-pss-verify.md | 89 ++ .../crypto/crypto-rsa/src/encoding/mgf1.md | 84 ++ .../crypto-rsa/src/encrypt/default-rng.md | 64 ++ .../crypto/crypto-rsa/src/encrypt/oaep.md | 91 ++ .../crypto/crypto-rsa/src/encrypt/pkcs1v15.md | 90 ++ .../crypto/crypto-rsa/src/engine/noble.md | 90 ++ .../crypto/crypto-rsa/src/engine/select.md | 76 ++ .../crypto/crypto-rsa/src/engine/subtle.md | 96 ++ .../crypto/crypto-rsa/src/errors/errors.md | 87 ++ .../crypto-rsa/src/fingerprint/format.md | 80 ++ .../crypto/crypto-rsa/src/fingerprint/spki.md | 73 ++ .../crypto/crypto-rsa/src/handle/registry.md | 93 ++ .../crypto/crypto-rsa/src/handle/software.md | 78 ++ .../crypto-rsa/src/jwk/thumbprint-uri.md | 59 ++ .../crypto/crypto-rsa/src/jwk/thumbprint.md | 84 ++ .../crypto/crypto-rsa/src/keygen/exponent.md | 68 ++ .../crypto/crypto-rsa/src/keygen/generate.md | 112 +++ .../crypto-rsa/src/keygen/miller-rabin.md | 75 ++ .../crypto-rsa/src/keygen/multi-prime.md | 95 ++ .../crypto/crypto-rsa/src/keys/jwk-policy.md | 93 ++ .../crypto/crypto-rsa/src/keys/oid.md | 53 ++ .../crypto/crypto-rsa/src/keys/parse-jwk.md | 80 ++ .../src/keys/parse-pkcs1-private.md | 66 ++ .../crypto-rsa/src/keys/parse-pkcs1-public.md | 60 ++ .../crypto/crypto-rsa/src/keys/parse-pkcs8.md | 55 ++ .../crypto/crypto-rsa/src/keys/parse-spki.md | 61 ++ .../crypto/crypto-rsa/src/keys/parse.md | 62 ++ .../crypto-rsa/src/keys/serialize-jwk.md | 54 ++ .../src/keys/serialize-pkcs1-private.md | 52 ++ .../src/keys/serialize-pkcs1-public.md | 53 ++ .../crypto-rsa/src/keys/serialize-pkcs8.md | 49 + .../crypto-rsa/src/keys/serialize-spki.md | 47 + .../crypto/crypto-rsa/src/keys/serialize.md | 52 ++ .../crypto/crypto-rsa/src/math/crt.md | 68 ++ .../crypto/crypto-rsa/src/math/i2osp.md | 60 ++ .../crypto/crypto-rsa/src/math/modpow.md | 60 ++ .../crypto/crypto-rsa/src/math/os2ip.md | 52 ++ .../crypto-rsa/src/observability/metrics.md | 85 ++ .../crypto-rsa/src/observability/timing.md | 67 ++ .../crypto/crypto-rsa/src/pem/labels.md | 49 + .../crypto-rsa/src/pem/parse-private.md | 50 + .../crypto/crypto-rsa/src/pem/parse-public.md | 52 ++ .../crypto/crypto-rsa/src/pem/pem-codec.md | 61 ++ .../crypto-rsa/src/pem/serialize-private.md | 43 + .../crypto-rsa/src/pem/serialize-public.md | 44 + .../crypto/crypto-rsa/src/policy/modulus.md | 73 ++ .../crypto/crypto-rsa/src/profile/profile.md | 108 +++ .../crypto/crypto-rsa/src/schemas/schemas.md | 90 ++ .../crypto/crypto-rsa/src/sign/pkcs1v15.md | 82 ++ .../crypto/crypto-rsa/src/sign/pss.md | 105 +++ .../crypto/crypto-rsa/src/verify/pkcs1v15.md | 81 ++ .../crypto/crypto-rsa/src/verify/pss.md | 87 ++ .../crypto/crypto-sodium/CHANGELOG.md | 21 + .../crypto/crypto-sodium/README.md | 89 ++ .../sodium-aead-engine/sodium-aead-engine.md | 96 ++ .../sodium-agree-engine.md | 81 ++ .../sodium-auth-box-engine.md | 110 +++ .../sodium-sealed-box-engine.md | 98 ++ .../sodium-sign-engine/sodium-sign-engine.md | 88 ++ .../crypto-sodium/src/errors/codes/codes.md | 80 ++ .../src/errors/sodium-error/sodium-error.md | 94 ++ .../crypto/crypto-sodium/src/init/init.md | 70 ++ .../src/primitives/crypto-auth/crypto-auth.md | 85 ++ .../src/primitives/crypto-kdf/crypto-kdf.md | 87 ++ .../primitives/crypto-pwhash/crypto-pwhash.md | 93 ++ .../primitives/ristretto255/ristretto255.md | 98 ++ .../crypto/crypto-utils/CHANGELOG.md | 14 + .../crypto/crypto-utils/README.md | 65 ++ .../src/bytes/concat-bytes/concat-bytes.md | 50 + .../crypto-utils/src/bytes/i2osp/i2osp.md | 52 ++ .../crypto-utils/src/bytes/os2ip/os2ip.md | 51 + .../crypto/crypto-utils/src/bytes/xor/xor.md | 48 + .../constant-time-equal.md | 52 ++ .../src/encoding/base58/base58.md | 60 ++ .../src/encoding/base64/base64.md | 56 ++ .../crypto-utils/src/encoding/hex/hex.md | 55 ++ .../crypto-utils/src/errors/codes/codes.md | 96 ++ .../crypto-utils-error/crypto-utils-error.md | 102 ++ .../primitive-not-implemented.md | 101 ++ .../src/merkle/merkle-proof/merkle-proof.md | 70 ++ .../src/merkle/merkle-root/merkle-root.md | 59 ++ .../src/primitive-id/primitive-id.md | 67 ++ .../src/random/random-bytes/random-bytes.md | 57 ++ .../src/testing/diff-fuzz/diff-fuzz.md | 68 ++ .../crypto-utils/src/testing/dudect/dudect.md | 118 +++ .../src/testing/run-vectors/run-vectors.md | 70 ++ .../crypto-utils/src/zeroize/zeroize.md | 61 ++ .../crypto/crypto-vault/README.md | 153 +++ .../crypto-vault/src/argon2id/argon2id.md | 116 +++ .../crypto/crypto-vault/src/bip39/bip39.md | 109 +++ .../crypto/crypto-vault/src/errors/codes.md | 78 ++ .../src/errors/crypto-vault-error.md | 93 ++ .../crypto-vault/src/handle/opaque-handle.md | 92 ++ .../crypto/crypto-vault/src/hd-key/hd-key.md | 102 ++ .../src/key-hierarchy/key-hierarchy.md | 114 +++ .../src/orchestration/internals.md | 88 ++ .../src/orchestration/orchestration.md | 146 +++ .../crypto-vault/src/otel/instruments.md | 98 ++ .../crypto-vault/src/schemas/schemas.md | 86 ++ .../crypto-vault/src/secure/secure-buffer.md | 128 +++ .../crypto/crypto-vault/src/srp/srp-client.md | 133 +++ .../crypto/crypto-vault/src/srp/srp-group.md | 71 ++ .../crypto/crypto-vault/src/twoskd/twoskd.md | 115 +++ .../crypto/crypto-vault/src/types/types.md | 101 ++ .../security-stack/crypto/crypto/CHANGELOG.md | 41 + docs/security-stack/crypto/crypto/README.md | 216 +++++ .../src/aead/streaming/streaming-aead.md | 83 ++ .../crypto/src/aead/streaming/web-streams.md | 78 ++ .../crypto/crypto/src/authority/authority.md | 133 +++ .../src/bundles/chain-bundle/chain-bundle.md | 112 +++ .../bundles/public-bundle/public-bundle.md | 135 +++ .../src/derivation/coordinate/coordinate.md | 143 +++ .../crypto/src/derivation/layouts/layouts.md | 125 +++ .../src/derivation/purposes/purposes.md | 121 +++ .../crypto/src/domain-tags/domain-tags.md | 115 +++ .../crypto/crypto/src/errors/codes/codes.md | 89 ++ .../src/errors/crypto-error/crypto-error.md | 81 ++ .../src/errors/keys-errors/codes/codes.md | 99 ++ .../crypto-keys-error/crypto-keys-error.md | 110 +++ .../src/errors/vault-errors/codes/codes.md | 96 ++ .../crypto-vault-error/crypto-vault-error.md | 112 +++ .../src/keychain/algorithms/algorithms.md | 108 +++ .../crypto/src/keychain/key-slot/key-slot.md | 118 +++ .../crypto/crypto/src/keychain/keychain.md | 153 +++ .../src/keychain/keypair/generate/generate.md | 74 ++ .../src/keychain/keypair/validate/validate.md | 82 ++ .../storage/adapters/memory/memory.md | 71 ++ .../storage/adapters/serialized/serialized.md | 91 ++ .../crypto/src/keychain/validity/validity.md | 86 ++ .../src/password/derive-key-from-password.md | 65 ++ .../src/password/encrypt-with-password.md | 64 ++ .../crypto/src/trust-anchors/trust-anchor.md | 82 ++ .../crypto/src/vault/mnemonic/mnemonic.md | 76 ++ docs/security-stack/security/README.md | 27 + docs/security-stack/security/_intro.md | 1 + docs/security-stack/security/hibp/README.md | 222 +++++ .../security/hibp/src/breach/breach-client.md | 78 ++ .../hibp/src/breach/rate-limit-gate.md | 68 ++ .../security/hibp/src/breach/retry-after.md | 56 ++ .../security/hibp/src/cache/cache.md | 94 ++ .../security/hibp/src/cache/lru.md | 65 ++ .../security/hibp/src/cache/null.md | 54 ++ .../security/hibp/src/client/client.md | 97 ++ .../hibp/src/client/options.schema.md | 60 ++ .../security/hibp/src/error-codes.md | 63 ++ .../security/hibp/src/errors/codes.md | 57 ++ .../security/hibp/src/errors/hibp-error.md | 69 ++ .../hibp/src/observability/metrics.md | 68 ++ .../hibp/src/privacy/assert-no-leak.md | 62 ++ .../hibp/src/range/constant-time-compare.md | 59 ++ .../hibp/src/range/differential-privacy.md | 62 ++ .../security/hibp/src/range/range-mode.md | 60 ++ .../hibp/src/range/range-stream-parse.md | 67 ++ .../hibp/src/range/range-strict-frame.md | 65 ++ .../security/hibp/src/range/range.md | 77 ++ .../hibp/src/schemas/breach.schema.md | 68 ++ .../security/hibp/src/schemas/paste.schema.md | 64 ++ .../hibp/src/schemas/pwned-result.schema.md | 57 ++ docs/security-stack/security/jws/README.md | 147 +++ .../security/jws/src/algorithms/builtin.md | 46 + .../security/jws/src/algorithms/ecdsa.md | 60 ++ .../security/jws/src/algorithms/eddsa.md | 52 ++ .../security/jws/src/algorithms/hmac.md | 54 ++ .../security/jws/src/algorithms/none.md | 59 ++ .../security/jws/src/algorithms/registry.md | 59 ++ .../security/jws/src/algorithms/rsa-pss.md | 57 ++ .../security/jws/src/algorithms/rsa.md | 53 ++ .../security/jws/src/base64url/base64url.md | 59 ++ .../security/jws/src/detached/detached.md | 65 ++ .../security/jws/src/errors/error-codes.md | 71 ++ .../security/jws/src/header/b64.md | 59 ++ .../security/jws/src/header/crit.md | 57 ++ .../security/jws/src/header/header.md | 57 ++ .../security/jws/src/keys/jwk.md | 66 ++ .../security/jws/src/keys/resolver.md | 59 ++ .../security/jws/src/keys/x5c.md | 61 ++ .../security/jws/src/observability/metrics.md | 57 ++ .../security/jws/src/schemas/schemas.md | 59 ++ .../jws/src/serialization/compact/compact.md | 65 ++ .../jws/src/serialization/flat/flat.md | 54 ++ .../jws/src/serialization/general/general.md | 69 ++ .../security/jws/src/sign/sign-pipeline.md | 49 + .../jws/src/verify/verify-pipeline.md | 65 ++ .../security-stack/security/license/README.md | 178 ++++ .../license/src/codec/base32/base32.md | 74 ++ .../license/src/codec/bitpack/bitpack.md | 90 ++ .../src/codec/obfuscation/obfuscation.md | 98 ++ .../license/src/codec/payload/payload.md | 89 ++ .../license/src/constants/constants.md | 81 ++ .../security/license/src/error-codes.md | 99 ++ .../security/license/src/flags/flags.md | 112 +++ .../security/license/src/generate/generate.md | 129 +++ .../security/license/src/manager/manager.md | 131 +++ .../security/license/src/otel/instruments.md | 89 ++ .../revocation-store/revocation-store.md | 102 ++ .../security/license/src/schemas/schemas.md | 91 ++ .../security/license/src/time/time.md | 85 ++ .../security/license/src/types/license.md | 121 +++ .../security/license/src/validate/validate.md | 110 +++ docs/security-stack/security/otp/README.md | 207 +++++ .../security/otp/openspec/specs/otp/spec.md | 0 .../security/otp/src/base32/base32.md | 58 ++ .../security/otp/src/drift/detect.md | 63 ++ .../security/otp/src/errors/codes.md | 61 ++ .../security/otp/src/errors/zod-map.md | 56 ++ .../security/otp/src/hotp/encode-counter.md | 58 ++ .../security/otp/src/hotp/hmac.md | 56 ++ .../security/otp/src/hotp/hotp.md | 79 ++ .../security/otp/src/hotp/hotp.schema.md | 61 ++ .../security/otp/src/observability/metrics.md | 70 ++ .../security/otp/src/ocra/encode-challenge.md | 56 ++ .../security/otp/src/ocra/mutual-auth.md | 71 ++ .../security/otp/src/ocra/ocra.md | 81 ++ .../security/otp/src/ocra/ocra.schema.md | 57 ++ .../security/otp/src/ocra/suite.md | 55 ++ .../security/otp/src/ocra/verify-ocra.md | 60 ++ .../security/otp/src/recovery/generate.md | 64 ++ .../security/otp/src/recovery/hash.md | 60 ++ .../security/otp/src/recovery/verify.md | 63 ++ .../security/otp/src/totp/totp.md | 93 ++ .../security/otp/src/totp/totp.schema.md | 60 ++ .../security/otp/src/totp/verify-many.md | 62 ++ .../security/otp/src/totp/verify.md | 61 ++ .../security/otp/src/uri/format-uri.md | 66 ++ .../security/otp/src/uri/parse-uri.md | 62 ++ .../security/otp/src/uri/uri.schema.md | 60 ++ .../security/password-formats/README.md | 137 +++ .../src/core/detector/format-detector.md | 72 ++ .../password-formats/src/core/parse/parse.md | 75 ++ .../src/core/validator/validate.md | 79 ++ .../src/errors/password-formats-error.md | 86 ++ .../password-formats/src/export/csv-export.md | 75 ++ .../apple-passwords/apple-passwords.md | 65 ++ .../src/parsers/bitwarden/bitwarden.md | 81 ++ .../src/parsers/chrome/chrome.md | 66 ++ .../src/parsers/keepass/keepass.md | 90 ++ .../src/types/password-formats.types.md | 83 ++ .../security/password-generator/README.md | 163 ++++ .../src/charsets/charsets.md | 72 ++ .../password-generator/src/entropy/entropy.md | 73 ++ .../password-generator/src/errors/codes.md | 81 ++ .../src/observability/metrics.md | 75 ++ .../src/passphrase/passphrase.md | 70 ++ .../src/password/password.md | 97 ++ .../src/password/pronounceable.md | 72 ++ .../password-generator/src/pin/pin.md | 66 ++ .../src/random/default-rng.md | 54 ++ .../src/random/fisher-yates.md | 64 ++ .../src/random/random-int.md | 68 ++ .../password-generator/src/schemas/schemas.md | 60 ++ .../src/wordlists/eff-long.md | 48 + .../src/wordlists/eff-short.md | 43 + .../src/wordlists/registry.md | 66 ++ .../security/password-strength/README.md | 207 +++++ .../src/assess/assess-reactive.md | 74 ++ .../password-strength/src/assess/assess.md | 70 ++ .../src/dicts/de/wikipedia.md | 63 ++ .../src/dicts/en/english-wikipedia.md | 62 ++ .../password-strength/src/dicts/en/names.md | 71 ++ .../src/dicts/en/passwords.md | 66 ++ .../src/dicts/es/wikipedia.md | 60 ++ .../src/dicts/fr/wikipedia.md | 63 ++ .../src/dicts/load-dictionaries.md | 78 ++ .../src/dicts/ru/wikipedia.md | 60 ++ .../src/dicts/zh-Hans/wikipedia.md | 64 ++ .../src/errors/error-codes.md | 76 ++ .../src/feedback/feedback.md | 69 ++ .../src/graphs/azerty/azerty.md | 66 ++ .../src/graphs/dvorak/dvorak.md | 65 ++ .../src/graphs/qwerty/qwerty.md | 69 ++ .../src/graphs/validate-graph.md | 76 ++ .../src/matchers/date/date.md | 62 ++ .../src/matchers/dictionary/dictionary.md | 87 ++ .../src/matchers/dictionary/l33t-table.md | 71 ++ .../src/matchers/keyboard/keyboard.md | 62 ++ .../src/matchers/regex/regex.md | 73 ++ .../src/matchers/repeat/repeat.md | 61 ++ .../src/matchers/sequence/sequence.md | 71 ++ .../password-strength/src/matchers/types.md | 88 ++ .../src/observability/metrics.md | 72 ++ .../password-strength/src/schemas/schemas.md | 83 ++ .../src/scoring/crack-times.md | 60 ++ .../src/scoring/estimate-guesses.md | 57 ++ .../scoring/most-guessable-match-sequence.md | 69 ++ .../password-strength/src/scoring/score.md | 74 ++ .../security/security-codes/README.md | 116 +++ .../src/core/code-detector/code-detector.md | 104 +++ .../src/core/code-sanitizer/code-sanitizer.md | 98 ++ .../src/errors/security-codes-error.md | 79 ++ .../security-codes/src/patterns/aws.md | 59 ++ .../src/patterns/credit-card.md | 65 ++ .../security-codes/src/patterns/entropy.md | 65 ++ .../security-codes/src/patterns/github.md | 70 ++ .../security-codes/src/patterns/google.md | 65 ++ .../security-codes/src/patterns/jwt.md | 64 ++ .../security-codes/src/patterns/openai.md | 65 ++ .../security-codes/src/patterns/pem.md | 67 ++ .../security-codes/src/patterns/ssh.md | 66 ++ .../security-codes/src/patterns/stripe.md | 68 ++ .../src/types/security-codes.md | 127 +++ .../src/types/security-codes.types.md | 97 ++ .../security/security-codes/src/utils/luhn.md | 69 ++ .../security/server-keys/README.md | 195 ++++ .../src/bin/create-root-keys-chain.md | 57 ++ .../server-keys/src/bin/create-root-keys.md | 57 ++ .../src/bin/create-server-keys-chain.md | 57 ++ .../server-keys/src/bin/create-server-keys.md | 57 ++ .../server-keys/src/bin/get-file-stats.md | 57 ++ .../security/server-keys/src/bin/index.md | 57 ++ .../security/server-keys/src/bin/license.md | 57 ++ .../server-keys/src/bin/prepare-file.md | 57 ++ .../src/bin/roll-server-keys-chain.md | 57 ++ .../server-keys/src/bin/roll-server-keys.md | 57 ++ .../server-keys/src/bin/serve-file.md | 57 ++ .../server-keys/src/bin/validate-file.md | 57 ++ .../server-keys/src/bin/validate-packet.md | 57 ++ .../server-keys/src/bin/verify-key-chain.md | 57 ++ .../server-keys/src/bin/view-chain-public.md | 57 ++ .../security/server-keys/src/bin/view-keys.md | 57 ++ .../src/bin/view-public-key-file.md | 57 ++ .../server-keys/src/bin/view-vault.md | 57 ++ .../server-keys/src/commands/files/files.md | 122 +++ .../src/commands/files/files.types.md | 93 ++ .../src/commands/files/packet-io.md | 87 ++ .../src/commands/files/serve-file.md | 87 ++ .../src/commands/keys/keys-chain.md | 115 +++ .../server-keys/src/commands/keys/keys-io.md | 116 +++ .../server-keys/src/commands/keys/keys.md | 124 +++ .../src/commands/keys/keys.types.md | 69 ++ .../server-keys/src/commands/license/hex.md | 73 ++ .../src/commands/license/license.md | 133 +++ .../src/commands/license/license.types.md | 98 ++ .../src/error-codes/error-codes.md | 94 ++ .../server-keys/src/otel/instruments.md | 89 ++ .../security/server-keys/src/prompt/prompt.md | 108 +++ .../src/run-function/run-function.md | 106 +++ docs/security-stack/security/slsa/README.md | 138 +++ .../slsa/src/assessment/assessment.md | 73 ++ .../slsa/src/attestation/dsse/dsse.md | 87 ++ .../security/slsa/src/errors/slsa-error.md | 81 ++ .../security/slsa/src/otel/slsa-otel.md | 74 ++ .../security/slsa/src/policy/policy.md | 88 ++ .../slsa/src/provenance/canonical-json.md | 59 ++ .../security/slsa/src/provenance/digest.md | 58 ++ .../slsa/src/provenance/provenance.md | 89 ++ .../slsa/src/rekor/inclusion-proof.md | 79 ++ .../security/slsa/src/rekor/rekor-client.md | 90 ++ .../security/slsa/src/sbom/sbom.md | 83 ++ .../security/slsa/src/schemas/parse.md | 67 ++ .../security/slsa/src/verification/checks.md | 76 ++ .../slsa/src/verification/verification.md | 74 ++ docs/security-stack/security/srp/README.md | 191 ++++ .../security/srp/src/client/client-finish.md | 87 ++ .../security/srp/src/client/client-start.md | 70 ++ .../security/srp/src/client/client-verify.md | 68 ++ .../security/srp/src/errors/errors.md | 71 ++ .../srp/src/groups/1024/groups-1024.md | 53 ++ .../srp/src/groups/1536/groups-1536.md | 56 ++ .../srp/src/groups/3072/groups-3072.md | 55 ++ .../srp/src/groups/4096/groups-4096.md | 56 ++ .../srp/src/groups/6144/groups-6144.md | 56 ++ .../srp/src/groups/8192/groups-8192.md | 55 ++ .../security/srp/src/groups/groups-2048.md | 58 ++ .../security/srp/src/hash/hash-bridge.md | 78 ++ .../security-stack/security/srp/src/math/k.md | 52 ++ .../security/srp/src/math/modpow.md | 63 ++ .../security/srp/src/math/pad.md | 51 + .../security/srp/src/math/proof.md | 64 ++ .../security/srp/src/math/rng-bytes.md | 58 ++ .../security-stack/security/srp/src/math/u.md | 61 ++ .../security-stack/security/srp/src/math/x.md | 53 ++ .../security/srp/src/observability/metrics.md | 79 ++ .../security/srp/src/pake/pake-provider.md | 74 ++ .../security/srp/src/params/params.md | 71 ++ .../security/srp/src/schemas/schemas.md | 70 ++ .../security/srp/src/server/server-finish.md | 74 ++ .../security/srp/src/server/server-m2.md | 65 ++ .../security/srp/src/server/server-start.md | 74 ++ .../security/srp/src/verifier/verifier.md | 65 ++ .../security/tpm-struct/README.md | 133 +++ .../security/tpm-struct/src/alg/alg.md | 93 ++ .../security/tpm-struct/src/attest/attest.md | 112 +++ .../tpm-struct/src/attest/serialize.md | 72 ++ .../security/tpm-struct/src/buffer/buffer.md | 86 ++ .../tpm-struct/src/diagnostic/diagnostic.md | 99 ++ .../tpm-struct/src/errors/error-codes.md | 104 +++ .../tpm-struct/src/extra-data/extra-data.md | 81 ++ .../security/tpm-struct/src/name/name.md | 86 ++ .../tpm-struct/src/observability/metrics.md | 115 +++ .../src/public/object-attributes.md | 84 ++ .../security/tpm-struct/src/public/public.md | 102 ++ .../tpm-struct/src/public/serialize.md | 86 ++ .../tpm-struct/src/schemas/schemas.md | 84 ++ .../security/vault-sync/README.md | 126 +++ .../vault-sync/src/crypto-sync/crypto-sync.md | 104 +++ .../security/vault-sync/src/engine/engine.md | 132 +++ .../security/vault-sync/src/errors/codes.md | 74 ++ .../vault-sync/src/errors/vault-sync-error.md | 84 ++ .../security/vault-sync/src/merge/merge.md | 109 +++ .../vault-sync/src/otel/instruments.md | 134 +++ .../security/vault-sync/src/patch/patch.md | 108 +++ .../security/vault-sync/src/queue/queue.md | 118 +++ .../vault-sync/src/schemas/schemas.md | 99 ++ .../security/vault-sync/src/types/types.md | 124 +++ .../src/vector-clock/vector-clock.md | 108 +++ docs/security-stack/security/vault/README.md | 156 ++++ .../vault/src/attachments/attachments.md | 102 ++ .../security/vault/src/container/container.md | 76 ++ .../vault/src/encryption/field-encryption.md | 74 ++ .../security/vault/src/errors/codes.md | 55 ++ .../security/vault/src/errors/vault-error.md | 52 ++ .../security/vault/src/items/helpers.md | 57 ++ .../security/vault/src/items/items.md | 99 ++ .../vault/src/items/migrations/migrations.md | 80 ++ .../security/vault/src/manifest/manifest.md | 84 ++ .../security/vault/src/otel/instruments.md | 71 ++ .../security/vault/src/schemas/schemas.md | 65 ++ .../security/vault/src/search/search.md | 70 ++ .../security/vault/src/shares/shares.md | 89 ++ .../security/vault/src/sync/sync.md | 74 ++ .../security/vault/src/types/adapters.md | 91 ++ .../security/vault/src/types/types.md | 81 ++ .../security/vault/src/vault/lifecycle.md | 77 ++ .../security/vault/src/vault/vault.md | 103 ++ .../security/vault/src/vault/wiring.md | 73 ++ docs/security-stack/security/x509/README.md | 205 ++++ .../x509/src/__fixtures__/build-certs.md | 155 ++++ .../security/x509/src/asn1/decoder.md | 57 ++ .../security/x509/src/asn1/encoder.md | 52 ++ .../security/x509/src/asn1/oid.md | 52 ++ .../security/x509/src/asn1/strings.md | 48 + .../security/x509/src/asn1/time.md | 51 + .../security/x509/src/certificate/name.md | 50 + .../security/x509/src/certificate/parse.md | 54 ++ .../security/x509/src/errors/error-codes.md | 78 ++ .../x509/src/extensions/authority-key-id.md | 56 ++ .../x509/src/extensions/basic-constraints.md | 50 + .../src/extensions/crl-distribution-points.md | 56 ++ .../x509/src/extensions/extended-key-usage.md | 56 ++ .../security/x509/src/extensions/key-usage.md | 56 ++ .../x509/src/extensions/name-constraints.md | 56 ++ .../security/x509/src/extensions/registry.md | 56 ++ .../x509/src/extensions/subject-alt-name.md | 56 ++ .../x509/src/extensions/subject-key-id.md | 56 ++ .../security/x509/src/helpers/chains-to.md | 48 + .../x509/src/helpers/has-name-match.md | 48 + .../security/x509/src/helpers/is-issuer-of.md | 48 + .../x509/src/observability/metrics.md | 66 ++ .../security/x509/src/pem/pem.md | 58 ++ .../security/x509/src/schemas/schemas.md | 56 ++ .../security/x509/src/signature/alg-map.md | 57 ++ .../x509/src/signature/decode-ecdsa-sig.md | 57 ++ .../security/x509/src/signature/verify.md | 57 ++ .../x509/src/validate/trust-anchor.md | 63 ++ .../x509/src/validate/validate-chain.md | 63 ++ docs/testkit/README.md | 29 + docs/testkit/_intro.md | 3 + docs/testkit/testing/README.md | 25 + docs/testkit/testing/_intro.md | 1 + docs/testkit/testing/ab-testing/README.md | 103 ++ .../ab-testing/src/bucketing/bucketing.md | 116 +++ .../experiment-manager/experiment-manager.md | 148 +++ .../ab-testing/src/providers/provider.md | 116 +++ .../testing/ab-testing/src/results/results.md | 118 +++ .../ab-testing/src/targeting/targeting.md | 92 ++ .../testing/ab-testing/src/types/common.md | 151 +++ .../testing/ab-testing/src/types/schemas.md | 107 +++ docs/testkit/testing/testing-dom/README.md | 154 +++ .../testing-dom/src/config/bun-test-config.md | 59 ++ .../testing/testing-dom/src/config/config.md | 125 +++ .../src/config/detect-environment.md | 51 + .../testing-dom/src/config/detect-runner.md | 60 ++ .../testing-dom/src/config/vitest-config.md | 62 ++ .../testing/testing-dom/src/errors/codes.md | 66 ++ .../src/errors/testing-dom-error.md | 61 ++ .../testing-dom/src/matchers/matchers.md | 60 ++ .../src/observability/instrumented.md | 64 ++ .../testing-dom/src/queries/queries.md | 64 ++ .../src/render/render-component.md | 60 ++ .../testing-dom/src/runner/bun-test.md | 62 ++ .../testing/testing-dom/src/runner/mocks.md | 57 ++ .../testing/testing-dom/src/runner/runner.md | 100 ++ .../testing/testing-dom/src/runner/vitest.md | 71 ++ .../testing-dom/src/setup/polyfills.md | 61 ++ .../testing-dom/src/user/setup-user.md | 63 ++ docs/testkit/testing/testing-e2e/README.md | 280 ++++++ .../testing/testing-e2e/docker/README.md | 76 ++ .../src/cloakserve/build-cloakserve-url.md | 92 ++ .../src/cloakserve/cloakserve-connect.md | 102 ++ .../src/config/create-playwright-config.md | 66 ++ .../src/console-monitor/console-monitor.md | 102 ++ .../testing/testing-e2e/src/errors/codes.md | 79 ++ .../src/errors/testing-e2e-error.md | 94 ++ .../launch-with-extension.md | 175 ++++ .../testing-e2e/src/fixtures/extended-test.md | 171 ++++ .../testing-e2e/src/helpers/dismiss-dialog.md | 59 ++ .../testing-e2e/src/helpers/mock-clipboard.md | 63 ++ .../src/helpers/mock-geolocation.md | 58 ++ .../src/helpers/screenshot-on-failure.md | 58 ++ .../src/helpers/wait-for-network-idle.md | 62 ++ .../src/multi-session/create-multi-session.md | 109 +++ .../src/network-monitor/network-monitor.md | 104 +++ .../src/observability/instrumented.md | 66 ++ .../src/page-objects/page-object.md | 87 ++ .../src/presets/stealth-presets.md | 101 ++ .../testing-integration-garage-s3/README.md | 47 + .../src/fixture/garage-s3-fixture.md | 126 +++ .../testing-integration-mailpit/README.md | 52 ++ .../src/fixture/mailpit-fixture.md | 110 +++ .../src/helpers/assert-mail.md | 104 +++ .../testing-integration-oauth-mock/README.md | 64 ++ .../src/control/audit.md | 65 ++ .../src/control/primer.md | 65 ++ .../src/endpoints/authorize.md | 61 ++ .../src/endpoints/openid.md | 57 ++ .../src/endpoints/token.md | 63 ++ .../src/endpoints/userinfo.md | 58 ++ .../src/error-codes/error-codes.md | 80 ++ .../src/server/server.md | 95 ++ .../src/shapes/generic.md | 64 ++ .../src/shapes/github.md | 61 ++ .../src/shapes/google.md | 65 ++ .../testing-integration-postgres/README.md | 43 + .../src/fixture/postgres-fixture.md | 114 +++ .../testing-integration-redis/README.md | 43 + .../src/fixture/redis-fixture.md | 117 +++ .../testing-integration-step-ca/README.md | 126 +++ .../src/fixture/parse-pem-blocks.md | 63 ++ .../src/fixture/step-ca-fixture.md | 86 ++ .../testing-integration-surrealdb/README.md | 45 + .../src/fixture/surrealdb-fixture.md | 112 +++ .../testing-integration-typesense/README.md | 44 + .../src/fixture/typesense-fixture.md | 103 ++ .../testing/testing-integration/README.md | 117 +++ .../src/environment/test-environment.md | 112 +++ .../src/fixture/service-fixture.md | 101 ++ .../src/helpers/health-poller.md | 104 +++ .../src/helpers/skip-if-unavailable.md | 78 ++ .../create-integration-setup-internal.md | 49 + .../src/internal/fixture-registry.md | 45 + .../internal/skip-if-unavailable-internal.md | 41 + .../src/setup/create-integration-setup.md | 91 ++ .../src/setup/global-setup.md | 73 ++ docs/testkit/testing/testing/README.md | 208 +++++ .../testing/src/builders/request/request.md | 144 +++ .../testing/src/builders/response/response.md | 130 +++ .../src/clock/fake-clock/fake-clock.md | 123 +++ .../testing/src/config/create-test-config.md | 85 ++ .../testing/src/constants/clock-constants.md | 82 ++ .../src/constants/fixture-constants.md | 71 ++ .../src/constants/helpers-constants.md | 66 ++ .../testing/src/constants/http-constants.md | 67 ++ .../testing/src/constants/store-constants.md | 78 ++ .../testing/testing/src/context/context.md | 90 ++ .../testing/testing/src/errors/codes.md | 52 ++ .../testing/src/errors/testing-error.md | 128 +++ .../testing/src/factories/factory/factory.md | 156 ++++ .../fixture-manager-internals.md | 97 ++ .../fixture-manager/fixture-manager.md | 146 +++ .../testing/src/helpers/test-helpers.md | 147 +++ .../src/observability/with-observability.md | 77 ++ .../testing/testing/src/runner/bun-test.md | 62 ++ .../testing/testing/src/runner/mocks.md | 57 ++ .../testing/testing/src/runner/runner.md | 93 ++ .../testing/testing/src/runner/vitest.md | 71 ++ .../src/storage/memory-store/memory-store.md | 135 +++ .../testkit/testing/testing/src/types/http.md | 99 ++ .../testing/testing/src/types/http.types.md | 73 ++ docs/threejs/README.md | 17 + docs/threejs/_intro.md | 3 + docs/threejs/r3f/README.md | 13 + docs/threejs/r3f/_intro.md | 1 + docs/threejs/r3f/r3f-networking/README.md | 108 +++ .../server-authority/server-authority.md | 82 ++ .../network-provider-context.md | 63 ++ .../network-provider/network-provider.md | 81 ++ .../components/network-stats/network-stats.md | 64 ++ .../networked-entity/apply-networked-frame.md | 56 ++ .../networked-entity/networked-entity.md | 81 ++ .../src/core/interpolation/interpolation.md | 75 ++ .../src/core/prediction/prediction.md | 72 ++ .../reconciliation-fsm/reconciliation-fsm.md | 68 ++ .../src/core/snapshot-diff/snapshot-diff.md | 74 ++ .../src/core/state-buffer/state-buffer.md | 68 ++ .../src/core/wire-codec/wire-codec.md | 77 ++ .../r3f/r3f-networking/src/errors/errors.md | 80 ++ .../use-network-predict.md | 76 ++ .../use-network-sync/use-network-sync.md | 71 ++ .../use-networked-entity.md | 70 ++ .../src/observability/observability.md | 69 ++ .../src/sync/entity-sync/entity-sync.md | 81 ++ .../sync/interest-manager/interest-manager.md | 74 ++ .../memory-transport/memory-transport.md | 67 ++ .../utils/network-helpers/network-helpers.md | 67 ++ docs/ui/README.md | 34 + docs/ui/_intro.md | 3 + docs/ui/forms/README.md | 14 + docs/ui/forms/_intro.md | 1 + docs/ui/forms/form-builder/README.md | 128 +++ .../src/builder/form-builder/form-builder.md | 80 ++ .../conditional/conditional/conditional.md | 70 ++ .../dependency-graph/dependency-graph.md | 82 ++ .../src/errors/form-error/form-error.md | 84 ++ .../fields/field-registry/field-registry.md | 69 ++ .../src/otel/instruments/instruments.md | 65 ++ .../form-builder/src/schema/schema/schema.md | 67 ++ .../src/serialise/serialise/serialise.md | 68 ++ .../src/state/form-state/form-state.md | 67 ++ .../src/state/undo-redo/undo-redo.md | 70 ++ .../src/submission/submission/submission.md | 79 ++ .../src/validation/validation/validation.md | 69 ++ .../src/validation/validators/validators.md | 75 ++ .../src/zod-schema/zod-schema/zod-schema.md | 60 ++ docs/ui/forms/react-forms/README.md | 533 +++++++++++ .../api-client-context/api-client-context.md | 103 ++ .../core/api-client-context/use-api-client.md | 84 ++ .../src/core/auth-context/auth-context.md | 93 ++ .../src/core/auth-context/use-auth.md | 79 ++ .../core/use-domain-form/use-domain-form.md | 161 ++++ .../use-form-validation.md | 122 +++ .../validation-engine/cross-field-rule.md | 104 +++ .../validation-engine/server-error-mapper.md | 98 ++ .../validation-engine/validation-engine.md | 131 +++ .../react-forms/src/errors/error-codes.md | 90 ++ .../src/errors/react-forms-error.md | 90 ++ .../create-domain-form/create-domain-form.md | 187 ++++ .../src/factory/field-config/field-config.md | 120 +++ .../src/factory/render-field/render-field.md | 162 ++++ .../react-forms/src/locales/augmentation.md | 72 ++ .../forms/react-forms/src/locales/locales.md | 105 +++ .../src/locales/translation-keys.md | 76 ++ .../src/observability/react-forms-metrics.md | 115 +++ .../react-forms/src/primitives/field/field.md | 121 +++ .../src/primitives/money-input/money-input.md | 128 +++ .../src/recipes/async-search/async-search.md | 150 +++ .../src/recipes/conditional/conditional.md | 122 +++ .../repeating-fieldset/repeating-fieldset.md | 173 ++++ .../react-forms/src/recipes/wizard/wizard.md | 176 ++++ .../async-email-unique/async-email-unique.md | 106 +++ .../async-username-available.md | 89 ++ .../src/validation/compose/compose.md | 117 +++ .../react-forms/src/validation/compose/or.md | 74 ++ .../src/validation/compose/sequence.md | 85 ++ .../src/validation/compose/shared.md | 88 ++ .../src/validation/validators/bic/bic.md | 78 ++ .../validators/credit-card/credit-card.md | 82 ++ .../validation/validators/custom/custom.md | 92 ++ .../src/validation/validators/email/email.md | 78 ++ .../src/validation/validators/iban/iban.md | 84 ++ .../validators/max-length/max-length.md | 70 ++ .../validators/min-length/min-length.md | 70 ++ .../password-strength/password-strength.md | 94 ++ .../validation/validators/pattern/pattern.md | 71 ++ .../src/validation/validators/phone/phone.md | 76 ++ .../validators/postcode/postcode.md | 88 ++ .../validators/required/required.md | 81 ++ .../src/validation/validators/url/url.md | 75 ++ docs/ui/react/README.md | 21 + docs/ui/react/_intro.md | 1 + .../react/react-audio-fingerprint/README.md | 91 ++ .../backends/local-backend/local-backend.md | 66 ++ .../fingerprint-match-display.md | 67 ++ .../src/corpus/memory-corpus/memory-corpus.md | 72 ++ .../src/error-codes/error-codes.md | 89 ++ .../audio-fingerprinter.md | 73 ++ .../constellation/constellation.md | 69 ++ .../fingerprint-matcher.md | 67 ++ .../peak-detector/peak-detector.md | 69 ++ .../use-audio-fingerprint.md | 71 ++ .../react-audio-fingerprint/src/test-setup.md | 58 ++ docs/ui/react/react-audio-player/README.md | 136 +++ .../src/error-codes/error-codes.md | 98 ++ .../src/karaoke/lrc-parser/lrc-parser.md | 106 +++ .../karaoke/lyrics-display/lyrics-display.md | 109 +++ .../src/karaoke/use-lyrics/use-lyrics.md | 121 +++ docs/ui/react/react-audio-stream/README.md | 132 +++ .../shared-transport-indicator.md | 67 ++ .../components/stream-mixer/stream-mixer.md | 63 ++ .../stream-permissions-banner.md | 62 ++ .../stream-recorder/stream-recorder.md | 60 ++ .../src/components/stream-room/stream-room.md | 72 ++ .../src/error-codes/error-codes.md | 104 +++ .../src/hooks/internal/use-stream-context.md | 59 ++ .../use-stream-levels/use-stream-levels.md | 54 ++ .../use-stream-mixer/use-stream-mixer.md | 72 ++ .../use-stream-peers/use-stream-peers.md | 61 ++ .../use-stream-permissions.md | 61 ++ .../use-stream-recording.md | 67 ++ .../hooks/use-stream-room/use-stream-room.md | 60 ++ .../use-stream-session/use-stream-session.md | 59 ++ .../use-transport-share.md | 97 ++ .../src/provider/stream-context.md | 61 ++ .../src/provider/stream-provider.md | 69 ++ .../interruption-classifier.md | 104 +++ .../src/session/reconnect.md | 68 ++ .../src/session/session-fsm/session-fsm.md | 110 +++ .../session/stream-session/stream-session.md | 114 +++ .../stream-source-plugin.md | 102 ++ .../src/telemetry/telemetry.md | 91 ++ .../react-audio-stream/src/test-setup.md | 59 ++ .../react-audio-stream/src/test-utils.md | 65 ++ .../src/transport-share/control-channel.md | 76 ++ .../src/transport-share/share-state.md | 67 ++ .../src/transports/transport.md | 81 ++ .../transports/trystero/trystero-transport.md | 80 ++ .../src/transports/webrtc/webrtc-transport.md | 76 ++ .../websocket/websocket-transport.md | 80 ++ docs/ui/react/react-audio/README.md | 206 ++++ .../a11y/aria-value-text/aria-value-text.md | 86 ++ .../keyboard-bindings/keyboard-bindings.md | 121 +++ .../components/audio-player/audio-player.md | 95 ++ .../audio-visualizer/audio-visualizer.md | 90 ++ .../components/basic-player/basic-player.md | 77 ++ .../glados-controls/glados-controls.md | 87 ++ .../components/internal/parameter-keyboard.md | 73 ++ .../src/components/internal/parameter-unit.md | 64 ++ .../components/master-meter/master-meter.md | 88 ++ .../microphone-controls.md | 100 ++ .../midi-controller-setup.md | 112 +++ .../react-audio/src/components/mixer/mixer.md | 94 ++ .../plugin-chain-view/plugin-chain-view.md | 99 ++ .../components/plugin-loader/plugin-loader.md | 90 ++ .../plugin-parameter-knob.md | 107 +++ .../plugin-parameter-slider.md | 102 ++ .../src/components/plugin-slot/plugin-slot.md | 99 ++ .../premium-player/premium-player.md | 88 ++ .../preset-manager/preset-manager.md | 103 ++ .../src/components/track-list/track-list.md | 78 ++ .../src/components/track-row/track-row.md | 80 ++ .../transport-controls/transport-controls.md | 93 ++ .../src/error-codes/error-codes.md | 92 ++ .../src/hooks/use-analyser/use-analyser.md | 120 +++ .../use-audio-engine/use-audio-engine.md | 73 ++ .../use-audio-fx-plugin.md | 78 ++ .../react-audio/src/hooks/use-bus/use-bus.md | 69 ++ .../use-chain-plugin/use-chain-plugin.md | 66 ++ .../use-chain-snapshot/use-chain-snapshot.md | 83 ++ .../use-engine-state/use-engine-state.md | 73 ++ .../use-midi-controller.md | 112 +++ .../src/hooks/use-parameter/use-parameter.md | 98 ++ .../src/hooks/use-playlist/use-playlist.md | 135 +++ .../use-plugin-chain/use-plugin-chain.md | 82 ++ .../src/hooks/use-preset/use-preset.md | 81 ++ .../src/hooks/use-provider-state.md | 70 ++ .../src/hooks/use-timeline/use-timeline.md | 74 ++ .../src/hooks/use-track/use-track.md | 74 ++ .../use-transport-time/use-transport-time.md | 63 ++ .../src/hooks/use-transport/use-transport.md | 78 ++ .../react-audio/src/provider/audio-context.md | 67 ++ .../src/provider/audio-provider.md | 89 ++ .../react-audio/src/provider/chain-map.md | 70 ++ .../src/provider/provider-bus-registry.md | 68 ++ .../src/provider/provider-options.md | 79 ++ .../src/stores/audio-store/audio-store.md | 72 ++ .../src/stores/ui-store/ui-store.md | 78 ++ docs/ui/react/react-audio/src/test-utils.md | 64 ++ docs/ui/react/react-auth-whitelabel/README.md | 106 +++ .../react/react-auth-whitelabel/e2e/README.md | 22 + .../src/components/login-form/login-form.md | 74 ++ .../password-reset-confirm.md | 70 ++ .../password-reset-form.md | 79 ++ .../password-reset-request.md | 64 ++ .../password-reset-success.md | 52 ++ .../register-form/register-form-fields.md | 64 ++ .../register-form/register-form-terms.md | 58 ++ .../components/register-form/register-form.md | 66 ++ .../src/context/auth-context.md | 75 ++ .../src/context/auth-http.md | 63 ++ .../src/context/branding-context.md | 79 ++ .../src/errors/error-codes.md | 65 ++ .../src/errors/react-auth-whitelabel-error.md | 68 ++ .../src/types/branding.schema.md | 59 ++ .../src/utils/navigate-or-call.md | 53 ++ docs/ui/react/react-auth/README.md | 126 +++ .../react-auth/src/client/auth-client.md | 82 ++ .../src/components/auth-guard/auth-guard.md | 55 ++ .../components/auth-provider/auth-provider.md | 56 ++ .../email-verification-view.md | 118 +++ .../forgot-password-form.md | 110 +++ .../src/components/login-form/login-form.md | 110 +++ .../permission-gate/permission-gate.md | 71 ++ .../register-form/register-form-fields.md | 75 ++ .../components/register-form/register-form.md | 127 +++ .../reset-password-form.md | 118 +++ .../react-auth/src/components/test-wrap.md | 58 ++ .../react-auth/src/context/auth-context.md | 74 ++ .../react-auth/src/error-codes/error-codes.md | 79 ++ .../react-auth/src/hooks/use-auth-guard.md | 56 ++ .../react-auth/src/hooks/use-permission.md | 62 ++ .../react-auth/src/lib/better-auth-adapter.md | 60 ++ .../src/observability/react-auth-metrics.md | 68 ++ .../email-verification/email-verification.md | 65 ++ .../pages/forgot-password/forgot-password.md | 70 ++ .../react/react-auth/src/pages/login/login.md | 67 ++ .../pages/profile/profile-account-section.md | 64 ++ .../src/pages/profile/profile-sections.md | 76 ++ .../react-auth/src/pages/profile/profile.md | 85 ++ .../react-auth/src/pages/register/register.md | 68 ++ .../pages/reset-password/reset-password.md | 56 ++ .../react-auth/src/translations/cy-gb.md | 37 + .../react-auth/src/translations/en-gb.md | 44 + .../react-auth/src/translations/zh-cn.md | 36 + .../react/react-auth/src/types/auth.types.md | 61 ++ .../react/react-auth/src/types/crud.types.md | 53 ++ docs/ui/react/react-control-surface/README.md | 114 +++ .../button-latching/button-latching.md | 69 ++ .../button-momentary/button-momentary.md | 74 ++ .../digital-display/digital-display.md | 110 +++ .../src/controls/drum-pad/drum-pad.md | 132 +++ .../src/controls/image/image.md | 70 ++ .../src/controls/jog-wheel/jog-wheel.md | 97 ++ .../src/controls/knob/knob.md | 132 +++ .../src/controls/led/led.md | 64 ++ .../src/controls/meter-peak/meter-peak.md | 96 ++ .../controls/meter-spectral/meter-spectral.md | 94 ++ .../src/controls/meter-vu/meter-vu.md | 82 ++ .../src/controls/piano-key/piano-key.md | 128 +++ .../src/controls/slider-h/slider-h.md | 105 +++ .../src/controls/slider-v/slider-helpers.md | 93 ++ .../src/controls/slider-v/slider-v.md | 109 +++ .../src/controls/switch-2/switch-2.md | 69 ++ .../src/controls/switch-3/switch-3.md | 72 ++ .../src/controls/text-label/text-label.md | 62 ++ .../src/controls/xy-pad/xy-pad.md | 104 +++ .../src/error-codes/error-codes.md | 90 ++ .../src/grouping/group/group.md | 68 ++ .../src/grouping/panel/panel.md | 69 ++ .../src/grouping/rack/rack.md | 72 ++ .../binding-registry/binding-registry.md | 88 ++ .../binding-registry/handlers/compound.md | 56 ++ .../runtime/binding-registry/handlers/dmx.md | 54 ++ .../binding-registry/handlers/midi-in.md | 57 ++ .../binding-registry/handlers/midi-out.md | 64 ++ .../binding-registry/handlers/plugin-param.md | 61 ++ .../binding-registry/handlers/transport.md | 57 ++ .../src/runtime/surface.md | 102 ++ .../src/skin/surface-skin-provider.md | 88 ++ .../src/telemetry/telemetry.md | 75 ++ docs/ui/react/react-midi/README.md | 166 ++++ .../midi-activity-indicator.md | 71 ++ .../midi-device-list/midi-device-list.md | 85 ++ .../react-midi/src/error-codes/error-codes.md | 82 ++ .../react-midi/src/hooks/use-cc14/use-cc14.md | 65 ++ .../react-midi/src/hooks/use-midi-context.md | 70 ++ .../use-midi-devices/use-midi-devices.md | 81 ++ .../hooks/use-midi-input/use-midi-input.md | 79 ++ .../use-midi-messages/use-midi-messages.md | 72 ++ .../hooks/use-midi-output/use-midi-output.md | 84 ++ .../react-midi/src/hooks/use-midi/use-midi.md | 72 ++ .../react-midi/src/hooks/use-nrpn/use-nrpn.md | 69 ++ .../react-midi/src/hooks/use-rpn/use-rpn.md | 65 ++ .../react-midi/src/midi-contract/codec.md | 69 ++ .../src/midi-contract/midi-message.md | 68 ++ .../react-midi/src/midi-contract/reducers.md | 67 ++ .../react-midi/src/port/web-midi-port.md | 72 ++ .../react-midi/src/provider/midi-context.md | 70 ++ .../react-midi/src/provider/midi-provider.md | 75 ++ .../react-midi/src/telemetry/telemetry.md | 66 ++ docs/ui/react/react-midi/src/test-setup.md | 62 ++ docs/ui/react/react-midi/src/test-utils.md | 85 ++ docs/ui/react/react-ui/README.md | 876 ++++++++++++++++++ .../react/react-ui/scripts/check-i18n-keys.md | 77 ++ .../react-ui/scripts/check-registry-eject.md | 63 ++ .../src/components/accordion/accordion.md | 166 ++++ .../accordion/accordion.variants.md | 83 ++ .../components/alert-dialog/alert-dialog.md | 163 ++++ .../alert-dialog/alert-dialog.variants.md | 69 ++ .../react-ui/src/components/alert/alert.md | 125 +++ .../src/components/alert/alert.variants.md | 57 ++ .../components/aspect-ratio/aspect-ratio.md | 124 +++ .../aspect-ratio/aspect-ratio.variants.md | 55 ++ .../react-ui/src/components/avatar/avatar.md | 111 +++ .../src/components/avatar/avatar.variants.md | 55 ++ .../react-ui/src/components/badge/badge.md | 88 ++ .../src/components/badge/badge.variants.md | 54 ++ .../src/components/breadcrumb/breadcrumb.md | 179 ++++ .../breadcrumb/breadcrumb.variants.md | 85 ++ .../react-ui/src/components/button/button.md | 118 +++ .../src/components/button/button.variants.md | 57 ++ .../src/components/calendar/calendar.md | 105 +++ .../calendar/calendar.test-fixtures.md | 63 ++ .../components/calendar/calendar.variants.md | 42 + .../react-ui/src/components/card/card.md | 135 +++ .../src/components/card/card.variants.md | 54 ++ .../src/components/checkbox/checkbox.md | 148 +++ .../components/checkbox/checkbox.variants.md | 53 ++ .../src/components/collapsible/collapsible.md | 123 +++ .../collapsible/collapsible.variants.md | 70 ++ .../confirm-delete-dialog.md | 172 ++++ .../confirm-delete-dialog.test-fixtures.md | 63 ++ .../components/context-menu/context-menu.md | 171 ++++ .../context-menu/context-menu.variants.md | 68 ++ .../src/components/data-table/data-table.md | 150 +++ .../data-table/data-table.variants.md | 44 + .../react-ui/src/components/dialog/dialog.md | 181 ++++ .../src/components/dialog/dialog.variants.md | 71 ++ .../react-ui/src/components/drawer/drawer.md | 149 +++ .../src/components/drawer/drawer.variants.md | 64 ++ .../components/dropdown-menu/dropdown-menu.md | 192 ++++ .../dropdown-menu/dropdown-menu.variants.md | 96 ++ .../react-ui/src/components/empty/empty.md | 141 +++ .../src/components/empty/empty.variants.md | 52 ++ .../error-boundary/error-boundary.md | 156 ++++ .../error-boundary/error-boundary.metrics.md | 75 ++ .../error-boundary.test-fixtures.md | 64 ++ .../error-boundary/error-boundary.variants.md | 71 ++ .../src/components/field-group/field-group.md | 116 +++ .../field-group/field-group.variants.md | 55 ++ .../src/components/field-set/field-set.md | 131 +++ .../field-set/field-set.variants.md | 59 ++ .../react-ui/src/components/field/field.md | 141 +++ .../src/components/field/field.variants.md | 78 ++ .../src/components/hover-card/hover-card.md | 128 +++ .../hover-card/hover-card.variants.md | 52 ++ .../src/components/input-group/input-group.md | 163 ++++ .../input-group/input-group.variants.md | 80 ++ .../input/input-number/input-number.md | 80 ++ .../react-ui/src/components/input/input.md | 117 +++ .../src/components/input/input.variants.md | 52 ++ .../react-ui/src/components/label/label.md | 110 +++ .../src/components/label/label.variants.md | 48 + .../src/components/menubar/menubar.md | 207 +++++ .../components/menubar/menubar.variants.md | 89 ++ .../src/components/pagination/pagination.md | 205 ++++ .../pagination/pagination.variants.md | 77 ++ .../src/components/popover/popover.md | 130 +++ .../components/popover/popover.variants.md | 52 ++ .../src/components/progress/progress.md | 94 ++ .../components/progress/progress.variants.md | 52 ++ .../src/components/radio-group/radio-group.md | 147 +++ .../radio-group/radio-group.variants.md | 61 ++ .../src/components/resizable/resizable.md | 163 ++++ .../resizable/resizable.variants.md | 79 ++ .../src/components/scroll-area/scroll-area.md | 132 +++ .../scroll-area/scroll-area.variants.md | 79 ++ .../react-ui/src/components/select/select.md | 154 +++ .../components/select/select.test-fixtures.md | 63 ++ .../src/components/select/select.variants.md | 46 + .../src/components/separator/separator.md | 108 +++ .../separator/separator.variants.md | 54 ++ .../react-ui/src/components/sheet/sheet.md | 146 +++ .../src/components/sheet/sheet.variants.md | 66 ++ .../src/components/skeleton/skeleton.md | 100 ++ .../components/skeleton/skeleton.variants.md | 51 + .../react-ui/src/components/sonner/sonner.md | 156 ++++ .../src/components/sonner/sonner.variants.md | 63 ++ .../src/components/spinner/spinner.md | 87 ++ .../components/spinner/spinner.variants.md | 50 + .../components/status-badge/status-badge.md | 97 ++ .../status-badge/status-badge.variants.md | 55 ++ .../react-ui/src/components/switch/switch.md | 124 +++ .../src/components/switch/switch.variants.md | 66 ++ .../react-ui/src/components/table/table.md | 171 ++++ .../src/components/table/table.variants.md | 54 ++ .../react-ui/src/components/tabs/tabs.md | 141 +++ .../src/components/tabs/tabs.variants.md | 73 ++ .../src/components/textarea/textarea.md | 103 ++ .../components/textarea/textarea.variants.md | 55 ++ .../components/theme-toggle/theme-toggle.md | 132 +++ .../theme-toggle/theme-toggle.variants.md | 64 ++ .../react-ui/src/components/toast/toast.md | 77 ++ .../components/toggle-group/toggle-group.md | 138 +++ .../toggle-group/toggle-group.variants.md | 67 ++ .../react-ui/src/components/toggle/toggle.md | 145 +++ .../src/components/toggle/toggle.variants.md | 59 ++ .../src/components/tooltip/tooltip.md | 155 ++++ .../components/tooltip/tooltip.variants.md | 57 ++ .../use-toast-sonner-bridge.md | 126 +++ .../react/react-ui/src/errors/error-codes.md | 86 ++ .../react-ui/src/errors/react-ui-error.md | 80 ++ .../src/hooks/use-mobile/use-mobile.md | 69 ++ .../react-ui/src/hooks/use-toast/use-toast.md | 91 ++ .../src/i18n/formatted-cell/formatted-cell.md | 78 ++ .../formatted-currency/formatted-currency.md | 62 ++ .../src/i18n/formatted-date/formatted-date.md | 60 ++ .../src/i18n/formatted-list/formatted-list.md | 59 ++ .../formatted-message/formatted-message.md | 63 ++ .../i18n/formatted-number/formatted-number.md | 58 ++ .../formatted-relative-time.md | 61 ++ .../react/react-ui/src/i18n/plural/plural.md | 66 ++ .../react-ui-i18n-bridge.md | 67 ++ .../src/i18n/stories-shell/stories-shell.md | 87 ++ .../i18n/tanstack-bridge/tanstack-bridge.md | 75 ++ .../validation-message-bridge.md | 87 ++ .../react-ui/src/locales/augmentation.md | 74 ++ .../react-ui/src/locales/locales.types.md | 62 ++ docs/ui/react/react-ui/src/locales/schema.md | 78 ++ .../react-ui/src/locales/translation-keys.md | 46 + .../src/observability/react-ui-metrics.md | 106 +++ .../react/react-ui/src/pack/pack-context.md | 78 ++ .../pack-registry-provider.md | 86 ++ .../pack/runtime-override/runtime-override.md | 76 ++ .../use-pack-component/use-pack-component.md | 76 ++ .../src/pack/version-check/version-check.md | 66 ++ .../react-ui-provider/react-ui-provider.md | 98 ++ .../src/theme/layer-stack/layer-stack.md | 85 ++ .../react/react-ui/src/theme/theme-context.md | 93 ++ .../theme/theme-provider/theme-provider.md | 97 ++ .../theme/theme-switcher/theme-switcher.md | 107 +++ .../react/react-ui/src/theme/themes/dark.md | 75 ++ .../src/theme/themes/high-contrast.md | 75 ++ .../react/react-ui/src/theme/themes/light.md | 78 ++ .../use-resolved-theme-tokens.md | 81 ++ .../use-theme-mutator/use-theme-mutator.md | 115 +++ .../use-theme-tokens/use-theme-tokens.md | 77 ++ .../react-ui/src/theme/use-theme/use-theme.md | 87 ++ .../use-themed-variants.md | 88 ++ docs/ui/react/react-ui/src/utils/cn/cn.md | 87 ++ .../react/react-ui/src/utils/motion/motion.md | 82 ++ .../react/react-ui/src/variants/variants.md | 80 ++ docs/ui/react/react-ui/src/version.md | 63 ++ .../.claude-plugin/plugin.json | 5 + plugins/document-navigator/skills/sp/SKILL.md | 88 ++ .../.claude-plugin/plugin.json | 5 + .../skills/sp-ab-testing/SKILL.md | 52 ++ .../skills/sp-analytics-browser/SKILL.md | 96 ++ .../skills/sp-audience-rules/SKILL.md | 53 ++ .../skills/sp-audio-analysis-beat/SKILL.md | 46 + .../sp-audio-analysis-loudness/SKILL.md | 45 + .../skills/sp-audio-analysis-pitch/SKILL.md | 47 + .../sp-audio-analysis-spectrum/SKILL.md | 48 + .../skills/sp-audio-cli/SKILL.md | 78 ++ .../sp-audio-codec-ffmpeg-native/SKILL.md | 75 ++ .../sp-audio-codec-ffmpeg-wasm/SKILL.md | 72 ++ .../skills/sp-audio-codecs/SKILL.md | 80 ++ .../skills/sp-audio-controllers/SKILL.md | 63 ++ .../skills/sp-audio-core/SKILL.md | 67 ++ .../skills/sp-audio-decode-wav/SKILL.md | 52 ++ .../skills/sp-audio-engine-browser/SKILL.md | 62 ++ .../skills/sp-audio-engine-server/SKILL.md | 61 ++ .../skills/sp-audio-fingerprint/SKILL.md | 45 + .../SKILL.md | 43 + .../sp-audio-fx-plugin-audio-player/SKILL.md | 44 + .../sp-audio-fx-plugin-auto-filter/SKILL.md | 42 + .../skills/sp-audio-fx-plugin-base/SKILL.md | 69 ++ .../skills/sp-audio-fx-plugin-chorus/SKILL.md | 41 + .../sp-audio-fx-plugin-compressor/SKILL.md | 48 + .../skills/sp-audio-fx-plugin-delay/SKILL.md | 47 + .../sp-audio-fx-plugin-distortion/SKILL.md | 44 + .../skills/sp-audio-fx-plugin-eq/SKILL.md | 52 ++ .../skills/sp-audio-fx-plugin-filter/SKILL.md | 44 + .../sp-audio-fx-plugin-flanger/SKILL.md | 42 + .../sp-audio-fx-plugin-game-audio/SKILL.md | 56 ++ .../skills/sp-audio-fx-plugin-gate/SKILL.md | 44 + .../skills/sp-audio-fx-plugin-glados/SKILL.md | 46 + .../sp-audio-fx-plugin-limiter/SKILL.md | 43 + .../sp-audio-fx-plugin-microphone/SKILL.md | 59 ++ .../skills/sp-audio-fx-plugin-mixer/SKILL.md | 55 ++ .../skills/sp-audio-fx-plugin-phaser/SKILL.md | 44 + .../sp-audio-fx-plugin-pitch-shifter/SKILL.md | 43 + .../skills/sp-audio-fx-plugin-reverb/SKILL.md | 66 ++ .../sp-audio-fx-plugin-sampler/SKILL.md | 60 ++ .../sp-audio-fx-plugin-spatial/SKILL.md | 54 ++ .../sp-audio-fx-plugin-spessasynth/SKILL.md | 75 ++ .../sp-audio-fx-plugin-synthesizer/SKILL.md | 62 ++ .../sp-audio-fx-plugin-tremolo/SKILL.md | 52 ++ .../sp-audio-fx-plugin-widener/SKILL.md | 48 + .../skills/sp-audio-ir-core/SKILL.md | 54 ++ .../skills/sp-audio-ir-loader/SKILL.md | 52 ++ .../sp-audio-ir-room-plugin-club/SKILL.md | 49 + .../sp-audio-ir-room-plugin-pool/SKILL.md | 43 + .../skills/sp-audio-metadata/SKILL.md | 54 ++ .../skills/sp-audio-sprite-packer/SKILL.md | 54 ++ .../skills/sp-audio-sprite-player/SKILL.md | 51 + .../skills/sp-audio-timeline/SKILL.md | 60 ++ .../skills/sp-audio-transport/SKILL.md | 66 ++ .../skills/sp-audit-logging/SKILL.md | 92 ++ .../library-navigator/skills/sp-auth/SKILL.md | 103 ++ .../skills/sp-barcode/SKILL.md | 144 +++ .../skills/sp-better-auth-surrealdb/SKILL.md | 100 ++ .../skills/sp-bitpacker-compressed/SKILL.md | 85 ++ .../skills/sp-bitpacker-crypto/SKILL.md | 188 ++++ .../skills/sp-bitpacker-delta/SKILL.md | 154 +++ .../skills/sp-bitpacker-game/SKILL.md | 221 +++++ .../skills/sp-bitpacker-network/SKILL.md | 179 ++++ .../skills/sp-bitpacker-schema/SKILL.md | 180 ++++ .../skills/sp-bitpacker-strategies/SKILL.md | 199 ++++ .../skills/sp-bitpacker-streaming/SKILL.md | 197 ++++ .../skills/sp-bitpacker-validation/SKILL.md | 152 +++ .../skills/sp-bitpacker/SKILL.md | 151 +++ .../skills/sp-booking/SKILL.md | 223 +++++ .../skills/sp-broadcast-channel/SKILL.md | 108 +++ .../skills/sp-bytes/SKILL.md | 113 +++ .../skills/sp-cache-redis/SKILL.md | 106 +++ .../skills/sp-cache-storage/SKILL.md | 133 +++ .../skills/sp-cache/SKILL.md | 162 ++++ .../skills/sp-caddy-imgproxy/SKILL.md | 174 ++++ .../skills/sp-campaigns/SKILL.md | 139 +++ .../library-navigator/skills/sp-cbor/SKILL.md | 164 ++++ .../library-navigator/skills/sp-cli/SKILL.md | 56 ++ .../skills/sp-clipboard/SKILL.md | 132 +++ .../skills/sp-colour-convert-adapt/SKILL.md | 85 ++ .../skills/sp-colour-convert-cieluv/SKILL.md | 110 +++ .../skills/sp-colour-convert-cmyk/SKILL.md | 90 ++ .../skills/sp-colour-convert-hsluv/SKILL.md | 97 ++ .../skills/sp-colour-filter-cct/SKILL.md | 81 ++ .../skills/sp-colour-filter-cmc/SKILL.md | 77 ++ .../sp-colour-filter-greyscale/SKILL.md | 66 ++ .../skills/sp-colour-filter-sepia/SKILL.md | 69 ++ .../skills/sp-colours/SKILL.md | 166 ++++ .../skills/sp-compress-image/SKILL.md | 158 ++++ .../skills/sp-compress-svg/SKILL.md | 126 +++ .../skills/sp-config/SKILL.md | 176 ++++ .../skills/sp-contacts/SKILL.md | 56 ++ .../skills/sp-control-surface-schema/SKILL.md | 61 ++ .../skills/sp-controller/SKILL.md | 120 +++ .../library-navigator/skills/sp-crdt/SKILL.md | 152 +++ .../sp-create-suaveplan-plugin/SKILL.md | 50 + .../library-navigator/skills/sp-cron/SKILL.md | 192 ++++ .../skills/sp-crypto-bin/SKILL.md | 112 +++ .../skills/sp-crypto-browser/SKILL.md | 145 +++ .../skills/sp-crypto-cipher/SKILL.md | 138 +++ .../skills/sp-crypto-cli/SKILL.md | 153 +++ .../skills/sp-crypto-core/SKILL.md | 130 +++ .../skills/sp-crypto-curve/SKILL.md | 107 +++ .../skills/sp-crypto-hash/SKILL.md | 151 +++ .../skills/sp-crypto-keys/SKILL.md | 198 ++++ .../skills/sp-crypto-rsa/SKILL.md | 166 ++++ .../skills/sp-crypto-sodium/SKILL.md | 122 +++ .../skills/sp-crypto-utils/SKILL.md | 166 ++++ .../skills/sp-crypto-vault/SKILL.md | 189 ++++ .../skills/sp-crypto/SKILL.md | 171 ++++ .../skills/sp-cryptocurrency/SKILL.md | 201 ++++ .../sp-currency-provider-binance/SKILL.md | 112 +++ .../sp-currency-provider-coingecko/SKILL.md | 103 ++ .../SKILL.md | 116 +++ .../SKILL.md | 126 +++ .../skills/sp-currency-provider-ecb/SKILL.md | 115 +++ .../sp-currency-provider-fixer/SKILL.md | 121 +++ .../sp-currency-provider-kraken/SKILL.md | 110 +++ .../SKILL.md | 127 +++ .../sp-currency-provider-virtual/SKILL.md | 137 +++ .../skills/sp-currency-providers/SKILL.md | 144 +++ .../skills/sp-currency/SKILL.md | 150 +++ .../skills/sp-data-masking/SKILL.md | 87 ++ .../skills/sp-datetime/SKILL.md | 172 ++++ .../skills/sp-db-sqlite/SKILL.md | 112 +++ .../library-navigator/skills/sp-db/SKILL.md | 97 ++ .../skills/sp-dedup/SKILL.md | 127 +++ .../skills/sp-delivery-tracking/SKILL.md | 153 +++ .../library-navigator/skills/sp-diff/SKILL.md | 123 +++ .../skills/sp-discord-client/SKILL.md | 115 +++ .../skills/sp-dmarc/SKILL.md | 114 +++ .../skills/sp-docker-nvidia/SKILL.md | 48 + .../library-navigator/skills/sp-docs/SKILL.md | 142 +++ .../skills/sp-domain-normalizer/SKILL.md | 146 +++ .../skills/sp-drive-mesh-protocol/SKILL.md | 124 +++ .../skills/sp-drive-mesh/SKILL.md | 100 ++ .../skills/sp-drive-plugin-cache/SKILL.md | 106 +++ .../skills/sp-drive-plugin-chunks/SKILL.md | 118 +++ .../skills/sp-drive-react-sharing/SKILL.md | 122 +++ .../skills/sp-drive-sharing/SKILL.md | 136 +++ .../sp-drive-storage-archive-core/SKILL.md | 102 ++ .../skills/sp-drive-storage-zip/SKILL.md | 85 ++ .../skills/sp-drive-template/SKILL.md | 109 +++ .../skills/sp-drive-transport-https/SKILL.md | 95 ++ .../skills/sp-drive-transport-webrtc/SKILL.md | 103 ++ .../skills/sp-drive-uri/SKILL.md | 95 ++ .../skills/sp-drive-webrtc/SKILL.md | 133 +++ .../skills/sp-drive/SKILL.md | 98 ++ .../library-navigator/skills/sp-ecs/SKILL.md | 108 +++ .../skills/sp-electrobun/SKILL.md | 61 ++ .../skills/sp-email-processing/SKILL.md | 184 ++++ .../skills/sp-email-templates/SKILL.md | 160 ++++ .../skills/sp-emailer/SKILL.md | 190 ++++ .../skills/sp-emblem-solver/SKILL.md | 193 ++++ .../library-navigator/skills/sp-env/SKILL.md | 200 ++++ .../skills/sp-error/SKILL.md | 219 +++++ .../library-navigator/skills/sp-etl/SKILL.md | 89 ++ .../skills/sp-event-sourcing/SKILL.md | 108 +++ .../skills/sp-events-metrics/SKILL.md | 72 ++ .../skills/sp-events-otel/SKILL.md | 82 ++ .../skills/sp-events-schema/SKILL.md | 80 ++ .../skills/sp-events-transport/SKILL.md | 89 ++ .../skills/sp-events/SKILL.md | 118 +++ .../library-navigator/skills/sp-exif/SKILL.md | 175 ++++ .../skills/sp-feature-flags/SKILL.md | 101 ++ .../skills/sp-font-compress/SKILL.md | 84 ++ .../skills/sp-font-convert/SKILL.md | 90 ++ .../skills/sp-font-decompress/SKILL.md | 92 ++ .../skills/sp-font-subset/SKILL.md | 114 +++ .../skills/sp-form-builder/SKILL.md | 86 ++ .../library-navigator/skills/sp-fsm/SKILL.md | 175 ++++ .../skills/sp-game-server/SKILL.md | 149 +++ .../skills/sp-geo-earth/SKILL.md | 117 +++ .../skills/sp-geo-planet/SKILL.md | 128 +++ .../library-navigator/skills/sp-geo/SKILL.md | 145 +++ .../skills/sp-health-check/SKILL.md | 90 ++ .../library-navigator/skills/sp-hibp/SKILL.md | 84 ++ .../skills/sp-i18n-backend-chained/SKILL.md | 52 ++ .../sp-i18n-backend-fs-multifile/SKILL.md | 44 + .../skills/sp-i18n-backend-http/SKILL.md | 46 + .../skills/sp-i18n-backend-memory/SKILL.md | 59 ++ .../skills/sp-i18n-backend-storage/SKILL.md | 47 + .../skills/sp-i18n-detector/SKILL.md | 58 ++ .../sp-i18n-formatter-collator/SKILL.md | 50 + .../sp-i18n-formatter-currency/SKILL.md | 51 + .../skills/sp-i18n-formatter-date/SKILL.md | 53 ++ .../sp-i18n-formatter-display-name/SKILL.md | 47 + .../skills/sp-i18n-formatter-list/SKILL.md | 49 + .../skills/sp-i18n-formatter-number/SKILL.md | 49 + .../sp-i18n-formatter-relative-time/SKILL.md | 51 + .../sp-i18n-formatter-segmenter/SKILL.md | 53 ++ .../skills/sp-i18n-icu-parser/SKILL.md | 55 ++ .../skills/sp-i18n-shared/SKILL.md | 57 ++ .../library-navigator/skills/sp-i18n/SKILL.md | 56 ++ .../skills/sp-idempotency/SKILL.md | 185 ++++ .../skills/sp-image-quantisation/SKILL.md | 168 ++++ .../skills/sp-image/SKILL.md | 164 ++++ .../skills/sp-imessage-adapter/SKILL.md | 172 ++++ .../skills/sp-install-agent-skills/SKILL.md | 49 + .../skills/sp-installer/SKILL.md | 57 ++ .../skills/sp-javy-cli-darwin-arm64/SKILL.md | 41 + .../skills/sp-javy-cli-darwin-x64/SKILL.md | 41 + .../skills/sp-javy-cli-linux-arm64/SKILL.md | 41 + .../skills/sp-javy-cli-linux-x64/SKILL.md | 41 + .../skills/sp-javy-cli-win32-x64/SKILL.md | 41 + .../skills/sp-job-scheduler/SKILL.md | 203 ++++ .../library-navigator/skills/sp-json/SKILL.md | 127 +++ .../library-navigator/skills/sp-jws/SKILL.md | 96 ++ .../skills/sp-jwt-tenant/SKILL.md | 88 ++ .../skills/sp-license/SKILL.md | 94 ++ .../skills/sp-linter/SKILL.md | 103 ++ .../skills/sp-locale-data/SKILL.md | 56 ++ .../skills/sp-logger/SKILL.md | 130 +++ .../skills/sp-macos-contacts/SKILL.md | 53 ++ .../skills/sp-macos-keychain/SKILL.md | 78 ++ .../library-navigator/skills/sp-mcp/SKILL.md | 65 ++ .../skills/sp-media/SKILL.md | 53 ++ .../library-navigator/skills/sp-midi/SKILL.md | 60 ++ .../skills/sp-migration/SKILL.md | 118 +++ .../library-navigator/skills/sp-mime/SKILL.md | 172 ++++ .../skills/sp-money/SKILL.md | 164 ++++ .../skills/sp-network-bootstrap/SKILL.md | 67 ++ .../skills/sp-network-discovery-crdt/SKILL.md | 64 ++ .../sp-network-discovery-gundb/SKILL.md | 73 ++ .../sp-network-discovery-hybrid/SKILL.md | 74 ++ .../sp-network-discovery-peerjs/SKILL.md | 69 ++ .../sp-network-discovery-trystero/SKILL.md | 72 ++ .../sp-network-discovery-webtorrent/SKILL.md | 62 ++ .../skills/sp-network-gundb-server/SKILL.md | 62 ++ .../skills/sp-network-libp2p-server/SKILL.md | 68 ++ .../sp-network-plugin-assignment/SKILL.md | 65 ++ .../sp-network-plugin-audit-mesh/SKILL.md | 78 ++ .../skills/sp-network-plugin-auth/SKILL.md | 56 ++ .../SKILL.md | 62 ++ .../SKILL.md | 71 ++ .../SKILL.md | 80 ++ .../sp-network-plugin-devtools/SKILL.md | 77 ++ .../sp-network-plugin-failover/SKILL.md | 73 ++ .../sp-network-plugin-governance/SKILL.md | 77 ++ .../sp-network-plugin-intra-relay/SKILL.md | 72 ++ .../sp-network-plugin-middleware/SKILL.md | 70 ++ .../sp-network-plugin-migration/SKILL.md | 62 ++ .../skills/sp-network-plugin-monitor/SKILL.md | 94 ++ .../sp-network-plugin-partition/SKILL.md | 65 ++ .../sp-network-plugin-protocol/SKILL.md | 80 ++ .../skills/sp-network-plugin-qos/SKILL.md | 66 ++ .../sp-network-plugin-registry/SKILL.md | 63 ++ .../skills/sp-network-plugin-relay/SKILL.md | 75 ++ .../sp-network-plugin-server-bridge/SKILL.md | 80 ++ .../skills/sp-network-plugin-session/SKILL.md | 79 ++ .../sp-network-plugin-simulation/SKILL.md | 80 ++ .../skills/sp-network-plugin-state/SKILL.md | 89 ++ .../sp-network-plugin-topology/SKILL.md | 69 ++ .../SKILL.md | 79 ++ .../skills/sp-network-testing/SKILL.md | 75 ++ .../sp-network-transport-hyperswarm/SKILL.md | 78 ++ .../sp-network-transport-libp2p/SKILL.md | 81 ++ .../sp-network-transport-standby/SKILL.md | 69 ++ .../sp-network-transport-webrtc/SKILL.md | 75 ++ .../sp-network-transport-websockets/SKILL.md | 59 ++ .../sp-network-trystero-server/SKILL.md | 58 ++ .../skills/sp-network/SKILL.md | 70 ++ .../skills/sp-noise/SKILL.md | 132 +++ .../skills/sp-notification-channel/SKILL.md | 256 +++++ .../skills/sp-oauth-client/SKILL.md | 111 +++ .../skills/sp-opentelemetry/SKILL.md | 129 +++ .../library-navigator/skills/sp-otp/SKILL.md | 95 ++ .../skills/sp-overview/SKILL.md | 55 ++ .../skills/sp-packer-browser/SKILL.md | 110 +++ .../skills/sp-packer/SKILL.md | 205 ++++ .../skills/sp-pagination/SKILL.md | 201 ++++ .../skills/sp-password-formats/SKILL.md | 74 ++ .../skills/sp-password-generator/SKILL.md | 82 ++ .../skills/sp-password-strength/SKILL.md | 91 ++ .../skills/sp-payment-provider-adyen/SKILL.md | 153 +++ .../sp-payment-provider-mollie/SKILL.md | 101 ++ .../sp-payment-provider-paypal/SKILL.md | 138 +++ .../sp-payment-provider-square/SKILL.md | 136 +++ .../sp-payment-provider-stripe/SKILL.md | 106 +++ .../skills/sp-payment-providers/SKILL.md | 146 +++ .../skills/sp-payment/SKILL.md | 266 ++++++ .../library-navigator/skills/sp-pdf/SKILL.md | 179 ++++ .../skills/sp-permissions/SKILL.md | 125 +++ .../skills/sp-ports/SKILL.md | 91 ++ .../skills/sp-profiler/SKILL.md | 108 +++ .../skills/sp-pseudo-random/SKILL.md | 112 +++ .../library-navigator/skills/sp-pwa/SKILL.md | 208 +++++ .../skills/sp-qrcode/SKILL.md | 167 ++++ .../sp-queue-distribution-http/SKILL.md | 91 ++ .../SKILL.md | 91 ++ .../skills/sp-queue-distribution/SKILL.md | 113 +++ .../skills/sp-queue/SKILL.md | 141 +++ .../skills/sp-r3f-networking/SKILL.md | 65 ++ .../skills/sp-random/SKILL.md | 130 +++ .../skills/sp-rate-limiter/SKILL.md | 168 ++++ .../sp-react-audio-fingerprint/SKILL.md | 77 ++ .../skills/sp-react-audio-player/SKILL.md | 73 ++ .../skills/sp-react-audio-stream/SKILL.md | 76 ++ .../skills/sp-react-audio/SKILL.md | 108 +++ .../skills/sp-react-auth-whitelabel/SKILL.md | 81 ++ .../skills/sp-react-auth/SKILL.md | 97 ++ .../skills/sp-react-control-surface/SKILL.md | 87 ++ .../skills/sp-react-forms/SKILL.md | 103 ++ .../skills/sp-react-i18n/SKILL.md | 95 ++ .../skills/sp-react-midi/SKILL.md | 90 ++ .../sp-react-network-libp2p-demo/SKILL.md | 65 ++ .../skills/sp-react-packer/SKILL.md | 71 ++ .../skills/sp-react-ui/SKILL.md | 152 +++ .../skills/sp-readline/SKILL.md | 106 +++ .../skills/sp-retry/SKILL.md | 157 ++++ .../skills/sp-rules-hono/SKILL.md | 116 +++ .../skills/sp-rules/SKILL.md | 157 ++++ .../skills/sp-sandbox/SKILL.md | 132 +++ .../skills/sp-schema-registry/SKILL.md | 138 +++ .../skills/sp-search/SKILL.md | 94 ++ .../skills/sp-security-codes/SKILL.md | 75 ++ .../library-navigator/skills/sp-seed/SKILL.md | 120 +++ .../skills/sp-serialize/SKILL.md | 153 +++ .../skills/sp-server-keys/SKILL.md | 58 ++ .../skills/sp-service-discovery/SKILL.md | 61 ++ .../skills/sp-sitemap/SKILL.md | 163 ++++ .../skills/sp-slack-client/SKILL.md | 125 +++ .../library-navigator/skills/sp-slsa/SKILL.md | 87 ++ .../skills/sp-sms-providers/SKILL.md | 179 ++++ .../library-navigator/skills/sp-sms/SKILL.md | 129 +++ .../skills/sp-solar-system/SKILL.md | 98 ++ .../library-navigator/skills/sp-srp/SKILL.md | 85 ++ .../skills/sp-stars/SKILL.md | 118 +++ .../sp-storage-browser-indexeddb/SKILL.md | 75 ++ .../sp-storage-browser-localstorage/SKILL.md | 78 ++ .../skills/sp-storage-browser-opfs/SKILL.md | 75 ++ .../skills/sp-storage-cdn-bunnycdn/SKILL.md | 91 ++ .../skills/sp-storage-cdn-rackspace/SKILL.md | 80 ++ .../skills/sp-storage-cdn/SKILL.md | 68 ++ .../skills/sp-storage-file/SKILL.md | 80 ++ .../skills/sp-storage-http/SKILL.md | 90 ++ .../skills/sp-storage-plugin-cache/SKILL.md | 61 ++ .../skills/sp-storage-s3/SKILL.md | 59 ++ .../sp-storage-uri-plugin-bundle/SKILL.md | 76 ++ .../sp-storage-uri-plugin-fallback/SKILL.md | 85 ++ .../skills/sp-storage-uri/SKILL.md | 73 ++ .../skills/sp-storage/SKILL.md | 99 ++ .../skills/sp-streams-chunk-queue/SKILL.md | 118 +++ .../skills/sp-streams-metadata/SKILL.md | 92 ++ .../skills/sp-streams/SKILL.md | 164 ++++ .../skills/sp-suppression/SKILL.md | 124 +++ .../skills/sp-surrealdb/SKILL.md | 94 ++ .../skills/sp-telegram-client/SKILL.md | 132 +++ .../skills/sp-templates/SKILL.md | 94 ++ .../skills/sp-test-vite/SKILL.md | 130 +++ .../skills/sp-testing-dom/SKILL.md | 54 ++ .../skills/sp-testing-e2e/SKILL.md | 60 ++ .../sp-testing-integration-garage-s3/SKILL.md | 50 + .../sp-testing-integration-mailpit/SKILL.md | 49 + .../SKILL.md | 61 ++ .../sp-testing-integration-postgres/SKILL.md | 49 + .../sp-testing-integration-redis/SKILL.md | 48 + .../sp-testing-integration-step-ca/SKILL.md | 59 ++ .../sp-testing-integration-surrealdb/SKILL.md | 51 + .../sp-testing-integration-typesense/SKILL.md | 50 + .../skills/sp-testing-integration/SKILL.md | 58 ++ .../skills/sp-testing/SKILL.md | 95 ++ .../skills/sp-third-party-elevenlabs/SKILL.md | 50 + .../skills/sp-tides/SKILL.md | 122 +++ .../skills/sp-timing/SKILL.md | 256 +++++ .../skills/sp-tpm-struct/SKILL.md | 80 ++ .../skills/sp-types/SKILL.md | 228 +++++ .../skills/sp-typescript-config/SKILL.md | 114 +++ .../library-navigator/skills/sp-undo/SKILL.md | 221 +++++ .../skills/sp-universe/SKILL.md | 127 +++ .../skills/sp-utils/SKILL.md | 210 +++++ .../skills/sp-validation/SKILL.md | 211 +++++ .../skills/sp-vault-sync/SKILL.md | 90 ++ .../skills/sp-vault/SKILL.md | 94 ++ .../skills/sp-video-thumbnails/SKILL.md | 74 ++ .../skills/sp-video/SKILL.md | 95 ++ .../skills/sp-voice-elevenlabs/SKILL.md | 53 ++ .../skills/sp-voice/SKILL.md | 53 ++ .../skills/sp-wasm-compiler-javy/SKILL.md | 58 ++ .../skills/sp-web-workers/SKILL.md | 147 +++ .../skills/sp-webauthn/SKILL.md | 135 +++ .../skills/sp-webhook-client/SKILL.md | 94 ++ .../skills/sp-websocket-gateway/SKILL.md | 103 ++ .../skills/sp-workflow/SKILL.md | 189 ++++ .../library-navigator/skills/sp-x509/SKILL.md | 101 ++ 6368 files changed, 527176 insertions(+) create mode 100644 .claude-plugin/marketplace.json create mode 100644 GUIDELINES.md create mode 100644 SKILL.md create mode 100644 docs/README.md create mode 100644 docs/_intro.md create mode 100644 docs/api-stack/README.md create mode 100644 docs/api-stack/_intro.md create mode 100644 docs/api-stack/api/README.md create mode 100644 docs/api-stack/api/_intro.md create mode 100644 docs/api-stack/api/api-2pc/README.md create mode 100644 docs/api-stack/api/api-2pc/src/coordinator/coordinator.md create mode 100644 docs/api-stack/api/api-2pc/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-2pc/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-2pc/src/limits/outstanding-cap.md create mode 100644 docs/api-stack/api/api-2pc/src/limits/timeout-ceiling.md create mode 100644 docs/api-stack/api/api-2pc/src/options/options.md create mode 100644 docs/api-stack/api/api-2pc/src/persistence/persistence.md create mode 100644 docs/api-stack/api/api-2pc/src/phases/commit.md create mode 100644 docs/api-stack/api/api-2pc/src/phases/gid.md create mode 100644 docs/api-stack/api/api-2pc/src/phases/prepare.md create mode 100644 docs/api-stack/api/api-2pc/src/phases/rollback.md create mode 100644 docs/api-stack/api/api-2pc/src/recovery/recovery.md create mode 100644 docs/api-stack/api/api-2pc/src/registry/participant-registry.md create mode 100644 docs/api-stack/api/api-2pc/src/testing/conformance.md create mode 100644 docs/api-stack/api/api-2pc/src/types/types.types.md create mode 100644 docs/api-stack/api/api-audit-file/README.md create mode 100644 docs/api-stack/api/api-audit-file/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-audit-file/src/fs-helpers/fs-helpers.md create mode 100644 docs/api-stack/api/api-audit-file/src/hmac/hmac.md create mode 100644 docs/api-stack/api/api-audit-file/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-audit-file/src/retention/retention.md create mode 100644 docs/api-stack/api/api-audit-file/src/rotation/rotation.md create mode 100644 docs/api-stack/api/api-audit-file/src/schema/schema.md create mode 100644 docs/api-stack/api/api-audit-file/src/sink/sink.md create mode 100644 docs/api-stack/api/api-audit-stdout/README.md create mode 100644 docs/api-stack/api/api-audit-stdout/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-audit-stdout/src/hmac/hmac.md create mode 100644 docs/api-stack/api/api-audit-stdout/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-audit-stdout/src/options/options.md create mode 100644 docs/api-stack/api/api-audit-stdout/src/schema/schema.md create mode 100644 docs/api-stack/api/api-audit-stdout/src/sink/sink.md create mode 100644 docs/api-stack/api/api-auth-anonymous/README.md create mode 100644 docs/api-stack/api/api-auth-anonymous/src/adapter/adapter.md create mode 100644 docs/api-stack/api/api-auth-anonymous/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-auth-anonymous/src/resolver/resolver.md create mode 100644 docs/api-stack/api/api-auth-bearer-static/README.md create mode 100644 docs/api-stack/api/api-auth-bearer-static/src/constant-time/token-match.md create mode 100644 docs/api-stack/api/api-auth-bearer-static/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-auth-bearer-static/src/factory/create-bearer-static-resolver.md create mode 100644 docs/api-stack/api/api-auth-bearer-static/src/mtls/mtls-gate.md create mode 100644 docs/api-stack/api/api-auth-bearer-static/src/options/bearer-static-resolver-options.md create mode 100644 docs/api-stack/api/api-auth-bearer-static/src/proxy/create-bearer-static-resolver-worker-proxy.md create mode 100644 docs/api-stack/api/api-auth-bearer-static/src/security-scheme/security-scheme-contribution.md create mode 100644 docs/api-stack/api/api-auth-bearer-static/src/telemetry/instruments.md create mode 100644 docs/api-stack/api/api-auth-better-auth/README.md create mode 100644 docs/api-stack/api/api-auth-better-auth/src/db/database.md create mode 100644 docs/api-stack/api/api-auth-better-auth/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-auth-better-auth/src/independence/session-without-provider.md create mode 100644 docs/api-stack/api/api-auth-better-auth/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-auth-better-auth/src/oauth/default-factory.md create mode 100644 docs/api-stack/api/api-auth-better-auth/src/oauth/github.md create mode 100644 docs/api-stack/api/api-auth-better-auth/src/options/options.md create mode 100644 docs/api-stack/api/api-auth-better-auth/src/principal/map-user-to-principal.md create mode 100644 docs/api-stack/api/api-auth-better-auth/src/provider/create-provider.md create mode 100644 docs/api-stack/api/api-auth-better-auth/src/provider/route-translation.md create mode 100644 docs/api-stack/api/api-auth-better-auth/src/route-prefix/route-prefix.md create mode 100644 docs/api-stack/api/api-auth-better-auth/src/session/create-session.md create mode 100644 docs/api-stack/api/api-auth-better-auth/src/testing/testing.md create mode 100644 docs/api-stack/api/api-auth-jwt/README.md create mode 100644 docs/api-stack/api/api-auth-jwt/src/claims-mapper/claims-mapper.md create mode 100644 docs/api-stack/api/api-auth-jwt/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-auth-jwt/src/jwks-cache/jwks-cache.md create mode 100644 docs/api-stack/api/api-auth-jwt/src/options/options.md create mode 100644 docs/api-stack/api/api-auth-jwt/src/resolver/resolver.md create mode 100644 docs/api-stack/api/api-auth-jwt/src/security-scheme/security-scheme.md create mode 100644 docs/api-stack/api/api-auth-provider/README.md create mode 100644 docs/api-stack/api/api-auth-provider/src/capability-id/capability-id.md create mode 100644 docs/api-stack/api/api-auth-provider/src/collision-detector/collision-detector.md create mode 100644 docs/api-stack/api/api-auth-provider/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-auth-provider/src/path-ownership/path-ownership.md create mode 100644 docs/api-stack/api/api-auth-provider/src/provider/provider.md create mode 100644 docs/api-stack/api/api-auth-provider/src/route-surface/route-surface.md create mode 100644 docs/api-stack/api/api-auth-provider/src/testing/conformance.md create mode 100644 docs/api-stack/api/api-auth-rolled/README.md create mode 100644 docs/api-stack/api/api-auth-rolled/src/composition/composition.md create mode 100644 docs/api-stack/api/api-auth-rolled/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-auth-rolled/src/options/options.md create mode 100644 docs/api-stack/api/api-auth-rolled/src/principal-projection/principal-projection.md create mode 100644 docs/api-stack/api/api-auth-rolled/src/security-schemes/security-schemes.md create mode 100644 docs/api-stack/api/api-auth-rolled/src/session/session.md create mode 100644 docs/api-stack/api/api-auth-rolled/src/token-rotator/token-rotator.md create mode 100644 docs/api-stack/api/api-auth-static-principal/README.md create mode 100644 docs/api-stack/api/api-auth-static-principal/src/adapter/adapter.md create mode 100644 docs/api-stack/api/api-auth-static-principal/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-auth-static-principal/src/factory/create-static-principal-resolver.md create mode 100644 docs/api-stack/api/api-auth-static-principal/src/options/options.md create mode 100644 docs/api-stack/api/api-auth-static-principal/src/security-scheme/security-scheme.md create mode 100644 docs/api-stack/api/api-auth/README.md create mode 100644 docs/api-stack/api/api-auth/src/capability-id/capability-id.md create mode 100644 docs/api-stack/api/api-auth/src/chain/chain.md create mode 100644 docs/api-stack/api/api-auth/src/csrf-policy/csrf-policy.md create mode 100644 docs/api-stack/api/api-auth/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-auth/src/resolver/resolver.md create mode 100644 docs/api-stack/api/api-auth/src/security-scheme/security-scheme.md create mode 100644 docs/api-stack/api/api-auth/src/session-adapter/session-adapter.md create mode 100644 docs/api-stack/api/api-auth/src/testing/conformance.md create mode 100644 docs/api-stack/api/api-db-adapter/README.md create mode 100644 docs/api-stack/api/api-db-adapter/src/engine-registry/engine-registry.md create mode 100644 docs/api-stack/api/api-db-adapter/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-db-adapter/src/factory/create-db-adapter.md create mode 100644 docs/api-stack/api/api-db-adapter/src/migrations/run-migrations.md create mode 100644 docs/api-stack/api/api-db-adapter/src/options/db-adapter-options.md create mode 100644 docs/api-stack/api/api-db-adapter/src/proxy/create-db-adapter-worker-proxy.md create mode 100644 docs/api-stack/api/api-db-adapter/src/tenant-scoped/create-tenant-scoped-wrapper.md create mode 100644 docs/api-stack/api/api-db-adapter/src/unsafe/unsafe-query-gate.md create mode 100644 docs/api-stack/api/api-db-sqlite-memory/README.md create mode 100644 docs/api-stack/api/api-db-sqlite-memory/src/engine/register-engine.md create mode 100644 docs/api-stack/api/api-db-sqlite-memory/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-db-sqlite-memory/src/factory/create-sqlite-memory-adapter.md create mode 100644 docs/api-stack/api/api-db-sqlite-memory/src/factory/create-sqlite-memory-db.md create mode 100644 docs/api-stack/api/api-db-sqlite-memory/src/migrations/migrations.md create mode 100644 docs/api-stack/api/api-db-sqlite-memory/src/options/sqlite-memory-db-options.md create mode 100644 docs/api-stack/api/api-db-sqlite-memory/src/tenant-scoping/tenant-scoping.md create mode 100644 docs/api-stack/api/api-db-sqlite-memory/src/testing/harness.md create mode 100644 docs/api-stack/api/api-db-worker-proxy/README.md create mode 100644 docs/api-stack/api/api-db-worker-proxy/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-db-worker-proxy/src/main-side/main-side.md create mode 100644 docs/api-stack/api/api-db-worker-proxy/src/tenant-scoped/tenant-scoped.md create mode 100644 docs/api-stack/api/api-db-worker-proxy/src/testing/testing.md create mode 100644 docs/api-stack/api/api-db-worker-proxy/src/worker-side/worker-side.md create mode 100644 docs/api-stack/api/api-events-in-memory/README.md create mode 100644 docs/api-stack/api/api-events-in-memory/src/bus/bus.md create mode 100644 docs/api-stack/api/api-events-in-memory/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-events-in-memory/src/history/history.md create mode 100644 docs/api-stack/api/api-events-in-memory/src/options/options.md create mode 100644 docs/api-stack/api/api-events-in-memory/src/testing/testing.md create mode 100644 docs/api-stack/api/api-events-worker-proxy/README.md create mode 100644 docs/api-stack/api/api-events-worker-proxy/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-events-worker-proxy/src/main-side/main-side.md create mode 100644 docs/api-stack/api/api-events-worker-proxy/src/payload-codec/payload-codec.md create mode 100644 docs/api-stack/api/api-events-worker-proxy/src/testing/testing.md create mode 100644 docs/api-stack/api/api-events-worker-proxy/src/worker-side/worker-side.md create mode 100644 docs/api-stack/api/api-graphql-apollo/README.md create mode 100644 docs/api-stack/api/api-graphql-apollo/src/endpoints/http.md create mode 100644 docs/api-stack/api/api-graphql-apollo/src/endpoints/ui-proxy.md create mode 100644 docs/api-stack/api/api-graphql-apollo/src/engine/apollo-engine.md create mode 100644 docs/api-stack/api/api-graphql-apollo/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-graphql-apollo/src/federation/federation.md create mode 100644 docs/api-stack/api/api-graphql-apollo/src/guards/depth-and-complexity.md create mode 100644 docs/api-stack/api/api-graphql-apollo/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-graphql-apollo/src/loaders/loaders.md create mode 100644 docs/api-stack/api/api-graphql-apollo/src/options/options.md create mode 100644 docs/api-stack/api/api-graphql-apollo/src/persisted-queries/persisted-queries.md create mode 100644 docs/api-stack/api/api-graphql-apollo/src/studio-reporting/studio-reporting.md create mode 100644 docs/api-stack/api/api-graphql-apollo/src/subscriptions/subscriptions.md create mode 100644 docs/api-stack/api/api-graphql-apollo/src/testing/conformance.md create mode 100644 docs/api-stack/api/api-graphql-ui-altair/README.md create mode 100644 docs/api-stack/api/api-graphql-ui-altair/src/assets/assets.md create mode 100644 docs/api-stack/api/api-graphql-ui-altair/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-graphql-ui-altair/src/factory/create-altair-ui.md create mode 100644 docs/api-stack/api/api-graphql-ui-altair/src/headers/csp.md create mode 100644 docs/api-stack/api/api-graphql-ui-altair/src/html/render-shell.md create mode 100644 docs/api-stack/api/api-graphql-ui-altair/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-graphql-ui-altair/src/options/options.md create mode 100644 docs/api-stack/api/api-graphql-ui-graphiql/README.md create mode 100644 docs/api-stack/api/api-graphql-ui-graphiql/src/assets/assets.md create mode 100644 docs/api-stack/api/api-graphql-ui-graphiql/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-graphql-ui-graphiql/src/factory/create-graphiql-ui.md create mode 100644 docs/api-stack/api/api-graphql-ui-graphiql/src/headers/csp.md create mode 100644 docs/api-stack/api/api-graphql-ui-graphiql/src/html/render-shell.md create mode 100644 docs/api-stack/api/api-graphql-ui-graphiql/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-graphql-ui-graphiql/src/options/options.md create mode 100644 docs/api-stack/api/api-graphql-yoga/README.md create mode 100644 docs/api-stack/api/api-graphql-yoga/src/engine/execute-helpers.md create mode 100644 docs/api-stack/api/api-graphql-yoga/src/engine/yoga-engine.md create mode 100644 docs/api-stack/api/api-graphql-yoga/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-graphql-yoga/src/federation/federation.md create mode 100644 docs/api-stack/api/api-graphql-yoga/src/guards/depth-and-complexity.md create mode 100644 docs/api-stack/api/api-graphql-yoga/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-graphql-yoga/src/loaders/loaders.md create mode 100644 docs/api-stack/api/api-graphql-yoga/src/options/options.md create mode 100644 docs/api-stack/api/api-graphql-yoga/src/subscriptions/subscriptions.md create mode 100644 docs/api-stack/api/api-graphql-yoga/src/testing/testing.md create mode 100644 docs/api-stack/api/api-graphql/README.md create mode 100644 docs/api-stack/api/api-graphql/src/directives/directives.md create mode 100644 docs/api-stack/api/api-graphql/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-graphql/src/federation/merge-sdl.md create mode 100644 docs/api-stack/api/api-graphql/src/federation/namespace.md create mode 100644 docs/api-stack/api/api-graphql/src/federation/parse-sdl.md create mode 100644 docs/api-stack/api/api-graphql/src/registry/registry.md create mode 100644 docs/api-stack/api/api-graphql/src/subscription/subscription.md create mode 100644 docs/api-stack/api/api-graphql/src/testing/conformance.md create mode 100644 docs/api-stack/api/api-graphql/src/validators/validators.md create mode 100644 docs/api-stack/api/api-host/README.md create mode 100644 docs/api-stack/api/api-host/src/admin-api/admin-api.md create mode 100644 docs/api-stack/api/api-host/src/admin-api/audit-sink.md create mode 100644 docs/api-stack/api/api-host/src/admin-api/idempotency-store.md create mode 100644 docs/api-stack/api/api-host/src/admin-api/rate-limiter.md create mode 100644 docs/api-stack/api/api-host/src/capability-registry/capability-registry.md create mode 100644 docs/api-stack/api/api-host/src/define-plugin/define-plugin.md create mode 100644 docs/api-stack/api/api-host/src/empty-secrets/empty-secrets.md create mode 100644 docs/api-stack/api/api-host/src/error-boundary/error-boundary.md create mode 100644 docs/api-stack/api/api-host/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-host/src/host/host.md create mode 100644 docs/api-stack/api/api-host/src/hot-reload/file-watcher.md create mode 100644 docs/api-stack/api/api-host/src/hot-reload/hot-reload.md create mode 100644 docs/api-stack/api/api-host/src/lifecycle/lifecycle.md create mode 100644 docs/api-stack/api/api-host/src/otel/otel.md create mode 100644 docs/api-stack/api/api-host/src/pipeline-events-bus/in-memory-bus.md create mode 100644 docs/api-stack/api/api-host/src/pipeline-events-bus/noop-bus.md create mode 100644 docs/api-stack/api/api-host/src/pipeline-events-bus/pipeline-events-constants.md create mode 100644 docs/api-stack/api/api-host/src/plugin-ledger/migrations.md create mode 100644 docs/api-stack/api/api-host/src/plugin-ledger/plugin-ledger.md create mode 100644 docs/api-stack/api/api-host/src/request-pipeline/request-pipeline-driver.md create mode 100644 docs/api-stack/api/api-host/src/request-pipeline/request-pipeline-emitters.md create mode 100644 docs/api-stack/api/api-host/src/request-pipeline/request-pipeline-helpers.md create mode 100644 docs/api-stack/api/api-host/src/request-pipeline/request-pipeline-outcomes.md create mode 100644 docs/api-stack/api/api-host/src/request-pipeline/request-pipeline-stage-emit.md create mode 100644 docs/api-stack/api/api-host/src/request-pipeline/request-pipeline-stage-skip.md create mode 100644 docs/api-stack/api/api-host/src/request-pipeline/request-pipeline-steps.md create mode 100644 docs/api-stack/api/api-host/src/request-pipeline/request-pipeline-validation.md create mode 100644 docs/api-stack/api/api-host/src/request-pipeline/request-pipeline.md create mode 100644 docs/api-stack/api/api-host/src/reserved-prefix/reserved-prefix.md create mode 100644 docs/api-stack/api/api-host/src/testing/create-test-host/create-test-host.md create mode 100644 docs/api-stack/api/api-host/src/testing/pipeline-events-conformance/pipeline-events-conformance.md create mode 100644 docs/api-stack/api/api-host/src/testing/testing.md create mode 100644 docs/api-stack/api/api-jobs-worker-proxy/README.md create mode 100644 docs/api-stack/api/api-jobs-worker-proxy/src/client/client.md create mode 100644 docs/api-stack/api/api-jobs-worker-proxy/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-jobs-worker-proxy/src/handler-bridge/handler-bridge.md create mode 100644 docs/api-stack/api/api-jobs-worker-proxy/src/server/server.md create mode 100644 docs/api-stack/api/api-jobs-worker-proxy/src/testing/testing.md create mode 100644 docs/api-stack/api/api-lifecycle/README.md create mode 100644 docs/api-stack/api/api-lifecycle/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-lifecycle/src/fsm-factory/fsm-factory.md create mode 100644 docs/api-stack/api/api-lifecycle/src/mutex-contract/mutex-contract.md create mode 100644 docs/api-stack/api/api-lifecycle/src/reinstall-criteria/reinstall-criteria.md create mode 100644 docs/api-stack/api/api-lifecycle/src/retry-policies/retry-policies.md create mode 100644 docs/api-stack/api/api-lifecycle/src/side-effects/side-effects.md create mode 100644 docs/api-stack/api/api-lifecycle/src/states/states.md create mode 100644 docs/api-stack/api/api-lifecycle/src/testing/conformance.md create mode 100644 docs/api-stack/api/api-lifecycle/src/transitions/transitions.md create mode 100644 docs/api-stack/api/api-loader/README.md create mode 100644 docs/api-stack/api/api-loader/src/cache-bust/cache-bust.md create mode 100644 docs/api-stack/api/api-loader/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-loader/src/journal-entry/journal-entry.md create mode 100644 docs/api-stack/api/api-loader/src/native-binding-detector/native-binding-detector.md create mode 100644 docs/api-stack/api/api-loader/src/resolver/resolver.md create mode 100644 docs/api-stack/api/api-loader/src/rollback-journal/rollback-journal.md create mode 100644 docs/api-stack/api/api-loader/src/testing/loader-conformance.md create mode 100644 docs/api-stack/api/api-logger-worker-proxy/README.md create mode 100644 docs/api-stack/api/api-logger-worker-proxy/src/batching/batching.md create mode 100644 docs/api-stack/api/api-logger-worker-proxy/src/client/client.md create mode 100644 docs/api-stack/api/api-logger-worker-proxy/src/control-channel/control-channel.md create mode 100644 docs/api-stack/api/api-logger-worker-proxy/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-logger-worker-proxy/src/protocol/protocol.md create mode 100644 docs/api-stack/api/api-logger-worker-proxy/src/redaction-passthrough/redaction-passthrough.md create mode 100644 docs/api-stack/api/api-logger-worker-proxy/src/server/server.md create mode 100644 docs/api-stack/api/api-logger-worker-proxy/src/testing/conformance.md create mode 100644 docs/api-stack/api/api-logger-worker-proxy/src/testing/testing.md create mode 100644 docs/api-stack/api/api-manifest/README.md create mode 100644 docs/api-stack/api/api-manifest/src/capability-resolver/capability-resolver.md create mode 100644 docs/api-stack/api/api-manifest/src/dep-graph/dep-graph.md create mode 100644 docs/api-stack/api/api-manifest/src/dep-graph/semver.md create mode 100644 docs/api-stack/api/api-manifest/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-manifest/src/hash/canonical-json.md create mode 100644 docs/api-stack/api/api-manifest/src/hash/hash.md create mode 100644 docs/api-stack/api/api-manifest/src/parse/parse.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/compat.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/config.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/database.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/depends-on.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/errors.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/events.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/graphql.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/identity.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/isolation.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/jobs.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/openapi.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/permissions.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/plugin-manifest.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/routes.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/sagas.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/scopes.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/secrets.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/sse.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/telemetry.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/two-phase-commit.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/uninstall.md create mode 100644 docs/api-stack/api/api-manifest/src/schema/websockets.md create mode 100644 docs/api-stack/api/api-manifest/src/testing/conformance.md create mode 100644 docs/api-stack/api/api-manifest/src/validators/validate-error-status-map-shape.md create mode 100644 docs/api-stack/api/api-manifest/src/validators/validate-openapi-requires-graphql-or-routes.md create mode 100644 docs/api-stack/api/api-manifest/src/validators/validate-permissions-when-sandboxed.md create mode 100644 docs/api-stack/api/api-manifest/src/validators/validate-saga-ownership.md create mode 100644 docs/api-stack/api/api-migrations/README.md create mode 100644 docs/api-stack/api/api-migrations/src/adapters/postgres/postgres.md create mode 100644 docs/api-stack/api/api-migrations/src/adapters/sqlite/sqlite.md create mode 100644 docs/api-stack/api/api-migrations/src/adapters/surrealql/surrealql.md create mode 100644 docs/api-stack/api/api-migrations/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-migrations/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-migrations/src/runner/runner.md create mode 100644 docs/api-stack/api/api-migrations/src/types/migration.md create mode 100644 docs/api-stack/api/api-migrations/tests/integration/README.md create mode 100644 docs/api-stack/api/api-openapi-ui-redoc/README.md create mode 100644 docs/api-stack/api/api-openapi-ui-redoc/src/assets/assets.md create mode 100644 docs/api-stack/api/api-openapi-ui-redoc/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-openapi-ui-redoc/src/handler/handler.md create mode 100644 docs/api-stack/api/api-openapi-ui-redoc/src/html/render-shell.md create mode 100644 docs/api-stack/api/api-openapi-ui-redoc/src/options/options.md create mode 100644 docs/api-stack/api/api-openapi-ui-redoc/src/per-plugin/per-plugin.md create mode 100644 docs/api-stack/api/api-openapi-ui-scalar/README.md create mode 100644 docs/api-stack/api/api-openapi-ui-scalar/src/assets/assets.md create mode 100644 docs/api-stack/api/api-openapi-ui-scalar/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-openapi-ui-scalar/src/handler/handler.md create mode 100644 docs/api-stack/api/api-openapi-ui-scalar/src/headers/csp.md create mode 100644 docs/api-stack/api/api-openapi-ui-scalar/src/html/render-shell.md create mode 100644 docs/api-stack/api/api-openapi-ui-scalar/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-openapi-ui-scalar/src/options/options.md create mode 100644 docs/api-stack/api/api-openapi-ui-scalar/src/per-plugin/per-plugin.md create mode 100644 docs/api-stack/api/api-openapi-ui-swagger/README.md create mode 100644 docs/api-stack/api/api-openapi-ui-swagger/src/assets/assets.md create mode 100644 docs/api-stack/api/api-openapi-ui-swagger/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-openapi-ui-swagger/src/handler/handler.md create mode 100644 docs/api-stack/api/api-openapi-ui-swagger/src/html/render-shell.md create mode 100644 docs/api-stack/api/api-openapi-ui-swagger/src/options/options.md create mode 100644 docs/api-stack/api/api-openapi-ui-swagger/src/per-plugin/per-plugin.md create mode 100644 docs/api-stack/api/api-openapi/README.md create mode 100644 docs/api-stack/api/api-openapi/src/emitter/emitter.md create mode 100644 docs/api-stack/api/api-openapi/src/endpoints/endpoints.md create mode 100644 docs/api-stack/api/api-openapi/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-openapi/src/merger/merger.md create mode 100644 docs/api-stack/api/api-openapi/src/namespacing/namespacing.md create mode 100644 docs/api-stack/api/api-openapi/src/plugin-integration/plugin-integration.md create mode 100644 docs/api-stack/api/api-openapi/src/registry/registry.md create mode 100644 docs/api-stack/api/api-openapi/src/route-factory/route-factory.md create mode 100644 docs/api-stack/api/api-openapi/src/schema-registry/common-schemas.md create mode 100644 docs/api-stack/api/api-openapi/src/schema-registry/schema-registry.md create mode 100644 docs/api-stack/api/api-openapi/src/strictness/strictness.md create mode 100644 docs/api-stack/api/api-openapi/src/types/openapi.md create mode 100644 docs/api-stack/api/api-plugin-audit/README.md create mode 100644 docs/api-stack/api/api-plugin-audit/src/context/audit-context.md create mode 100644 docs/api-stack/api/api-plugin-audit/src/context/context-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-audit/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-audit/src/middleware/audit-middleware.md create mode 100644 docs/api-stack/api/api-plugin-audit/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-audit/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-audit/src/redact/redact.md create mode 100644 docs/api-stack/api/api-plugin-audit/src/schemas/options.md create mode 100644 docs/api-stack/api/api-plugin-audit/src/services/audit-service.md create mode 100644 docs/api-stack/api/api-plugin-audit/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-audit/src/types/types.md create mode 100644 docs/api-stack/api/api-plugin-auth/README.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/middleware/context-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/middleware/require-auth.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/middleware/require-email-verified.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/middleware/require-role.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/middleware/session.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/principal/principal.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/routes/build-routes.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/schema/schema.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/schemas/options.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/schemas/principal.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/schemas/routes/forgot-password.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/schemas/routes/oauth.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/schemas/routes/reset-password.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/schemas/routes/session.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/schemas/routes/sign-in.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/schemas/routes/sign-out.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/schemas/routes/sign-up.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/schemas/routes/verify-email.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/services/auth-service.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-auth/src/types/types.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/README.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/context/context.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/repositories/campaign/campaign.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/repositories/suppression/suppression-internals.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/repositories/suppression/suppression-memory.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/repositories/suppression/suppression.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/routes/campaigns/action-routes.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/routes/campaigns/build-routes.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/routes/campaigns/crud-routes.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/routes/campaigns/schemas.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/routes/shared/require-tenant.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/routes/shared/strip-undefined.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/routes/suppression/build-routes.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/routes/suppression/routes.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/routes/suppression/schemas.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/routes/webhooks/build-routes.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/routes/webhooks/routes.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/routes/webhooks/schemas.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/schemas/options.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-campaigns/src/types/types.md create mode 100644 docs/api-stack/api/api-plugin-cms/README.md create mode 100644 docs/api-stack/api/api-plugin-cms/src/engine/cms-engine.md create mode 100644 docs/api-stack/api/api-plugin-cms/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-cms/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-cms/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-cms/src/routes/problem-json.md create mode 100644 docs/api-stack/api/api-plugin-cms/src/schemas/options.md create mode 100644 docs/api-stack/api/api-plugin-cms/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-database/README.md create mode 100644 docs/api-stack/api/api-plugin-database/src/config/config-schema.md create mode 100644 docs/api-stack/api/api-plugin-database/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-database/src/migrations/lock.md create mode 100644 docs/api-stack/api/api-plugin-database/src/migrations/runner.md create mode 100644 docs/api-stack/api/api-plugin-database/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-database/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-database/src/pool/extended-adapter.md create mode 100644 docs/api-stack/api/api-plugin-database/src/pool/pool.md create mode 100644 docs/api-stack/api/api-plugin-database/src/retry/retry.md create mode 100644 docs/api-stack/api/api-plugin-database/src/routes/problem-json.md create mode 100644 docs/api-stack/api/api-plugin-database/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-database/src/tenancy/tenancy.md create mode 100644 docs/api-stack/api/api-plugin-database/src/types/types.md create mode 100644 docs/api-stack/api/api-plugin-event-bus/README.md create mode 100644 docs/api-stack/api/api-plugin-event-bus/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-event-bus/src/middleware/context-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-event-bus/src/middleware/request-bus.md create mode 100644 docs/api-stack/api/api-plugin-event-bus/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-event-bus/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-event-bus/src/routes/build-routes.md create mode 100644 docs/api-stack/api/api-plugin-event-bus/src/schemas/options.md create mode 100644 docs/api-stack/api/api-plugin-event-bus/src/schemas/routes.md create mode 100644 docs/api-stack/api/api-plugin-event-bus/src/services/backpressure.md create mode 100644 docs/api-stack/api/api-plugin-event-bus/src/services/event-bus-service.md create mode 100644 docs/api-stack/api/api-plugin-event-bus/src/services/helpers.md create mode 100644 docs/api-stack/api/api-plugin-event-bus/src/services/idempotency-cache.md create mode 100644 docs/api-stack/api/api-plugin-event-bus/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-event-bus/src/topic/topic.md create mode 100644 docs/api-stack/api/api-plugin-event-bus/src/types/types.md create mode 100644 docs/api-stack/api/api-plugin-events/README.md create mode 100644 docs/api-stack/api/api-plugin-events/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-events/src/ics/ics-builder/ics-builder.md create mode 100644 docs/api-stack/api/api-plugin-events/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-events/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-events/src/repositories/event-repository/event-repository.md create mode 100644 docs/api-stack/api/api-plugin-events/src/repositories/rsvp-repository/rsvp-repository.md create mode 100644 docs/api-stack/api/api-plugin-events/src/routes/events-routes/events-routes.md create mode 100644 docs/api-stack/api/api-plugin-events/src/routes/ics-export/ics-export.md create mode 100644 docs/api-stack/api/api-plugin-events/src/schemas/event-schemas.md create mode 100644 docs/api-stack/api/api-plugin-events/src/schemas/options.md create mode 100644 docs/api-stack/api/api-plugin-events/src/schemas/rsvp-schemas.md create mode 100644 docs/api-stack/api/api-plugin-events/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-events/src/types/types.md create mode 100644 docs/api-stack/api/api-plugin-example/README.md create mode 100644 docs/api-stack/api/api-plugin-example/src/domain/in-memory-store.md create mode 100644 docs/api-stack/api/api-plugin-example/src/domain/invoice-rules.md create mode 100644 docs/api-stack/api/api-plugin-example/src/domain/invoice.types.md create mode 100644 docs/api-stack/api/api-plugin-example/src/domain/validators/assert-shape.md create mode 100644 docs/api-stack/api/api-plugin-example/src/domain/validators/schema.types.md create mode 100644 docs/api-stack/api/api-plugin-example/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-example/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-plugin-example/src/schemas/schemas.md create mode 100644 docs/api-stack/api/api-plugin-example/src/trusted/events/events.md create mode 100644 docs/api-stack/api/api-plugin-example/src/trusted/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-example/src/trusted/routes/routes.md create mode 100644 docs/api-stack/api/api-plugin-example/src/wasm/dispose.md create mode 100644 docs/api-stack/api/api-plugin-example/src/wasm/handle-request.md create mode 100644 docs/api-stack/api/api-plugin-example/src/wasm/routes.md create mode 100644 docs/api-stack/api/api-plugin-example/src/wasm/start.md create mode 100644 docs/api-stack/api/api-plugin-example/src/wasm/wasm-state.md create mode 100644 docs/api-stack/api/api-plugin-export/README.md create mode 100644 docs/api-stack/api/api-plugin-export/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-export/src/exporters/csv/csv.md create mode 100644 docs/api-stack/api/api-plugin-export/src/exporters/json/json.md create mode 100644 docs/api-stack/api/api-plugin-export/src/exporters/xlsx/xlsx.md create mode 100644 docs/api-stack/api/api-plugin-export/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-export/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-export/src/routes/download/download.md create mode 100644 docs/api-stack/api/api-plugin-export/src/routes/exports/exports.md create mode 100644 docs/api-stack/api/api-plugin-export/src/routes/exports/post-handler.md create mode 100644 docs/api-stack/api/api-plugin-export/src/routes/problem-json/problem-json.md create mode 100644 docs/api-stack/api/api-plugin-export/src/services/export/export-service.md create mode 100644 docs/api-stack/api/api-plugin-export/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-export/src/store/memory/memory-store.md create mode 100644 docs/api-stack/api/api-plugin-export/src/store/surreal/surreal-store.md create mode 100644 docs/api-stack/api/api-plugin-export/src/store/types/types.md create mode 100644 docs/api-stack/api/api-plugin-export/src/types/types.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/README.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/assembler/assembler.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/routes/build-routes.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/routes/handlers.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/schemas/options.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/schemas/routes/initiate.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/schemas/routes/single-shot.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/schemas/routes/status.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/services/complete-chunked.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/services/file-upload-helpers.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/services/file-upload-service.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/services/single-shot.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/session-store/memory.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/storage/file-system.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/storage/memory.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/types/types.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/validators/mime.md create mode 100644 docs/api-stack/api/api-plugin-file-upload/src/validators/size.md create mode 100644 docs/api-stack/api/api-plugin-graphql/README.md create mode 100644 docs/api-stack/api/api-plugin-graphql/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-graphql/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-graphql/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-graphql/src/resolver/resolver.md create mode 100644 docs/api-stack/api/api-plugin-graphql/src/schema-builder/schema-builder.md create mode 100644 docs/api-stack/api/api-plugin-graphql/src/schemas/options.md create mode 100644 docs/api-stack/api/api-plugin-graphql/src/type-builder/type-builder.md create mode 100644 docs/api-stack/api/api-plugin-graphql/src/types/graphql.types.md create mode 100644 docs/api-stack/api/api-plugin-import/README.md create mode 100644 docs/api-stack/api/api-plugin-import/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-import/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-import/src/parsers/csv.md create mode 100644 docs/api-stack/api/api-plugin-import/src/parsers/json.md create mode 100644 docs/api-stack/api/api-plugin-import/src/parsers/xlsx.md create mode 100644 docs/api-stack/api/api-plugin-import/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-import/src/progress/tracker.md create mode 100644 docs/api-stack/api/api-plugin-import/src/routes/build-routes.md create mode 100644 docs/api-stack/api/api-plugin-import/src/routes/problem-json.md create mode 100644 docs/api-stack/api/api-plugin-import/src/routes/progress-sse/progress-sse.md create mode 100644 docs/api-stack/api/api-plugin-import/src/schemas/options.md create mode 100644 docs/api-stack/api/api-plugin-import/src/schemas/schemas.md create mode 100644 docs/api-stack/api/api-plugin-import/src/service/service.md create mode 100644 docs/api-stack/api/api-plugin-import/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-import/src/store/memory.md create mode 100644 docs/api-stack/api/api-plugin-import/src/store/surreal/surreal-import-store.md create mode 100644 docs/api-stack/api/api-plugin-import/src/transform/pipeline.md create mode 100644 docs/api-stack/api/api-plugin-import/src/types/types.md create mode 100644 docs/api-stack/api/api-plugin-notifications/README.md create mode 100644 docs/api-stack/api/api-plugin-notifications/src/channels/apn-channel/apn-channel.md create mode 100644 docs/api-stack/api/api-plugin-notifications/src/channels/email-channel/email-channel.md create mode 100644 docs/api-stack/api/api-plugin-notifications/src/dispatcher/idempotency-adapter/idempotency-adapter.md create mode 100644 docs/api-stack/api/api-plugin-notifications/src/dispatcher/notification-dispatcher/notification-dispatcher.md create mode 100644 docs/api-stack/api/api-plugin-notifications/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-notifications/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-notifications/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-notifications/src/repositories/device-token-repository/device-token-repository.md create mode 100644 docs/api-stack/api/api-plugin-notifications/src/repositories/notification-repository/notification-repository.md create mode 100644 docs/api-stack/api/api-plugin-notifications/src/routes/notifications-routes/notifications-routes.md create mode 100644 docs/api-stack/api/api-plugin-notifications/src/routes/push-routes/push-routes.md create mode 100644 docs/api-stack/api/api-plugin-notifications/src/schemas/dispatch-schemas.md create mode 100644 docs/api-stack/api/api-plugin-notifications/src/schemas/notification-schemas.md create mode 100644 docs/api-stack/api/api-plugin-notifications/src/schemas/options.md create mode 100644 docs/api-stack/api/api-plugin-notifications/src/schemas/push-schemas.md create mode 100644 docs/api-stack/api/api-plugin-notifications/src/services/apn-service/apn-service.md create mode 100644 docs/api-stack/api/api-plugin-notifications/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-notifications/src/transport/apn-transport/apn-transport.md create mode 100644 docs/api-stack/api/api-plugin-notifications/src/types/types.md create mode 100644 docs/api-stack/api/api-plugin-payment/README.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/middleware/context-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/middleware/idempotency-middleware.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/routes/build-routes.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/schemas/money.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/schemas/options.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/schemas/routes/capture-intent.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/schemas/routes/create-intent.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/schemas/routes/empty-body.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/schemas/routes/intent-id-param.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/schemas/routes/list-intents.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/schemas/routes/payment-intent.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/schemas/routes/refund.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/schemas/routes/webhook.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/services/payment-service.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/store/memory-store.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/store/payment-intent-store.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/types/types.md create mode 100644 docs/api-stack/api/api-plugin-payment/src/webhook/verify-webhook.md create mode 100644 docs/api-stack/api/api-plugin-rate-limit/README.md create mode 100644 docs/api-stack/api/api-plugin-rate-limit/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-rate-limit/src/headers/headers.md create mode 100644 docs/api-stack/api/api-plugin-rate-limit/src/middleware/context-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-rate-limit/src/middleware/rate-limit.md create mode 100644 docs/api-stack/api/api-plugin-rate-limit/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-rate-limit/src/path-matcher/path-matcher.md create mode 100644 docs/api-stack/api/api-plugin-rate-limit/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-rate-limit/src/schemas/options.md create mode 100644 docs/api-stack/api/api-plugin-rate-limit/src/services/rate-limit-service.md create mode 100644 docs/api-stack/api/api-plugin-rate-limit/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-rate-limit/src/types/types.md create mode 100644 docs/api-stack/api/api-plugin-search/README.md create mode 100644 docs/api-stack/api/api-plugin-search/src/analyzer/analyzer.md create mode 100644 docs/api-stack/api/api-plugin-search/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-search/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-search/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-search/src/routes/build-routes.md create mode 100644 docs/api-stack/api/api-plugin-search/src/schemas/options.md create mode 100644 docs/api-stack/api/api-plugin-search/src/schemas/schemas.md create mode 100644 docs/api-stack/api/api-plugin-search/src/service/service.md create mode 100644 docs/api-stack/api/api-plugin-search/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-search/src/types/types.md create mode 100644 docs/api-stack/api/api-plugin-site/README.md create mode 100644 docs/api-stack/api/api-plugin-site/docs/middleware-integration.md create mode 100644 docs/api-stack/api/api-plugin-site/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-site/src/integration/middleware-recommendations.md create mode 100644 docs/api-stack/api/api-plugin-site/src/middleware/domain-resolver.md create mode 100644 docs/api-stack/api/api-plugin-site/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-site/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-site/src/routes/private-routes.md create mode 100644 docs/api-stack/api/api-plugin-site/src/routes/public-routes.md create mode 100644 docs/api-stack/api/api-plugin-site/src/schemas/domain.md create mode 100644 docs/api-stack/api/api-plugin-site/src/schemas/options.md create mode 100644 docs/api-stack/api/api-plugin-site/src/schemas/push.md create mode 100644 docs/api-stack/api/api-plugin-site/src/schemas/site.md create mode 100644 docs/api-stack/api/api-plugin-site/src/service/db-port.md create mode 100644 docs/api-stack/api/api-plugin-site/src/service/domain-resolver.md create mode 100644 docs/api-stack/api/api-plugin-site/src/service/normalize-domain.md create mode 100644 docs/api-stack/api/api-plugin-site/src/service/site.md create mode 100644 docs/api-stack/api/api-plugin-site/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-site/src/types/types.md create mode 100644 docs/api-stack/api/api-plugin-sse/README.md create mode 100644 docs/api-stack/api/api-plugin-sse/src/buffer/ring-buffer.md create mode 100644 docs/api-stack/api/api-plugin-sse/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-sse/src/fanout/in-process.md create mode 100644 docs/api-stack/api/api-plugin-sse/src/formatter/format.md create mode 100644 docs/api-stack/api/api-plugin-sse/src/formatter/parse.md create mode 100644 docs/api-stack/api/api-plugin-sse/src/middleware/sse-handler.md create mode 100644 docs/api-stack/api/api-plugin-sse/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-sse/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-sse/src/registry/service-registry.md create mode 100644 docs/api-stack/api/api-plugin-sse/src/schemas/event.md create mode 100644 docs/api-stack/api/api-plugin-sse/src/schemas/options.md create mode 100644 docs/api-stack/api/api-plugin-sse/src/services/service.md create mode 100644 docs/api-stack/api/api-plugin-tenant/README.md create mode 100644 docs/api-stack/api/api-plugin-tenant/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-tenant/src/middleware/tenant.md create mode 100644 docs/api-stack/api/api-plugin-tenant/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-tenant/src/plugin/build-resolver.md create mode 100644 docs/api-stack/api/api-plugin-tenant/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-tenant/src/routes/routes.md create mode 100644 docs/api-stack/api/api-plugin-tenant/src/schemas/options.md create mode 100644 docs/api-stack/api/api-plugin-tenant/src/schemas/routes.md create mode 100644 docs/api-stack/api/api-plugin-tenant/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-tenant/src/services/tenant-service.md create mode 100644 docs/api-stack/api/api-plugin-tenant/src/store/memory.md create mode 100644 docs/api-stack/api/api-plugin-tenant/src/store/store.md create mode 100644 docs/api-stack/api/api-plugin-tenant/src/types/types.md create mode 100644 docs/api-stack/api/api-plugin-user/README.md create mode 100644 docs/api-stack/api/api-plugin-user/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-user/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-user/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-user/src/routes/build-routes.md create mode 100644 docs/api-stack/api/api-plugin-user/src/routes/delete-me.md create mode 100644 docs/api-stack/api/api-plugin-user/src/routes/get-me.md create mode 100644 docs/api-stack/api/api-plugin-user/src/routes/patch-me.md create mode 100644 docs/api-stack/api/api-plugin-user/src/schema/schema.md create mode 100644 docs/api-stack/api/api-plugin-user/src/schemas/options.md create mode 100644 docs/api-stack/api/api-plugin-user/src/schemas/user-profile.md create mode 100644 docs/api-stack/api/api-plugin-user/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-user/src/services/user-service.md create mode 100644 docs/api-stack/api/api-plugin-user/src/types/types.md create mode 100644 docs/api-stack/api/api-plugin-vault/README.md create mode 100644 docs/api-stack/api/api-plugin-vault/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-vault/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-vault/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-vault/src/plugin/unlock.md create mode 100644 docs/api-stack/api/api-plugin-vault/src/routes/build-routes.md create mode 100644 docs/api-stack/api/api-plugin-vault/src/schema/schema.md create mode 100644 docs/api-stack/api/api-plugin-vault/src/schemas/options.md create mode 100644 docs/api-stack/api/api-plugin-vault/src/schemas/vault-item.md create mode 100644 docs/api-stack/api/api-plugin-vault/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-vault/src/services/vault-service.md create mode 100644 docs/api-stack/api/api-plugin-vault/src/types/types.md create mode 100644 docs/api-stack/api/api-plugin-webhook/README.md create mode 100644 docs/api-stack/api/api-plugin-webhook/src/dead-letter/dead-letter.md create mode 100644 docs/api-stack/api/api-plugin-webhook/src/dead-letter/memory.md create mode 100644 docs/api-stack/api/api-plugin-webhook/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin-webhook/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-plugin-webhook/src/plugin/plugin.md create mode 100644 docs/api-stack/api/api-plugin-webhook/src/routes/build-routes.md create mode 100644 docs/api-stack/api/api-plugin-webhook/src/schemas/endpoint.md create mode 100644 docs/api-stack/api/api-plugin-webhook/src/schemas/options.md create mode 100644 docs/api-stack/api/api-plugin-webhook/src/schemas/routes/routes.md create mode 100644 docs/api-stack/api/api-plugin-webhook/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api-plugin-webhook/src/services/webhook-service.md create mode 100644 docs/api-stack/api/api-plugin-webhook/src/store/endpoint-store.md create mode 100644 docs/api-stack/api/api-plugin-webhook/src/store/memory.md create mode 100644 docs/api-stack/api/api-plugin-webhook/src/types/types.md create mode 100644 docs/api-stack/api/api-plugin/README.md create mode 100644 docs/api-stack/api/api-plugin/src/context/context.md create mode 100644 docs/api-stack/api/api-plugin/src/define/define.md create mode 100644 docs/api-stack/api/api-plugin/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-plugin/src/hook-executor/hook-executor.md create mode 100644 docs/api-stack/api/api-plugin/src/registry/registry.md create mode 100644 docs/api-stack/api/api-plugin/src/service-registry/service-registry.md create mode 100644 docs/api-stack/api/api-plugin/src/topo-sort/topo-sort.md create mode 100644 docs/api-stack/api/api-plugin/src/types/api-plugin.md create mode 100644 docs/api-stack/api/api-rate-limit/README.md create mode 100644 docs/api-stack/api/api-rate-limit/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-rate-limit/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-rate-limit/src/middleware/middleware.md create mode 100644 docs/api-stack/api/api-rate-limit/src/selector/selector.md create mode 100644 docs/api-stack/api/api-rate-limit/src/store/memory-store/memory-store.md create mode 100644 docs/api-stack/api/api-rate-limit/src/store/store-like/store-like.md create mode 100644 docs/api-stack/api/api-rbac/README.md create mode 100644 docs/api-stack/api/api-rbac/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-rbac/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-rbac/src/middleware/middleware.md create mode 100644 docs/api-stack/api/api-rbac/src/registry/registry.md create mode 100644 docs/api-stack/api/api-rbac/src/spec/spec.md create mode 100644 docs/api-stack/api/api-router-hono/README.md create mode 100644 docs/api-stack/api/api-router-hono/src/adapter/adapter.md create mode 100644 docs/api-stack/api/api-router-hono/src/blue-green-slot/blue-green-slot.md create mode 100644 docs/api-stack/api/api-router-hono/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-router-hono/src/middleware-adapter/middleware-adapter.md create mode 100644 docs/api-stack/api/api-router-hono/src/pipeline/pipeline.md create mode 100644 docs/api-stack/api/api-router-in-memory/README.md create mode 100644 docs/api-stack/api/api-router-in-memory/src/adapter/adapter.md create mode 100644 docs/api-stack/api/api-router-in-memory/src/blue-green-slot/blue-green-slot.md create mode 100644 docs/api-stack/api/api-router-in-memory/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-router-in-memory/src/pipeline/pipeline.md create mode 100644 docs/api-stack/api/api-router-in-memory/src/testing/testing.md create mode 100644 docs/api-stack/api/api-router-worker-bridge/README.md create mode 100644 docs/api-stack/api/api-router-worker-bridge/src/bridge/bridge.md create mode 100644 docs/api-stack/api/api-router-worker-bridge/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-router-worker-bridge/src/marshal-request/marshal-request.md create mode 100644 docs/api-stack/api/api-router-worker-bridge/src/marshal-response/marshal-response.md create mode 100644 docs/api-stack/api/api-router-worker-bridge/src/streaming/streaming.md create mode 100644 docs/api-stack/api/api-router-worker-bridge/src/testing/testing.md create mode 100644 docs/api-stack/api/api-router/README.md create mode 100644 docs/api-stack/api/api-router/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-router/src/middleware/insertion-point.md create mode 100644 docs/api-stack/api/api-router/src/middleware/middleware.md create mode 100644 docs/api-stack/api/api-router/src/request/request.md create mode 100644 docs/api-stack/api/api-router/src/response/response.md create mode 100644 docs/api-stack/api/api-router/src/route-match/route-match.md create mode 100644 docs/api-stack/api/api-router/src/route-options/route-options.md create mode 100644 docs/api-stack/api/api-router/src/router/router.md create mode 100644 docs/api-stack/api/api-router/src/slot/slot.md create mode 100644 docs/api-stack/api/api-router/src/testing/conformance.md create mode 100644 docs/api-stack/api/api-router/src/testing/pipeline-router-conformance/pipeline-router-conformance.md create mode 100644 docs/api-stack/api/api-saga/README.md create mode 100644 docs/api-stack/api/api-saga/src/compensation/compensation.md create mode 100644 docs/api-stack/api/api-saga/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-saga/src/events/events.md create mode 100644 docs/api-stack/api/api-saga/src/idempotency/idempotency.md create mode 100644 docs/api-stack/api/api-saga/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-saga/src/orchestrator/compensate-runner.md create mode 100644 docs/api-stack/api/api-saga/src/orchestrator/orchestrator.md create mode 100644 docs/api-stack/api/api-saga/src/orchestrator/step-runner.md create mode 100644 docs/api-stack/api/api-saga/src/persistence/persistence.md create mode 100644 docs/api-stack/api/api-saga/src/recovery/recovery.md create mode 100644 docs/api-stack/api/api-saga/src/registry/participant-registry.md create mode 100644 docs/api-stack/api/api-saga/src/state/state-machine.md create mode 100644 docs/api-stack/api/api-saga/src/tenant/cross-tenant.md create mode 100644 docs/api-stack/api/api-saga/src/testing/testing.md create mode 100644 docs/api-stack/api/api-sandbox-permissions/README.md create mode 100644 docs/api-stack/api/api-sandbox-permissions/src/budget/budget.md create mode 100644 docs/api-stack/api/api-sandbox-permissions/src/checker/capability/capability.md create mode 100644 docs/api-stack/api/api-sandbox-permissions/src/checker/checker.md create mode 100644 docs/api-stack/api/api-sandbox-permissions/src/checker/fetch/fetch.md create mode 100644 docs/api-stack/api/api-sandbox-permissions/src/checker/fs/fs.md create mode 100644 docs/api-stack/api/api-sandbox-permissions/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-sandbox-permissions/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-sandbox-permissions/src/policy/policy.md create mode 100644 docs/api-stack/api/api-sandbox-permissions/src/testing/run-permissions-conformance.md create mode 100644 docs/api-stack/api/api-sandbox-vm-host-bridge/README.md create mode 100644 docs/api-stack/api/api-sandbox-vm-host-bridge/src/bridge/bridge.md create mode 100644 docs/api-stack/api/api-sandbox-vm-host-bridge/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-sandbox-vm-host-bridge/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-sandbox-vm-host-bridge/src/lifecycle/lifecycle.md create mode 100644 docs/api-stack/api/api-sandbox-vm-host-bridge/src/marshal/marshal-request.md create mode 100644 docs/api-stack/api/api-sandbox-vm-host-bridge/src/marshal/marshal-response.md create mode 100644 docs/api-stack/api/api-sandbox-vm-host-bridge/src/route-discovery/route-discovery.md create mode 100644 docs/api-stack/api/api-sandbox-vm-host-bridge/src/testing/vm-host-bridge-conformance/vm-host-bridge-conformance.md create mode 100644 docs/api-stack/api/api-sandbox-vm/README.md create mode 100644 docs/api-stack/api/api-sandbox-vm/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-sandbox-vm/src/globals/frozen-globals/frozen-globals.md create mode 100644 docs/api-stack/api/api-sandbox-vm/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-sandbox-vm/src/permissions/checker.md create mode 100644 docs/api-stack/api/api-sandbox-vm/src/proxies/fetch-proxy/fetch-proxy.md create mode 100644 docs/api-stack/api/api-sandbox-vm/src/proxies/fs-proxy/fs-proxy.md create mode 100644 docs/api-stack/api/api-sandbox-vm/src/proxies/install-capability-proxies/install-capability-proxies.md create mode 100644 docs/api-stack/api/api-sandbox-vm/src/sandbox/sandbox.md create mode 100644 docs/api-stack/api/api-sandbox-vm/src/testing/run-vm-conformance.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/README.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/abi-direct/marshal/marshal.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/abi-direct/memory/memory.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/abi-direct/memory/trap-classifier.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/abi-direct/wasm-abi/abi-validator.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/abi-direct/wasm-abi/abi.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/abi-wasi-stdio/wasi-stdio-validate.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/bridge/bridge-direct.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/bridge/bridge-marshal.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/bridge/bridge-wasi-stdio.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/bridge/bridge.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/lifecycle/lifecycle.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/route-discovery/route-discovery.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/testing/wasm-host-bridge-conformance/wasm-host-bridge-conformance.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/wasi-stdio/wasi-stdio-frame.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/wasi-stdio/wasi-stdio-imports.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/wasi-stdio/wasi-stdio-lifecycle.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/wasi-stdio/wasi-stdio-memory-ref.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/wasi-stdio/wasi-stdio-routes.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/wasi-stdio/wasi-stdio-runner.md create mode 100644 docs/api-stack/api/api-sandbox-wasm-host-bridge/src/wasi-stdio/wasi-stdio-streams.md create mode 100644 docs/api-stack/api/api-sandbox-wasm/README.md create mode 100644 docs/api-stack/api/api-sandbox-wasm/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-sandbox-wasm/src/imports/install-capability-imports/install-capability-imports.md create mode 100644 docs/api-stack/api/api-sandbox-wasm/src/otel/otel.md create mode 100644 docs/api-stack/api/api-sandbox-wasm/src/outbound/outbound.md create mode 100644 docs/api-stack/api/api-sandbox-wasm/src/policy/policy.md create mode 100644 docs/api-stack/api/api-sandbox-wasm/src/preopens/preopens.md create mode 100644 docs/api-stack/api/api-sandbox-wasm/src/sandbox/sandbox.md create mode 100644 docs/api-stack/api/api-sandbox-wasm/src/testing/run-wasm-conformance.md create mode 100644 docs/api-stack/api/api-sandbox-wasm/src/wasi/wasi.md create mode 100644 docs/api-stack/api/api-schemas/README.md create mode 100644 docs/api-stack/api/api-schemas/src/admin/health.md create mode 100644 docs/api-stack/api/api-schemas/src/admin/ping.md create mode 100644 docs/api-stack/api/api-schemas/src/admin/status.md create mode 100644 docs/api-stack/api/api-schemas/src/auth/context.md create mode 100644 docs/api-stack/api/api-schemas/src/auth/login.md create mode 100644 docs/api-stack/api/api-schemas/src/auth/logout.md create mode 100644 docs/api-stack/api/api-schemas/src/auth/refresh.md create mode 100644 docs/api-stack/api/api-schemas/src/auth/register.md create mode 100644 docs/api-stack/api/api-schemas/src/common/error-envelope.md create mode 100644 docs/api-stack/api/api-schemas/src/common/filter.md create mode 100644 docs/api-stack/api/api-schemas/src/common/id-param.md create mode 100644 docs/api-stack/api/api-schemas/src/common/pagination.md create mode 100644 docs/api-stack/api/api-schemas/src/common/sort.md create mode 100644 docs/api-stack/api/api-schemas/src/common/timestamps.md create mode 100644 docs/api-stack/api/api-schemas/src/events/domain-event.md create mode 100644 docs/api-stack/api/api-schemas/src/events/envelope.md create mode 100644 docs/api-stack/api/api-schemas/src/events/metadata.md create mode 100644 docs/api-stack/api/api-schemas/src/helpers/to-suaveplan-error.md create mode 100644 docs/api-stack/api/api-secrets-bun/README.md create mode 100644 docs/api-stack/api/api-secrets-bun/src/adapter/adapter.md create mode 100644 docs/api-stack/api/api-secrets-bun/src/allowlist/allowlist.md create mode 100644 docs/api-stack/api/api-secrets-bun/src/descriptor-builder/descriptor-builder.md create mode 100644 docs/api-stack/api/api-secrets-bun/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-secrets-bun/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-secrets-env/README.md create mode 100644 docs/api-stack/api/api-secrets-env/src/adapter/adapter.md create mode 100644 docs/api-stack/api/api-secrets-env/src/descriptor-builder/descriptor-builder.md create mode 100644 docs/api-stack/api/api-secrets-env/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-secrets-vault/README.md create mode 100644 docs/api-stack/api/api-secrets-vault/src/adapter/adapter.md create mode 100644 docs/api-stack/api/api-secrets-vault/src/allowlist/allowlist.md create mode 100644 docs/api-stack/api/api-secrets-vault/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-secrets-vault/src/from-vault/from-vault.md create mode 100644 docs/api-stack/api/api-secrets-vault/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-secrets-vault/src/types/types.md create mode 100644 docs/api-stack/api/api-secrets-vault/src/watcher/watcher.md create mode 100644 docs/api-stack/api/api-secrets-worker-proxy/README.md create mode 100644 docs/api-stack/api/api-secrets-worker-proxy/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-secrets-worker-proxy/src/main-side/main-side.md create mode 100644 docs/api-stack/api/api-secrets-worker-proxy/src/redaction/redaction.md create mode 100644 docs/api-stack/api/api-secrets-worker-proxy/src/testing/testing.md create mode 100644 docs/api-stack/api/api-secrets-worker-proxy/src/worker-side/worker-side.md create mode 100644 docs/api-stack/api/api-secrets/README.md create mode 100644 docs/api-stack/api/api-secrets/src/capability-id/capability-id.md create mode 100644 docs/api-stack/api/api-secrets/src/descriptor/descriptor.md create mode 100644 docs/api-stack/api/api-secrets/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-secrets/src/redaction/redaction.md create mode 100644 docs/api-stack/api/api-secrets/src/secrets-like/secrets-like.md create mode 100644 docs/api-stack/api/api-secrets/src/testing/conformance.md create mode 100644 docs/api-stack/api/api-sse-bun/README.md create mode 100644 docs/api-stack/api/api-sse-bun/src/compression/compression.md create mode 100644 docs/api-stack/api/api-sse-bun/src/engine/bun-sse-engine.md create mode 100644 docs/api-stack/api/api-sse-bun/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-sse-bun/src/event-buffer/event-buffer.md create mode 100644 docs/api-stack/api/api-sse-bun/src/handshake/handshake.md create mode 100644 docs/api-stack/api/api-sse-bun/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-sse-bun/src/keep-alive/keep-alive.md create mode 100644 docs/api-stack/api/api-sse-bun/src/last-event-id/last-event-id.md create mode 100644 docs/api-stack/api/api-sse-bun/src/limits/tenant-cap.md create mode 100644 docs/api-stack/api/api-sse-bun/src/options/options.md create mode 100644 docs/api-stack/api/api-sse-bun/src/stream/sse-stream.md create mode 100644 docs/api-stack/api/api-sse-bun/src/subscription/subscription-bus.md create mode 100644 docs/api-stack/api/api-sse-bun/src/testing/conformance.md create mode 100644 docs/api-stack/api/api-sse/README.md create mode 100644 docs/api-stack/api/api-sse/src/broker/broker.md create mode 100644 docs/api-stack/api/api-sse/src/capability-id/capability-id.md create mode 100644 docs/api-stack/api/api-sse/src/connection-registry/connection-registry.md create mode 100644 docs/api-stack/api/api-sse/src/connection/connection.md create mode 100644 docs/api-stack/api/api-sse/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-sse/src/error-codes/production-throws.md create mode 100644 docs/api-stack/api/api-sse/src/event/event.md create mode 100644 docs/api-stack/api/api-sse/src/replay-buffer/replay-buffer.md create mode 100644 docs/api-stack/api/api-sse/src/testing/conformance.md create mode 100644 docs/api-stack/api/api-tenant-provider-memory/README.md create mode 100644 docs/api-stack/api/api-tenant-provider-memory/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-tenant-provider-memory/src/provider/provider.md create mode 100644 docs/api-stack/api/api-tenant-provider/README.md create mode 100644 docs/api-stack/api/api-tenant-provider/src/capability-id/capability-id.md create mode 100644 docs/api-stack/api/api-tenant-provider/src/chain/chain.md create mode 100644 docs/api-stack/api/api-tenant-provider/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-tenant-provider/src/pagination/pagination.md create mode 100644 docs/api-stack/api/api-tenant-provider/src/provider/provider.md create mode 100644 docs/api-stack/api/api-tenant-provider/src/tenant-record/tenant-record.md create mode 100644 docs/api-stack/api/api-tenant-provider/src/testing/conformance.md create mode 100644 docs/api-stack/api/api-tenant-resolver-header/README.md create mode 100644 docs/api-stack/api/api-tenant-resolver-header/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-tenant-resolver-header/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-tenant-resolver-header/src/options/options.md create mode 100644 docs/api-stack/api/api-tenant-resolver-header/src/resolver/resolver.md create mode 100644 docs/api-stack/api/api-tenant-resolver-header/src/trust/trust.md create mode 100644 docs/api-stack/api/api-tenant-resolver-header/src/validate/validate.md create mode 100644 docs/api-stack/api/api-tenant-resolver-jwt/README.md create mode 100644 docs/api-stack/api/api-tenant-resolver-jwt/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-tenant-resolver-jwt/src/options/options.md create mode 100644 docs/api-stack/api/api-tenant-resolver-jwt/src/resolver/resolver.md create mode 100644 docs/api-stack/api/api-tenant-resolver-subdomain/README.md create mode 100644 docs/api-stack/api/api-tenant-resolver-subdomain/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-tenant-resolver-subdomain/src/forwarded/forwarded.md create mode 100644 docs/api-stack/api/api-tenant-resolver-subdomain/src/options/options.md create mode 100644 docs/api-stack/api/api-tenant-resolver-subdomain/src/otel/instruments.md create mode 100644 docs/api-stack/api/api-tenant-resolver-subdomain/src/resolver/resolver.md create mode 100644 docs/api-stack/api/api-tenant-resolver-subdomain/src/validate/validate.md create mode 100644 docs/api-stack/api/api-tenant/README.md create mode 100644 docs/api-stack/api/api-tenant/src/cache/cache.md create mode 100644 docs/api-stack/api/api-tenant/src/context/context.md create mode 100644 docs/api-stack/api/api-tenant/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-tenant/src/lifecycle/lifecycle.md create mode 100644 docs/api-stack/api/api-tenant/src/middleware/middleware.md create mode 100644 docs/api-stack/api/api-tenant/src/middleware/require-feature.md create mode 100644 docs/api-stack/api/api-tenant/src/middleware/require-plugin.md create mode 100644 docs/api-stack/api/api-tenant/src/rate-limit/rate-limit.md create mode 100644 docs/api-stack/api/api-tenant/src/resolver/resolver.md create mode 100644 docs/api-stack/api/api-tenant/src/storage/storage.md create mode 100644 docs/api-stack/api/api-tenant/src/types/tenant.md create mode 100644 docs/api-stack/api/api-types/README.md create mode 100644 docs/api-stack/api/api-types/src/auth/auth.md create mode 100644 docs/api-stack/api/api-types/src/capabilities/capabilities.md create mode 100644 docs/api-stack/api/api-types/src/db/db.md create mode 100644 docs/api-stack/api/api-types/src/errors/errors.md create mode 100644 docs/api-stack/api/api-types/src/graphql/graphql.md create mode 100644 docs/api-stack/api/api-types/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-types/src/lifecycle/lifecycle.md create mode 100644 docs/api-stack/api/api-types/src/manifest/manifest.md create mode 100644 docs/api-stack/api/api-types/src/pipeline-events/pipeline-events.md create mode 100644 docs/api-stack/api/api-types/src/plugin-context/plugin-context.md create mode 100644 docs/api-stack/api/api-types/src/principal/principal.md create mode 100644 docs/api-stack/api/api-types/src/rollback-journal/rollback-journal.md create mode 100644 docs/api-stack/api/api-types/src/router/router.md create mode 100644 docs/api-stack/api/api-types/src/saga/saga.md create mode 100644 docs/api-stack/api/api-types/src/sandbox-bridge/sandbox-bridge.md create mode 100644 docs/api-stack/api/api-types/src/sandbox-bridge/wasi-stdio-protocol.md create mode 100644 docs/api-stack/api/api-types/src/secrets/secrets.md create mode 100644 docs/api-stack/api/api-types/src/sse/sse.md create mode 100644 docs/api-stack/api/api-types/src/tenant-resolver/tenant-resolver.md create mode 100644 docs/api-stack/api/api-types/src/tenant/tenant.md create mode 100644 docs/api-stack/api/api-types/src/twopc/twopc.md create mode 100644 docs/api-stack/api/api-types/src/worker-rpc/worker-rpc.md create mode 100644 docs/api-stack/api/api-types/src/ws/ws.md create mode 100644 docs/api-stack/api/api-worker-host/README.md create mode 100644 docs/api-stack/api/api-worker-host/src/bootstrap/bootstrap.md create mode 100644 docs/api-stack/api/api-worker-host/src/capability-proxies/capability-proxies.md create mode 100644 docs/api-stack/api/api-worker-host/src/crash-detection/crash-detection.md create mode 100644 docs/api-stack/api/api-worker-host/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-worker-host/src/lifecycle/lifecycle.md create mode 100644 docs/api-stack/api/api-worker-host/src/protocol-extension/protocol-extension.md create mode 100644 docs/api-stack/api/api-worker-host/src/testing/testing.md create mode 100644 docs/api-stack/api/api-worker-rpc/README.md create mode 100644 docs/api-stack/api/api-worker-rpc/src/abort-forwarding/abort-forwarding.md create mode 100644 docs/api-stack/api/api-worker-rpc/src/backpressure/backpressure.md create mode 100644 docs/api-stack/api/api-worker-rpc/src/client/client.md create mode 100644 docs/api-stack/api/api-worker-rpc/src/client/cloneable-guard.md create mode 100644 docs/api-stack/api/api-worker-rpc/src/correlation/correlation.md create mode 100644 docs/api-stack/api/api-worker-rpc/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-worker-rpc/src/error-reconstruction/error-reconstruction.md create mode 100644 docs/api-stack/api/api-worker-rpc/src/protocol/protocol.md create mode 100644 docs/api-stack/api/api-worker-rpc/src/server/server.md create mode 100644 docs/api-stack/api/api-worker-rpc/src/streaming/streaming.md create mode 100644 docs/api-stack/api/api-worker-rpc/src/testing/conformance.md create mode 100644 docs/api-stack/api/api-worker-rpc/src/testing/testing.md create mode 100644 docs/api-stack/api/api-ws-broker-in-memory/README.md create mode 100644 docs/api-stack/api/api-ws-broker-in-memory/src/broker/broker.md create mode 100644 docs/api-stack/api/api-ws-broker-in-memory/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-ws-broker-in-memory/src/options/options.md create mode 100644 docs/api-stack/api/api-ws-broker-in-memory/src/testing/testing.md create mode 100644 docs/api-stack/api/api-ws-broker-redis/README.md create mode 100644 docs/api-stack/api/api-ws-broker-redis/src/broker/broker.md create mode 100644 docs/api-stack/api/api-ws-broker-redis/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-ws-broker-redis/src/event-buffer/event-buffer.md create mode 100644 docs/api-stack/api/api-ws-broker-redis/src/health/health.md create mode 100644 docs/api-stack/api/api-ws-broker-redis/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-ws-broker-redis/src/options/options.md create mode 100644 docs/api-stack/api/api-ws-broker-redis/src/publish/publish.md create mode 100644 docs/api-stack/api/api-ws-broker-redis/src/reconnect/reconnect.md create mode 100644 docs/api-stack/api/api-ws-broker-redis/src/resp-client/resp-client.md create mode 100644 docs/api-stack/api/api-ws-broker-redis/src/subscribe/subscribe.md create mode 100644 docs/api-stack/api/api-ws-bun/README.md create mode 100644 docs/api-stack/api/api-ws-bun/src/backpressure/backpressure.md create mode 100644 docs/api-stack/api/api-ws-bun/src/engine/bun-ws-engine.md create mode 100644 docs/api-stack/api/api-ws-bun/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-ws-bun/src/handshake/handshake.md create mode 100644 docs/api-stack/api/api-ws-bun/src/handshake/subprotocol.md create mode 100644 docs/api-stack/api/api-ws-bun/src/heartbeat/heartbeat.md create mode 100644 docs/api-stack/api/api-ws-bun/src/instruments/instruments.md create mode 100644 docs/api-stack/api/api-ws-bun/src/limits/tenant-cap.md create mode 100644 docs/api-stack/api/api-ws-bun/src/options/options.md create mode 100644 docs/api-stack/api/api-ws-bun/src/principal/principal-expiry.md create mode 100644 docs/api-stack/api/api-ws-bun/src/reconnect/event-buffer.md create mode 100644 docs/api-stack/api/api-ws-bun/src/reconnect/reconnect-token.md create mode 100644 docs/api-stack/api/api-ws-bun/src/registry/connection-registry.md create mode 100644 docs/api-stack/api/api-ws-bun/src/subscription/subscription-bus.md create mode 100644 docs/api-stack/api/api-ws-bun/src/testing/conformance-binding.md create mode 100644 docs/api-stack/api/api-ws/README.md create mode 100644 docs/api-stack/api/api-ws/src/backpressure/backpressure.md create mode 100644 docs/api-stack/api/api-ws/src/broker/broker.md create mode 100644 docs/api-stack/api/api-ws/src/capability-id/capability-id.md create mode 100644 docs/api-stack/api/api-ws/src/connection-registry/connection-registry.md create mode 100644 docs/api-stack/api/api-ws/src/connection/connection.md create mode 100644 docs/api-stack/api/api-ws/src/envelope/envelope.md create mode 100644 docs/api-stack/api/api-ws/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api-ws/src/heartbeat/heartbeat.md create mode 100644 docs/api-stack/api/api-ws/src/reconnect-token/reconnect-token.md create mode 100644 docs/api-stack/api/api-ws/src/subscription-bus/subscription-bus.md create mode 100644 docs/api-stack/api/api-ws/src/testing/conformance.md create mode 100644 docs/api-stack/api/api/README.md create mode 100644 docs/api-stack/api/api/src/app/app.md create mode 100644 docs/api-stack/api/api/src/app/health-routes.md create mode 100644 docs/api-stack/api/api/src/app/migrations.md create mode 100644 docs/api-stack/api/api/src/app/request-context.md create mode 100644 docs/api-stack/api/api/src/app/timeout.md create mode 100644 docs/api-stack/api/api/src/builder/assemble.md create mode 100644 docs/api-stack/api/api/src/builder/builder.md create mode 100644 docs/api-stack/api/api/src/builder/cors-bridge.md create mode 100644 docs/api-stack/api/api/src/config/config.md create mode 100644 docs/api-stack/api/api/src/config/loader.md create mode 100644 docs/api-stack/api/api/src/config/validator.md create mode 100644 docs/api-stack/api/api/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/api/src/event-integration/event-bridge.md create mode 100644 docs/api-stack/api/api/src/middleware/chain.md create mode 100644 docs/api-stack/api/api/src/middleware/composition.md create mode 100644 docs/api-stack/api/api/src/middleware/cors.md create mode 100644 docs/api-stack/api/api/src/middleware/error-handler.md create mode 100644 docs/api-stack/api/api/src/middleware/logger.md create mode 100644 docs/api-stack/api/api/src/middleware/request-id.md create mode 100644 docs/api-stack/api/api/src/services/registry-augmentation.md create mode 100644 docs/api-stack/api/api/src/types/api.md create mode 100644 docs/api-stack/api/create-suaveplan-plugin/README.md create mode 100644 docs/api-stack/api/create-suaveplan-plugin/src/bin/create-suaveplan-plugin.md create mode 100644 docs/api-stack/api/create-suaveplan-plugin/src/error-codes.md create mode 100644 docs/api-stack/api/create-suaveplan-plugin/src/generator/generator.md create mode 100644 docs/api-stack/api/create-suaveplan-plugin/src/prompt/prompt.md create mode 100644 docs/api-stack/api/create-suaveplan-plugin/src/templates/templates.md create mode 100644 docs/api-stack/api/create-suaveplan-plugin/tests/scaffold-output/snapshots/isolated-sqlite-rest-only/README.md create mode 100644 docs/api-stack/api/create-suaveplan-plugin/tests/scaffold-output/snapshots/sandboxed-none-rest-only/README.md create mode 100644 docs/api-stack/api/create-suaveplan-plugin/tests/scaffold-output/snapshots/trusted-postgres-full/README.md create mode 100644 docs/api-stack/api/wasm-compiler-javy/README.md create mode 100644 docs/api-stack/api/wasm-compiler-javy/src/abi-shim/abi-shim-polyfills.md create mode 100644 docs/api-stack/api/wasm-compiler-javy/src/abi-shim/abi-shim.md create mode 100644 docs/api-stack/api/wasm-compiler-javy/src/bin/cli.md create mode 100644 docs/api-stack/api/wasm-compiler-javy/src/bundle/bundle.md create mode 100644 docs/api-stack/api/wasm-compiler-javy/src/compile/compile.md create mode 100644 docs/api-stack/api/wasm-compiler-javy/src/error-codes/error-codes.md create mode 100644 docs/api-stack/api/wasm-compiler-javy/src/instruments/instruments.md create mode 100644 docs/api-stack/api/wasm-compiler-javy/src/javy/javy-invoke.md create mode 100644 docs/api-stack/api/wasm-compiler-javy/src/javy/javy-locate.md create mode 100644 docs/api-stack/api/wasm-compiler-javy/src/manifest/manifest.md create mode 100644 docs/api-stack/api/wasm-compiler-javy/src/route-extract/route-extract.md create mode 100644 docs/api-stack/api/wasm-compiler-javy/src/testing/wasm-compiler-conformance/wasm-compiler-conformance.md create mode 100644 docs/api-stack/api/wasm-compiler-javy/src/validate/abi-validate.md create mode 100644 docs/commerce/README.md create mode 100644 docs/commerce/_intro.md create mode 100644 docs/commerce/booking/README.md create mode 100644 docs/commerce/booking/_intro.md create mode 100644 docs/commerce/booking/booking/README.md create mode 100644 docs/commerce/booking/booking/src/availability/resolver/resolver.md create mode 100644 docs/commerce/booking/booking/src/availability/strategies/strategies.md create mode 100644 docs/commerce/booking/booking/src/conflict/detector/detector.md create mode 100644 docs/commerce/booking/booking/src/conflict/exact-match/exact-match.md create mode 100644 docs/commerce/booking/booking/src/conflict/provider-overlap/provider-overlap.md create mode 100644 docs/commerce/booking/booking/src/conflict/range-overlap/range-overlap.md create mode 100644 docs/commerce/booking/booking/src/conflict/slot-capacity/slot-capacity.md create mode 100644 docs/commerce/booking/booking/src/core/engine/engine.md create mode 100644 docs/commerce/booking/booking/src/core/event-bus/event-bus.md create mode 100644 docs/commerce/booking/booking/src/core/state-machine/state-machine.md create mode 100644 docs/commerce/booking/booking/src/domains/accommodation/accommodation.md create mode 100644 docs/commerce/booking/booking/src/domains/activities/activities.md create mode 100644 docs/commerce/booking/booking/src/domains/appointments/appointments.md create mode 100644 docs/commerce/booking/booking/src/domains/resources/resources.md create mode 100644 docs/commerce/booking/booking/src/domains/seats/seats.md create mode 100644 docs/commerce/booking/booking/src/domains/shared.md create mode 100644 docs/commerce/booking/booking/src/domains/transport/transport.md create mode 100644 docs/commerce/booking/booking/src/error-codes/error-codes.md create mode 100644 docs/commerce/booking/booking/src/hooks/hooks.md create mode 100644 docs/commerce/booking/booking/src/pricing/calculator/calculator.md create mode 100644 docs/commerce/booking/booking/src/pricing/dynamic/dynamic.md create mode 100644 docs/commerce/booking/booking/src/pricing/seasonal/seasonal.md create mode 100644 docs/commerce/booking/booking/src/rules/conditions/conditions.md create mode 100644 docs/commerce/booking/booking/src/rules/evaluator/evaluator.md create mode 100644 docs/commerce/booking/booking/src/schemas/booking.schema.md create mode 100644 docs/commerce/booking/booking/src/schemas/config.schema.md create mode 100644 docs/commerce/booking/booking/src/temporal/recurrence/recurrence.md create mode 100644 docs/commerce/booking/booking/src/temporal/slots/slots.md create mode 100644 docs/commerce/booking/booking/src/temporal/windows/windows.md create mode 100644 docs/commerce/booking/booking/src/types/bookable.types.md create mode 100644 docs/commerce/booking/booking/src/types/booking-hooks.types.md create mode 100644 docs/commerce/booking/booking/src/types/booking.types.md create mode 100644 docs/commerce/booking/booking/src/types/capacity.types.md create mode 100644 docs/commerce/booking/booking/src/types/config.types.md create mode 100644 docs/commerce/booking/booking/src/types/events.types.md create mode 100644 docs/commerce/booking/booking/src/types/layout.types.md create mode 100644 docs/commerce/booking/booking/src/types/pricing.types.md create mode 100644 docs/commerce/booking/booking/src/types/rules.types.md create mode 100644 docs/commerce/booking/booking/src/types/temporal.types.md create mode 100644 docs/commerce/booking/booking/src/utils/utils.md create mode 100644 docs/commerce/contacts/README.md create mode 100644 docs/commerce/contacts/_intro.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/README.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/context/context.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/error-codes/error-codes.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/otel/instruments.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/plugin/plugin.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/plugin/schema.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/repositories/contact-repository.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/repositories/group-repository.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/repositories/membership-repository.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/routes/contacts/build-routes.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/routes/contacts/contacts-bulk-routes.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/routes/contacts/contacts-crud-routes.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/routes/groups/build-routes.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/routes/groups/groups-crud-routes.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/routes/groups/groups-members-routes.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/routes/groups/groups-tree-routes.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/routes/shared/require-tenant.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/routes/shared/strip-undefined.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/schemas/contacts-schemas.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/schemas/groups-schemas.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/schemas/options.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/services/registry-augmentation.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/tree/build-tree.md create mode 100644 docs/commerce/contacts/api-plugin-contacts/src/types/types.md create mode 100644 docs/commerce/contacts/audience-rules/README.md create mode 100644 docs/commerce/contacts/audience-rules/src/error-codes/error-codes.md create mode 100644 docs/commerce/contacts/audience-rules/src/predicates/predicates.md create mode 100644 docs/commerce/contacts/audience-rules/src/schemas/schemas.md create mode 100644 docs/commerce/contacts/audience-rules/src/segment-evaluator/segment-evaluator.md create mode 100644 docs/commerce/contacts/audience-rules/src/segment-refresher/segment-refresher.md create mode 100644 docs/commerce/contacts/audience-rules/src/store/store.md create mode 100644 docs/commerce/contacts/audience-rules/src/types/segment.types.md create mode 100644 docs/commerce/contacts/contacts/README.md create mode 100644 docs/commerce/contacts/contacts/src/core/audience-resolver/audience-resolver.md create mode 100644 docs/commerce/contacts/contacts/src/core/contact-manager/contact-manager.md create mode 100644 docs/commerce/contacts/contacts/src/core/contact-merger/contact-merger.md create mode 100644 docs/commerce/contacts/contacts/src/core/group-manager/group-manager.md create mode 100644 docs/commerce/contacts/contacts/src/core/membership-manager/membership-manager.md create mode 100644 docs/commerce/contacts/contacts/src/error-codes/error-codes.md create mode 100644 docs/commerce/contacts/contacts/src/import-export/contact-exporter/contact-exporter.md create mode 100644 docs/commerce/contacts/contacts/src/import-export/contact-importer/contact-importer.md create mode 100644 docs/commerce/contacts/contacts/src/otel/instruments.md create mode 100644 docs/commerce/contacts/contacts/src/schemas/schemas.md create mode 100644 docs/commerce/contacts/contacts/src/stores/contact-store/contact-store.md create mode 100644 docs/commerce/contacts/contacts/src/stores/group-store/group-store.md create mode 100644 docs/commerce/contacts/contacts/src/stores/membership-store/membership-store.md create mode 100644 docs/commerce/contacts/contacts/src/tree/tree-utils.md create mode 100644 docs/commerce/contacts/contacts/src/types/contact.types.md create mode 100644 docs/commerce/contacts/contacts/src/types/group.types.md create mode 100644 docs/commerce/contacts/contacts/src/types/membership.types.md create mode 100644 docs/commerce/contacts/macos-contacts/README.md create mode 100644 docs/commerce/contacts/macos-contacts/src/applescript/applescript.md create mode 100644 docs/commerce/contacts/macos-contacts/src/bridge/bridge.md create mode 100644 docs/commerce/contacts/macos-contacts/src/error-codes/error-codes.md create mode 100644 docs/commerce/contacts/macos-contacts/src/executor/executor.md create mode 100644 docs/commerce/contacts/macos-contacts/src/otel/instruments.md create mode 100644 docs/commerce/contacts/macos-contacts/src/parser/parser.md create mode 100644 docs/commerce/contacts/macos-contacts/src/schemas/schemas.md create mode 100644 docs/commerce/contacts/macos-contacts/src/types/macos-contacts.types.md create mode 100644 docs/communication/README.md create mode 100644 docs/communication/_intro.md create mode 100644 docs/communication/emails/README.md create mode 100644 docs/communication/emails/_intro.md create mode 100644 docs/communication/emails/campaigns/README.md create mode 100644 docs/communication/emails/campaigns/src/batch-planner/batch-planner.md create mode 100644 docs/communication/emails/campaigns/src/engine/engine.md create mode 100644 docs/communication/emails/campaigns/src/error-codes/error-codes.md create mode 100644 docs/communication/emails/campaigns/src/state-machine/state-machine.md create mode 100644 docs/communication/emails/campaigns/src/store/store.md create mode 100644 docs/communication/emails/campaigns/src/telemetry/telemetry.md create mode 100644 docs/communication/emails/campaigns/src/types/campaign.types.md create mode 100644 docs/communication/emails/campaigns/src/workflow/workflow.md create mode 100644 docs/communication/emails/delivery-tracking/README.md create mode 100644 docs/communication/emails/delivery-tracking/src/core/aggregator/aggregator.md create mode 100644 docs/communication/emails/delivery-tracking/src/core/tracker/tracker.md create mode 100644 docs/communication/emails/delivery-tracking/src/core/tracker/tracker.schemas.md create mode 100644 docs/communication/emails/delivery-tracking/src/core/tracking-link/tracking-link.md create mode 100644 docs/communication/emails/delivery-tracking/src/core/tracking-pixel/token-codec.md create mode 100644 docs/communication/emails/delivery-tracking/src/core/tracking-pixel/tracking-pixel.md create mode 100644 docs/communication/emails/delivery-tracking/src/core/webhook-parser/webhook-parser.md create mode 100644 docs/communication/emails/delivery-tracking/src/errors/delivery-tracking-error.md create mode 100644 docs/communication/emails/delivery-tracking/src/otel/instruments.md create mode 100644 docs/communication/emails/delivery-tracking/src/stores/memory/memory-store.md create mode 100644 docs/communication/emails/delivery-tracking/src/stores/surreal/surreal-store.md create mode 100644 docs/communication/emails/dmarc/README.md create mode 100644 docs/communication/emails/dmarc/src/decoders/gzip.md create mode 100644 docs/communication/emails/dmarc/src/decoders/xml.md create mode 100644 docs/communication/emails/dmarc/src/errors/dmarc-error.md create mode 100644 docs/communication/emails/dmarc/src/otel/dmarc-otel.md create mode 100644 docs/communication/emails/dmarc/src/parsers/aggregate.md create mode 100644 docs/communication/emails/dmarc/src/parsers/forensic.md create mode 100644 docs/communication/emails/domain-normalizer/README.md create mode 100644 docs/communication/emails/domain-normalizer/src/core/aliases/aliases.md create mode 100644 docs/communication/emails/domain-normalizer/src/core/matcher/matcher.md create mode 100644 docs/communication/emails/domain-normalizer/src/core/normalizer/normalizer.md create mode 100644 docs/communication/emails/domain-normalizer/src/errors/domain-normalizer-error.md create mode 100644 docs/communication/emails/domain-normalizer/src/types/domain-normalizer.md create mode 100644 docs/communication/emails/domain-normalizer/src/types/domain-normalizer.types.md create mode 100644 docs/communication/emails/email-processing/README.md create mode 100644 docs/communication/emails/email-processing/src/attachment-processor/attachment-processor.md create mode 100644 docs/communication/emails/email-processing/src/calendar-parser/calendar-parser.md create mode 100644 docs/communication/emails/email-processing/src/cid-resolver/cid-resolver.md create mode 100644 docs/communication/emails/email-processing/src/data-extractor/data-extractor.md create mode 100644 docs/communication/emails/email-processing/src/dkim-canonicalize/dkim-canonicalize.md create mode 100644 docs/communication/emails/email-processing/src/dkim-verifier/dkim-verifier.md create mode 100644 docs/communication/emails/email-processing/src/dmarc-checker/dmarc-checker.md create mode 100644 docs/communication/emails/email-processing/src/error-codes/error-codes.md create mode 100644 docs/communication/emails/email-processing/src/hooks/hooks.md create mode 100644 docs/communication/emails/email-processing/src/mime-utils/mime-utils.md create mode 100644 docs/communication/emails/email-processing/src/parser/parser.md create mode 100644 docs/communication/emails/email-processing/src/spam-scorer/spam-scorer.md create mode 100644 docs/communication/emails/email-processing/src/spf-checker/spf-checker.md create mode 100644 docs/communication/emails/email-processing/src/telemetry/telemetry.md create mode 100644 docs/communication/emails/email-processing/src/thread-grouper/thread-grouper.md create mode 100644 docs/communication/emails/email-templates/README.md create mode 100644 docs/communication/emails/email-templates/src/components/email-button/email-button.md create mode 100644 docs/communication/emails/email-templates/src/components/email-container/email-container.md create mode 100644 docs/communication/emails/email-templates/src/components/email-divider/email-divider.md create mode 100644 docs/communication/emails/email-templates/src/components/email-footer/email-footer.md create mode 100644 docs/communication/emails/email-templates/src/components/email-heading/email-heading.md create mode 100644 docs/communication/emails/email-templates/src/components/email-image/email-image.md create mode 100644 docs/communication/emails/email-templates/src/components/email-layout/email-layout.md create mode 100644 docs/communication/emails/email-templates/src/components/email-link/email-link.md create mode 100644 docs/communication/emails/email-templates/src/components/email-text/email-text.md create mode 100644 docs/communication/emails/email-templates/src/error-codes/error-codes.md create mode 100644 docs/communication/emails/email-templates/src/message/message.md create mode 100644 docs/communication/emails/email-templates/src/renderer/renderer.md create mode 100644 docs/communication/emails/email-templates/src/telemetry/telemetry.md create mode 100644 docs/communication/emails/email-templates/src/template-builder/template-builder.md create mode 100644 docs/communication/emails/email-templates/src/template-registry/template-registry.md create mode 100644 docs/communication/emails/email-templates/src/templates/invoice/invoice.md create mode 100644 docs/communication/emails/email-templates/src/templates/notification/notification.md create mode 100644 docs/communication/emails/email-templates/src/templates/password-reset/password-reset.md create mode 100644 docs/communication/emails/email-templates/src/templates/verification/verification.md create mode 100644 docs/communication/emails/email-templates/src/templates/welcome/welcome.md create mode 100644 docs/communication/emails/email-templates/src/theme/theme.md create mode 100644 docs/communication/emails/email-templates/src/vnode/vnode.md create mode 100644 docs/communication/emails/emailer/README.md create mode 100644 docs/communication/emails/emailer/src/core/email-service/base-email-transport.md create mode 100644 docs/communication/emails/emailer/src/core/email-service/email-service.md create mode 100644 docs/communication/emails/emailer/src/core/retry/retry.md create mode 100644 docs/communication/emails/emailer/src/core/validate/validate.md create mode 100644 docs/communication/emails/emailer/src/error-codes/error-codes.md create mode 100644 docs/communication/emails/emailer/src/fakes/fake-fetch.md create mode 100644 docs/communication/emails/emailer/src/fakes/fake-smtp-client.md create mode 100644 docs/communication/emails/emailer/src/otel/metrics.md create mode 100644 docs/communication/emails/emailer/src/schemas/schemas.md create mode 100644 docs/communication/emails/emailer/src/transports/dummy/dummy-transport.md create mode 100644 docs/communication/emails/emailer/src/transports/gmail-rest/gmail-rest-transport.md create mode 100644 docs/communication/emails/emailer/src/transports/smtp/smtp-client-like.types.md create mode 100644 docs/communication/emails/emailer/src/transports/smtp/smtp-transport.md create mode 100644 docs/communication/emails/emailer/src/types/emailer.types.md create mode 100644 docs/communication/emails/suppression/README.md create mode 100644 docs/communication/emails/suppression/src/core/exporter/csv-exporter.md create mode 100644 docs/communication/emails/suppression/src/core/exporter/json-exporter.md create mode 100644 docs/communication/emails/suppression/src/core/importer/csv-importer.md create mode 100644 docs/communication/emails/suppression/src/core/store/suppression-store.md create mode 100644 docs/communication/emails/suppression/src/errors/suppression-error.md create mode 100644 docs/communication/emails/suppression/src/types/suppression.types.md create mode 100644 docs/communication/emails/suppression/src/utils/email-utils.md create mode 100644 docs/communication/messaging/README.md create mode 100644 docs/communication/messaging/_intro.md create mode 100644 docs/communication/messaging/discord-client/README.md create mode 100644 docs/communication/messaging/discord-client/src/core/bot-client/discord-bot-client.md create mode 100644 docs/communication/messaging/discord-client/src/core/webhook/discord-webhook.md create mode 100644 docs/communication/messaging/discord-client/src/errors/discord-client-error.md create mode 100644 docs/communication/messaging/discord-client/src/types/discord-client.types.md create mode 100644 docs/communication/messaging/discord-client/src/utils/http.md create mode 100644 docs/communication/messaging/discord-client/src/utils/rate-limit.md create mode 100644 docs/communication/messaging/imessage-adapter/README.md create mode 100644 docs/communication/messaging/imessage-adapter/src/adapter/imessage-adapter.md create mode 100644 docs/communication/messaging/imessage-adapter/src/error-codes/error-codes.md create mode 100644 docs/communication/messaging/imessage-adapter/src/fixtures/chat-db-fixture.md create mode 100644 docs/communication/messaging/imessage-adapter/src/otel/metrics.md create mode 100644 docs/communication/messaging/imessage-adapter/src/parser/imessage-parser.md create mode 100644 docs/communication/messaging/imessage-adapter/src/schemas/schemas.md create mode 100644 docs/communication/messaging/imessage-adapter/src/sqlite/bun-sqlite-reader.md create mode 100644 docs/communication/messaging/imessage-adapter/src/watcher/imessage-watcher.md create mode 100644 docs/communication/messaging/notification-channel/README.md create mode 100644 docs/communication/messaging/notification-channel/src/channels/delivery-channel.md create mode 100644 docs/communication/messaging/notification-channel/src/channels/email-channel.md create mode 100644 docs/communication/messaging/notification-channel/src/channels/in-app-channel.md create mode 100644 docs/communication/messaging/notification-channel/src/channels/push-channel.md create mode 100644 docs/communication/messaging/notification-channel/src/channels/sms-channel.md create mode 100644 docs/communication/messaging/notification-channel/src/channels/webhook-channel.md create mode 100644 docs/communication/messaging/notification-channel/src/digest/digest-channel.md create mode 100644 docs/communication/messaging/notification-channel/src/error-codes/error-codes.md create mode 100644 docs/communication/messaging/notification-channel/src/error-mapping/error-mapping.md create mode 100644 docs/communication/messaging/notification-channel/src/fakes/fake-fetch.md create mode 100644 docs/communication/messaging/notification-channel/src/hooks/hooks.md create mode 100644 docs/communication/messaging/notification-channel/src/otel/metrics.md create mode 100644 docs/communication/messaging/notification-channel/src/preferences/preference-manager.md create mode 100644 docs/communication/messaging/notification-channel/src/rate-limiter/channel-rate-limiter.md create mode 100644 docs/communication/messaging/notification-channel/src/retry/delivery-retry.md create mode 100644 docs/communication/messaging/notification-channel/src/router/notification-router.md create mode 100644 docs/communication/messaging/notification-channel/src/scheduler/notification-scheduler.md create mode 100644 docs/communication/messaging/notification-channel/src/schemas/schemas.md create mode 100644 docs/communication/messaging/notification-channel/src/templates/template-engine.md create mode 100644 docs/communication/messaging/slack-client/README.md create mode 100644 docs/communication/messaging/slack-client/src/client/classify.md create mode 100644 docs/communication/messaging/slack-client/src/client/retry-after.md create mode 100644 docs/communication/messaging/slack-client/src/client/slack-api-client.md create mode 100644 docs/communication/messaging/slack-client/src/error-codes/error-codes.md create mode 100644 docs/communication/messaging/slack-client/src/fakes/fake-fetch.md create mode 100644 docs/communication/messaging/slack-client/src/otel/metrics.md create mode 100644 docs/communication/messaging/slack-client/src/schemas/schemas.md create mode 100644 docs/communication/messaging/slack-client/src/webhook/slack-webhook.md create mode 100644 docs/communication/messaging/sms-providers/README.md create mode 100644 docs/communication/messaging/sms-providers/src/aws-sns/aws-sns.md create mode 100644 docs/communication/messaging/sms-providers/src/aws-sns/sigv4.md create mode 100644 docs/communication/messaging/sms-providers/src/crypto/default-hmac.md create mode 100644 docs/communication/messaging/sms-providers/src/error-codes/error-codes.md create mode 100644 docs/communication/messaging/sms-providers/src/http/http.md create mode 100644 docs/communication/messaging/sms-providers/src/keywords/keywords.md create mode 100644 docs/communication/messaging/sms-providers/src/messagebird/messagebird.md create mode 100644 docs/communication/messaging/sms-providers/src/otel/otel.md create mode 100644 docs/communication/messaging/sms-providers/src/plivo/plivo.md create mode 100644 docs/communication/messaging/sms-providers/src/registry/registry.md create mode 100644 docs/communication/messaging/sms-providers/src/twilio/twilio.md create mode 100644 docs/communication/messaging/sms-providers/src/types/provider.md create mode 100644 docs/communication/messaging/sms-providers/src/vonage/vonage.md create mode 100644 docs/communication/messaging/sms/README.md create mode 100644 docs/communication/messaging/sms/src/delivery-tracker/delivery-tracker.md create mode 100644 docs/communication/messaging/sms/src/error-codes/error-codes.md create mode 100644 docs/communication/messaging/sms/src/in-memory-provider/in-memory-provider.md create mode 100644 docs/communication/messaging/sms/src/legacy-errors/legacy-errors.md create mode 100644 docs/communication/messaging/sms/src/legacy-metadata/legacy-metadata.md create mode 100644 docs/communication/messaging/sms/src/opt-out/opt-out.md create mode 100644 docs/communication/messaging/sms/src/otel/metrics.md create mode 100644 docs/communication/messaging/sms/src/rate-limiter/rate-limiter.md create mode 100644 docs/communication/messaging/sms/src/retry/retry.md create mode 100644 docs/communication/messaging/sms/src/routes/problem-json.md create mode 100644 docs/communication/messaging/sms/src/scheduler/scheduler.md create mode 100644 docs/communication/messaging/sms/src/schemas/schemas.md create mode 100644 docs/communication/messaging/sms/src/service/bus-map.md create mode 100644 docs/communication/messaging/sms/src/service/legacy-emitter.md create mode 100644 docs/communication/messaging/sms/src/service/sms-service.md create mode 100644 docs/communication/messaging/sms/src/templates/templates.md create mode 100644 docs/communication/messaging/sms/src/types/sms.types.md create mode 100644 docs/communication/messaging/sms/src/validation/phone.md create mode 100644 docs/communication/messaging/telegram-client/README.md create mode 100644 docs/communication/messaging/telegram-client/src/core/telegram-bot-client/telegram-bot-client.md create mode 100644 docs/communication/messaging/telegram-client/src/errors/telegram-client-error.md create mode 100644 docs/communication/messaging/telegram-client/src/types/telegram-bot-config.md create mode 100644 docs/communication/messaging/telegram-client/src/types/telegram-client.types.md create mode 100644 docs/communication/messaging/telegram-client/src/utils/build-bodies.md create mode 100644 docs/communication/messaging/telegram-client/src/utils/classify-error.md create mode 100644 docs/communication/webhook-client/README.md create mode 100644 docs/communication/webhook-client/_intro.md create mode 100644 docs/communication/webhook-client/webhook-client/README.md create mode 100644 docs/communication/webhook-client/webhook-client/src/core/client/webhook-client.md create mode 100644 docs/communication/webhook-client/webhook-client/src/core/delivery/webhook-delivery.md create mode 100644 docs/communication/webhook-client/webhook-client/src/errors/webhook-client-error.md create mode 100644 docs/communication/webhook-client/webhook-client/src/types/webhook-client.types.md create mode 100644 docs/communication/webhook-client/webhook-client/src/utils/payload-builder.md create mode 100644 docs/communication/webhook-client/webhook-client/src/utils/signature.md create mode 100644 docs/devtools/README.md create mode 100644 docs/devtools/_intro.md create mode 100644 docs/devtools/docker/README.md create mode 100644 docs/devtools/docker/_intro.md create mode 100644 docs/devtools/docker/docker-nvidia/README.md create mode 100644 docs/devtools/docs/README.md create mode 100644 docs/devtools/docs/_intro.md create mode 100644 docs/devtools/docs/compress-svg/README.md create mode 100644 docs/devtools/docs/compress-svg/src/core/compress-svg/compress-svg.md create mode 100644 docs/devtools/docs/compress-svg/src/parser/svg/svg.md create mode 100644 docs/devtools/docs/compress-svg/src/plugins/cleanup-attrs/cleanup-attrs.md create mode 100644 docs/devtools/docs/compress-svg/src/plugins/collapse-groups/collapse-groups.md create mode 100644 docs/devtools/docs/compress-svg/src/plugins/convert-path-data/convert-path-data.md create mode 100644 docs/devtools/docs/compress-svg/src/plugins/convert-transforms/convert-transforms.md create mode 100644 docs/devtools/docs/compress-svg/src/plugins/mangle-ids/mangle-ids.md create mode 100644 docs/devtools/docs/compress-svg/src/plugins/remove-comments/remove-comments.md create mode 100644 docs/devtools/docs/compress-svg/src/plugins/remove-doctype/remove-doctype.md create mode 100644 docs/devtools/docs/compress-svg/src/plugins/remove-metadata/remove-metadata.md create mode 100644 docs/devtools/docs/compress-svg/src/types/common.md create mode 100644 docs/devtools/docs/docs/README.md create mode 100644 docs/devtools/docs/docs/src/discovery/discover.md create mode 100644 docs/devtools/docs/docs/src/errors/errors.md create mode 100644 docs/devtools/docs/docs/src/graph/build-graph.md create mode 100644 docs/devtools/docs/docs/src/graph/find-orphans.md create mode 100644 docs/devtools/docs/docs/src/hierarchy/build-hierarchy.md create mode 100644 docs/devtools/docs/docs/src/observability/observability.md create mode 100644 docs/devtools/docs/docs/src/parser/parse.md create mode 100644 docs/devtools/docs/docs/src/search/search.md create mode 100644 docs/devtools/docs/docs/src/types/docs.types.md create mode 100644 docs/devtools/docs/pdf/README.md create mode 100644 docs/devtools/docs/pdf/src/colors/colors.md create mode 100644 docs/devtools/docs/pdf/src/content-stream/content-stream.md create mode 100644 docs/devtools/docs/pdf/src/divider-element/divider-element.md create mode 100644 docs/devtools/docs/pdf/src/document-builder/document-builder.md create mode 100644 docs/devtools/docs/pdf/src/error-codes/error-codes.md create mode 100644 docs/devtools/docs/pdf/src/image-element/image-element.md create mode 100644 docs/devtools/docs/pdf/src/image-registry/image-registry.md create mode 100644 docs/devtools/docs/pdf/src/layout-engine/layout-engine.md create mode 100644 docs/devtools/docs/pdf/src/pdf-writer/pdf-writer.md create mode 100644 docs/devtools/docs/pdf/src/render-pipeline/render-pipeline.md create mode 100644 docs/devtools/docs/pdf/src/renderer/renderer.md create mode 100644 docs/devtools/docs/pdf/src/schemas/schemas.md create mode 100644 docs/devtools/docs/pdf/src/style-resolver/style-resolver.md create mode 100644 docs/devtools/docs/pdf/src/table-element/table-element.md create mode 100644 docs/devtools/docs/pdf/src/telemetry/telemetry.md create mode 100644 docs/devtools/docs/pdf/src/templates/invoice-template/invoice-template.md create mode 100644 docs/devtools/docs/pdf/src/templates/receipt-template/receipt-template.md create mode 100644 docs/devtools/docs/pdf/src/templates/report-template/report-template.md create mode 100644 docs/devtools/docs/pdf/src/text-element/text-element.md create mode 100644 docs/devtools/docs/pdf/src/types/page-size.md create mode 100644 docs/devtools/docs/pdf/src/units/units.md create mode 100644 docs/devtools/docs/sitemap/README.md create mode 100644 docs/devtools/docs/sitemap/src/core/builder/sitemap-builder.md create mode 100644 docs/devtools/docs/sitemap/src/core/index-builder/index-builder.md create mode 100644 docs/devtools/docs/sitemap/src/core/parser/sitemap-parser.md create mode 100644 docs/devtools/docs/sitemap/src/errors/sitemap-error.md create mode 100644 docs/devtools/docs/sitemap/src/schemas/sitemap.schema.md create mode 100644 docs/devtools/docs/sitemap/src/utils/url-utils.md create mode 100644 docs/devtools/tooling/README.md create mode 100644 docs/devtools/tooling/_intro.md create mode 100644 docs/devtools/tooling/cli/README.md create mode 100644 docs/devtools/tooling/cli/src/app/app.md create mode 100644 docs/devtools/tooling/cli/src/command/command.md create mode 100644 docs/devtools/tooling/cli/src/errors/errors.md create mode 100644 docs/devtools/tooling/cli/src/output/format/format.md create mode 100644 docs/devtools/tooling/cli/src/output/table/table.md create mode 100644 docs/devtools/tooling/cli/src/parser/parser.md create mode 100644 docs/devtools/tooling/cli/src/progress/progress.md create mode 100644 docs/devtools/tooling/cli/src/prompt/prompt.md create mode 100644 docs/devtools/tooling/cli/src/spinner/spinner.md create mode 100644 docs/devtools/tooling/cli/src/style/style.md create mode 100644 docs/devtools/tooling/electrobun/README.md create mode 100644 docs/devtools/tooling/electrobun/src/bin/suaveplan-electrobun.md create mode 100644 docs/devtools/tooling/electrobun/src/cli/cli.md create mode 100644 docs/devtools/tooling/electrobun/src/config/config.md create mode 100644 docs/devtools/tooling/electrobun/src/error-codes/error-codes.md create mode 100644 docs/devtools/tooling/electrobun/src/fs/fs.md create mode 100644 docs/devtools/tooling/electrobun/src/generator/generator.md create mode 100644 docs/devtools/tooling/electrobun/src/icons/icons.md create mode 100644 docs/devtools/tooling/electrobun/src/prompts/prompts.md create mode 100644 docs/devtools/tooling/electrobun/src/runner/runner.md create mode 100644 docs/devtools/tooling/electrobun/src/schemas/schemas.md create mode 100644 docs/devtools/tooling/electrobun/src/telemetry/telemetry.md create mode 100644 docs/devtools/tooling/electrobun/src/templates/features.md create mode 100644 docs/devtools/tooling/electrobun/src/templates/templates.md create mode 100644 docs/devtools/tooling/electrobun/src/types/electrobun.types.md create mode 100644 docs/devtools/tooling/install-agent-skills/README.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/ab-testing/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/api-schemas/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/audit-logging/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/auth/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/barcode/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/bitpacker/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/bytes/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/cache/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/cli/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/compress-image/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/compress-svg/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/config/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/crdt/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/crypto-browser/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/crypto-cipher/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/crypto-curve/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/crypto-hash/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/crypto-keys/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/crypto-sodium/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/crypto-utils/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/crypto-vault/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/crypto/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/data-masking/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/datetime/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/db-sqlite/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/db/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/dedup/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/diff/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/dmarc/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/domain-normalizer/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/env/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/error/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/etl/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/event-sourcing/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/events-metrics/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/events-otel/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/events-schema/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/events-transport/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/events/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/exif/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/feature-flags/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/font-compress/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/font-convert/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/font-subset/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/fsm/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/i18n/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/idempotency/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/json/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/jwt-tenant/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/locale-data/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/logger/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/metadata/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/migration/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/mime/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/noise/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/oauth-client/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/opentelemetry/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/pagination/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/password-formats/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/permissions/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/pick-plugins/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/pseudo-random/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/qrcode/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/queue/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/random/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/rate-limiter/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/readline/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/retry/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/schema-registry/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/search/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/security-codes/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/serialize/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/sitemap/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/slsa/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/storage-s3/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/storage/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/streams/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/suppression/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/surrealdb/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/templates/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/testing-dom/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/testing-e2e/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/testing-integration-garage-s3/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/testing-integration-mailpit/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/testing-integration-postgres/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/testing-integration-redis/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/testing-integration-surrealdb/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/testing-integration-typesense/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/testing-integration/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/testing/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/timing/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/types/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/typescript-config/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/undo/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/utils/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/validation/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/assets/skills/webhook-client/SKILL.md create mode 100644 docs/devtools/tooling/install-agent-skills/src/apply/apply.md create mode 100644 docs/devtools/tooling/install-agent-skills/src/detect/detect.md create mode 100644 docs/devtools/tooling/install-agent-skills/src/error-codes.md create mode 100644 docs/devtools/tooling/install-agent-skills/src/manifest-loader.md create mode 100644 docs/devtools/tooling/install-agent-skills/src/plan/plan.md create mode 100644 docs/devtools/tooling/install-agent-skills/src/plugin/plugin.md create mode 100644 docs/devtools/tooling/install-agent-skills/src/post-install/post-install.md create mode 100644 docs/devtools/tooling/install-agent-skills/src/prompts/prompts.md create mode 100644 docs/devtools/tooling/install-agent-skills/src/types/answers.types.md create mode 100644 docs/devtools/tooling/installer/README.md create mode 100644 docs/devtools/tooling/installer/src/bin/suaveplan-install.md create mode 100644 docs/devtools/tooling/installer/src/error-codes.md create mode 100644 docs/devtools/tooling/installer/src/errors/errors.md create mode 100644 docs/devtools/tooling/installer/src/fs/disk-fs.md create mode 100644 docs/devtools/tooling/installer/src/fs/installer-fs.md create mode 100644 docs/devtools/tooling/installer/src/fs/memory-fs.md create mode 100644 docs/devtools/tooling/installer/src/host/apply/apply.md create mode 100644 docs/devtools/tooling/installer/src/host/apply/conflict.md create mode 100644 docs/devtools/tooling/installer/src/host/apply/json-merge.md create mode 100644 docs/devtools/tooling/installer/src/host/apply/text-patch.md create mode 100644 docs/devtools/tooling/installer/src/host/detect.md create mode 100644 docs/devtools/tooling/installer/src/host/host.md create mode 100644 docs/devtools/tooling/installer/src/host/plan.md create mode 100644 docs/devtools/tooling/installer/src/host/post-install.md create mode 100644 docs/devtools/tooling/installer/src/host/prompts.md create mode 100644 docs/devtools/tooling/installer/src/manifest/discover.md create mode 100644 docs/devtools/tooling/installer/src/manifest/manifest.md create mode 100644 docs/devtools/tooling/installer/src/testing/installer-fs.test-helpers.md create mode 100644 docs/devtools/tooling/installer/src/testing/run-plugin.md create mode 100644 docs/devtools/tooling/installer/src/testing/script-cli.md create mode 100644 docs/devtools/tooling/installer/src/types/file-op.types.md create mode 100644 docs/devtools/tooling/installer/src/types/installer.types.md create mode 100644 docs/devtools/tooling/javy-cli-darwin-arm64/README.md create mode 100644 docs/devtools/tooling/javy-cli-darwin-arm64/src/index.md create mode 100644 docs/devtools/tooling/javy-cli-darwin-x64/README.md create mode 100644 docs/devtools/tooling/javy-cli-darwin-x64/src/index.md create mode 100644 docs/devtools/tooling/javy-cli-linux-arm64/README.md create mode 100644 docs/devtools/tooling/javy-cli-linux-arm64/src/index.md create mode 100644 docs/devtools/tooling/javy-cli-linux-x64/README.md create mode 100644 docs/devtools/tooling/javy-cli-linux-x64/src/index.md create mode 100644 docs/devtools/tooling/javy-cli-win32-x64/README.md create mode 100644 docs/devtools/tooling/javy-cli-win32-x64/src/index.md create mode 100644 docs/devtools/tooling/linter/README.md create mode 100644 docs/devtools/tooling/linter/src/bin.md create mode 100644 docs/devtools/tooling/linter/src/biome-runner/biome-runner.md create mode 100644 docs/devtools/tooling/linter/src/cli/cli.md create mode 100644 docs/devtools/tooling/linter/src/error-codes/error-codes.md create mode 100644 docs/devtools/tooling/linter/src/glob-resolver/glob-resolver.md create mode 100644 docs/devtools/tooling/linter/src/markdown-fixer/markdown-fixer.md create mode 100644 docs/devtools/tooling/linter/src/markdown-fixer/rules.md create mode 100644 docs/devtools/tooling/linter/src/telemetry/telemetry.md create mode 100644 docs/devtools/tooling/linter/src/types/linter.types.md create mode 100644 docs/devtools/tooling/linter/src/unified-lint/unified-lint.md create mode 100644 docs/devtools/tooling/mcp/README.md create mode 100644 docs/devtools/tooling/mcp/src/client/mcp-client/mcp-client.md create mode 100644 docs/devtools/tooling/mcp/src/error-codes/error-codes.md create mode 100644 docs/devtools/tooling/mcp/src/events/events.md create mode 100644 docs/devtools/tooling/mcp/src/jsonrpc/dispatcher/dispatcher.md create mode 100644 docs/devtools/tooling/mcp/src/schemas/schemas.md create mode 100644 docs/devtools/tooling/mcp/src/server/mcp-server/mcp-server.md create mode 100644 docs/devtools/tooling/mcp/src/telemetry/telemetry.md create mode 100644 docs/devtools/tooling/mcp/src/transport/http-sse/http-sse.md create mode 100644 docs/devtools/tooling/mcp/src/transport/in-memory/in-memory.md create mode 100644 docs/devtools/tooling/mcp/src/transport/stdio/stdio.md create mode 100644 docs/devtools/tooling/mcp/src/transport/transport/transport.md create mode 100644 docs/devtools/tooling/mcp/src/types/types.md create mode 100644 docs/devtools/tooling/overview/README.md create mode 100644 docs/devtools/tooling/overview/src/discover/discover.md create mode 100644 docs/devtools/tooling/overview/src/errors/errors.md create mode 100644 docs/devtools/tooling/overview/src/graph/graph.md create mode 100644 docs/devtools/tooling/overview/src/rollups/rollups.md create mode 100644 docs/devtools/tooling/overview/src/schemas/schemas.md create mode 100644 docs/devtools/tooling/overview/src/telemetry/telemetry.md create mode 100644 docs/devtools/tooling/overview/src/tier/tier.md create mode 100644 docs/devtools/tooling/overview/src/types/types.md create mode 100644 docs/devtools/tooling/profiler/README.md create mode 100644 docs/devtools/tooling/profiler/src/bottleneck/bottleneck.md create mode 100644 docs/devtools/tooling/profiler/src/comparison/comparison.md create mode 100644 docs/devtools/tooling/profiler/src/error-codes/error-codes.md create mode 100644 docs/devtools/tooling/profiler/src/flamegraph/flamegraph.md create mode 100644 docs/devtools/tooling/profiler/src/memory/memory.md create mode 100644 docs/devtools/tooling/profiler/src/otel/otel.md create mode 100644 docs/devtools/tooling/profiler/src/profiler/profiler.md create mode 100644 docs/devtools/tooling/profiler/src/reporter/reporter.md create mode 100644 docs/devtools/tooling/profiler/src/sampler/sampler.md create mode 100644 docs/devtools/tooling/profiler/src/telemetry/telemetry.md create mode 100644 docs/devtools/tooling/profiler/src/types/profiler.types.md create mode 100644 docs/devtools/tooling/readline/README.md create mode 100644 docs/devtools/tooling/readline/src/errors/errors.md create mode 100644 docs/devtools/tooling/readline/src/interface/interface.md create mode 100644 docs/devtools/tooling/readline/src/reader/reader.md create mode 100644 docs/devtools/tooling/readline/src/scanner/scanner.md create mode 100644 docs/devtools/tooling/sandbox/README.md create mode 100644 docs/devtools/tooling/sandbox/src/audit-logger/audit-logger.md create mode 100644 docs/devtools/tooling/sandbox/src/code-transformer/code-transformer.md create mode 100644 docs/devtools/tooling/sandbox/src/error-codes/error-codes.md create mode 100644 docs/devtools/tooling/sandbox/src/isolate-engine/isolate-engine.md create mode 100644 docs/devtools/tooling/sandbox/src/module-resolver/module-resolver.md create mode 100644 docs/devtools/tooling/sandbox/src/pool/pool.md create mode 100644 docs/devtools/tooling/sandbox/src/resource-limiter/resource-limiter.md create mode 100644 docs/devtools/tooling/sandbox/src/result-streamer/result-streamer.md create mode 100644 docs/devtools/tooling/sandbox/src/sandbox/sandbox.md create mode 100644 docs/devtools/tooling/sandbox/src/schemas/schemas.md create mode 100644 docs/devtools/tooling/sandbox/src/spawn-engine/runner.md create mode 100644 docs/devtools/tooling/sandbox/src/spawn-engine/spawn-engine.md create mode 100644 docs/devtools/tooling/sandbox/src/telemetry/telemetry.md create mode 100644 docs/devtools/tooling/sandbox/src/vm-engine/vm-engine.md create mode 100644 docs/devtools/tooling/sandbox/src/worker-engine/worker-engine.md create mode 100644 docs/devtools/tooling/test-vite/README.md create mode 100644 docs/devtools/tooling/test-vite/src/browser-environment/browser-environment.md create mode 100644 docs/devtools/tooling/test-vite/src/bundle-size-snapshot/bundle-size-snapshot.md create mode 100644 docs/devtools/tooling/test-vite/src/error-codes/error-codes.md create mode 100644 docs/devtools/tooling/test-vite/src/hmr-tester/hmr-tester.md create mode 100644 docs/devtools/tooling/test-vite/src/matchers/matchers.md create mode 100644 docs/devtools/tooling/test-vite/src/port-allocator/port-allocator.md create mode 100644 docs/devtools/tooling/test-vite/src/telemetry/telemetry.md create mode 100644 docs/devtools/tooling/test-vite/src/tree-shake-validator/tree-shake-validator.md create mode 100644 docs/devtools/tooling/test-vite/src/types/test-vite.types.md create mode 100644 docs/devtools/tooling/test-vite/src/vite-app-config/vite-app-config.md create mode 100644 docs/devtools/tooling/test-vite/src/vite-library-config/vite-library-config.md create mode 100644 docs/devtools/tooling/test-vite/src/vitest-browser-config/vitest-browser-config.md create mode 100644 docs/devtools/tooling/test-vite/src/vitest-config/vitest-config.md create mode 100644 docs/foundation/README.md create mode 100644 docs/foundation/_intro.md create mode 100644 docs/foundation/barcode/README.md create mode 100644 docs/foundation/barcode/_intro.md create mode 100644 docs/foundation/barcode/barcode/README.md create mode 100644 docs/foundation/barcode/barcode/src/core/encoder/encoder.md create mode 100644 docs/foundation/barcode/barcode/src/core/validator/validator.md create mode 100644 docs/foundation/barcode/barcode/src/errors/barcode-error.md create mode 100644 docs/foundation/barcode/barcode/src/symbologies/code128.md create mode 100644 docs/foundation/barcode/barcode/src/symbologies/code39.md create mode 100644 docs/foundation/barcode/barcode/src/symbologies/ean13.md create mode 100644 docs/foundation/barcode/barcode/src/symbologies/ean8.md create mode 100644 docs/foundation/barcode/barcode/src/symbologies/itf.md create mode 100644 docs/foundation/barcode/barcode/src/symbologies/upca.md create mode 100644 docs/foundation/barcode/barcode/src/symbologies/upce.md create mode 100644 docs/foundation/barcode/barcode/src/types/barcode.types.md create mode 100644 docs/foundation/barcode/qrcode/README.md create mode 100644 docs/foundation/barcode/qrcode/src/core/encoder/data-encoder.md create mode 100644 docs/foundation/barcode/qrcode/src/core/mask/masking.md create mode 100644 docs/foundation/barcode/qrcode/src/core/matrix/matrix-builder.md create mode 100644 docs/foundation/barcode/qrcode/src/core/qrcode.md create mode 100644 docs/foundation/barcode/qrcode/src/core/reed-solomon/reed-solomon.md create mode 100644 docs/foundation/barcode/qrcode/src/core/renderer/svg-renderer.md create mode 100644 docs/foundation/barcode/qrcode/src/core/tables/tables.md create mode 100644 docs/foundation/barcode/qrcode/src/errors/qrcode-error.md create mode 100644 docs/foundation/barcode/qrcode/src/types/qrcode.types.md create mode 100644 docs/foundation/bitpacker/README.md create mode 100644 docs/foundation/bitpacker/_intro.md create mode 100644 docs/foundation/bitpacker/bitpacker-compressed/README.md create mode 100644 docs/foundation/bitpacker/bitpacker-compressed/src/adapters/deflate/deflate.md create mode 100644 docs/foundation/bitpacker/bitpacker-compressed/src/adapters/gzip/gzip.md create mode 100644 docs/foundation/bitpacker/bitpacker-compressed/src/adapters/none/none.md create mode 100644 docs/foundation/bitpacker/bitpacker-compressed/src/api/api.md create mode 100644 docs/foundation/bitpacker/bitpacker-compressed/src/compressed-bit-packer/compressed-bit-packer.md create mode 100644 docs/foundation/bitpacker/bitpacker-compressed/src/compressed-bit-packer/compressed-bit-packer.schema.md create mode 100644 docs/foundation/bitpacker/bitpacker-compressed/src/index.md create mode 100644 docs/foundation/bitpacker/bitpacker-compressed/src/otel/instruments.md create mode 100644 docs/foundation/bitpacker/bitpacker-compressed/src/register-schemas/register-schemas.md create mode 100644 docs/foundation/bitpacker/bitpacker-compressed/src/registry/registry.md create mode 100644 docs/foundation/bitpacker/bitpacker-compressed/src/rle/rle.md create mode 100644 docs/foundation/bitpacker/bitpacker-compressed/src/rle/rle.schema.md create mode 100644 docs/foundation/bitpacker/bitpacker-compressed/src/types/types.md create mode 100644 docs/foundation/bitpacker/bitpacker-compressed/src/types/types.schema.md create mode 100644 docs/foundation/bitpacker/bitpacker-crypto/README.md create mode 100644 docs/foundation/bitpacker/bitpacker-crypto/SUPERSEDED.md create mode 100644 docs/foundation/bitpacker/bitpacker-crypto/src/crc32.md create mode 100644 docs/foundation/bitpacker/bitpacker-crypto/src/encrypted/encrypted-bitschema.md create mode 100644 docs/foundation/bitpacker/bitpacker-crypto/src/envelope/envelope-schema.md create mode 100644 docs/foundation/bitpacker/bitpacker-crypto/src/fingerprint/schema-fingerprint.md create mode 100644 docs/foundation/bitpacker/bitpacker-crypto/src/hash-registry/hash-registry.md create mode 100644 docs/foundation/bitpacker/bitpacker-crypto/src/hashchain/hashchain-schema.md create mode 100644 docs/foundation/bitpacker/bitpacker-crypto/src/index.md create mode 100644 docs/foundation/bitpacker/bitpacker-crypto/src/multisigned/multisigned-bitschema.md create mode 100644 docs/foundation/bitpacker/bitpacker-crypto/src/signed/signed-bitschema.md create mode 100644 docs/foundation/bitpacker/bitpacker-crypto/src/xxhash32.md create mode 100644 docs/foundation/bitpacker/bitpacker-delta/README.md create mode 100644 docs/foundation/bitpacker/bitpacker-delta/src/delta-manager/delta-manager.md create mode 100644 docs/foundation/bitpacker/bitpacker-delta/src/delta-state/delta-state.md create mode 100644 docs/foundation/bitpacker/bitpacker-delta/src/index.md create mode 100644 docs/foundation/bitpacker/bitpacker-delta/src/string-diff.md create mode 100644 docs/foundation/bitpacker/bitpacker-delta/src/xor-encoder.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/README.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/bitpacker/bitpacker.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/index.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/integration-manager/integration-manager.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/interpolation/index.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/interpolation/interpolation.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/otel/instruments.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/prediction/index.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/prediction/kalman-filter.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/prediction/motion-math.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/prediction/position-predictor.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/prediction/prediction-algorithms.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/prediction/prediction.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/prediction/rotation-predictor.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/quantization/quantization.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/reconciliation/index.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/reconciliation/reconciliation.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/register-schemas/register-schemas.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/schema-factory/schema-factory.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/schemas/schemas.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/state-manager/state-manager.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/types.md create mode 100644 docs/foundation/bitpacker/bitpacker-game/src/types.schema/types.schema.md create mode 100644 docs/foundation/bitpacker/bitpacker-network/README.md create mode 100644 docs/foundation/bitpacker/bitpacker-network/src/defaults/default-clock.md create mode 100644 docs/foundation/bitpacker/bitpacker-network/src/defaults/default-rng.md create mode 100644 docs/foundation/bitpacker/bitpacker-network/src/defaults/defaults.md create mode 100644 docs/foundation/bitpacker/bitpacker-network/src/index.md create mode 100644 docs/foundation/bitpacker/bitpacker-network/src/otel/instruments.md create mode 100644 docs/foundation/bitpacker/bitpacker-network/src/register-schemas/register-schemas.md create mode 100644 docs/foundation/bitpacker/bitpacker-network/src/simulator/simulator.md create mode 100644 docs/foundation/bitpacker/bitpacker-network/src/simulator/simulator.schema.md create mode 100644 docs/foundation/bitpacker/bitpacker-network/src/types/types.md create mode 100644 docs/foundation/bitpacker/bitpacker-network/src/types/types.schema.md create mode 100644 docs/foundation/bitpacker/bitpacker-schema/README.md create mode 100644 docs/foundation/bitpacker/bitpacker-schema/src/index.md create mode 100644 docs/foundation/bitpacker/bitpacker-schema/src/matching/matching.md create mode 100644 docs/foundation/bitpacker/bitpacker-schema/src/migration/migration.md create mode 100644 docs/foundation/bitpacker/bitpacker-schema/src/registry/defaults/default-clock.md create mode 100644 docs/foundation/bitpacker/bitpacker-schema/src/registry/factories/factories.md create mode 100644 docs/foundation/bitpacker/bitpacker-schema/src/registry/registry.md create mode 100644 docs/foundation/bitpacker/bitpacker-schema/src/registry/storage/in-memory/in-memory.md create mode 100644 docs/foundation/bitpacker/bitpacker-schema/src/registry/storage/local-storage/local-storage.md create mode 100644 docs/foundation/bitpacker/bitpacker-schema/src/validation/validation.md create mode 100644 docs/foundation/bitpacker/bitpacker-schema/src/versioning/versioning.md create mode 100644 docs/foundation/bitpacker/bitpacker-schema/src/visualization/visualization.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/README.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/index.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/otel/instruments.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/register-default-strategies.schema/register-default-strategies.schema.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/register-default-strategies/register-default-strategies.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/register-schemas/register-schemas.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/array-config/array-config.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/array-notation/array-notation.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/array-schema/array-schema.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/array/array.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/bigint-array/bigint-array.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/bigint/bigint.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/bitarray/bitarray.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/bitset/bitset.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/blob/blob.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/boolean/boolean.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/conditional/conditional.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/customType/customType.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/datetime/datetime.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/defs/defs.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/enum/enum.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/map/map.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/null/null.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/number/number.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/object/object.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/oneOf/oneOf.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/optional-marker/optional-marker.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/optional-suffix/optional-suffix.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/optional/optional.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/set/set.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/string/string.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/union/union.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/varint/varint.md create mode 100644 docs/foundation/bitpacker/bitpacker-strategies/src/strategies/version/version.md create mode 100644 docs/foundation/bitpacker/bitpacker-streaming/README.md create mode 100644 docs/foundation/bitpacker/bitpacker-streaming/src/defaults/default-clock.md create mode 100644 docs/foundation/bitpacker/bitpacker-streaming/src/index.md create mode 100644 docs/foundation/bitpacker/bitpacker-streaming/src/otel/instruments.md create mode 100644 docs/foundation/bitpacker/bitpacker-streaming/src/register-schemas/register-schemas.md create mode 100644 docs/foundation/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.md create mode 100644 docs/foundation/bitpacker/bitpacker-streaming/src/streaming-bit-packer/streaming-bit-packer.schema.md create mode 100644 docs/foundation/bitpacker/bitpacker-streaming/src/transform/transform.md create mode 100644 docs/foundation/bitpacker/bitpacker-streaming/src/transform/transform.schema.md create mode 100644 docs/foundation/bitpacker/bitpacker-streaming/src/transform/transform.types.md create mode 100644 docs/foundation/bitpacker/bitpacker-validation/README.md create mode 100644 docs/foundation/bitpacker/bitpacker-validation/src/index.md create mode 100644 docs/foundation/bitpacker/bitpacker-validation/src/otel/instruments.md create mode 100644 docs/foundation/bitpacker/bitpacker-validation/src/register-schemas/register-schemas.md create mode 100644 docs/foundation/bitpacker/bitpacker-validation/src/safety/safety-checks.md create mode 100644 docs/foundation/bitpacker/bitpacker-validation/src/safety/safety-checks.schema.md create mode 100644 docs/foundation/bitpacker/bitpacker-validation/src/safety/safety.md create mode 100644 docs/foundation/bitpacker/bitpacker-validation/src/types.schema/types.schema.md create mode 100644 docs/foundation/bitpacker/bitpacker-validation/src/types/types.md create mode 100644 docs/foundation/bitpacker/bitpacker-validation/src/utils/utils.md create mode 100644 docs/foundation/bitpacker/bitpacker-validation/src/validation/find-array-length-errors.md create mode 100644 docs/foundation/bitpacker/bitpacker-validation/src/validation/find-extra-fields.md create mode 100644 docs/foundation/bitpacker/bitpacker-validation/src/validation/validate-data.md create mode 100644 docs/foundation/bitpacker/bitpacker-validation/src/validation/validation.md create mode 100644 docs/foundation/bitpacker/bitpacker-validation/src/validation/validator.md create mode 100644 docs/foundation/bitpacker/bitpacker/README.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/bit-reader/bit-reader.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/bit-reader/index.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/bit-schema.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/bit-writer/bit-writer.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/bit-writer/index.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/core/bitpacker.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/core/bitpacker.schema.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/core/safety/safety-checks.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/core/strategies/invalid.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/core/strategies/manager.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/core/strategies/types.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/core/strategies/types.schema.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/error-codes/error-codes.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/handlers/custom-type-registry.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/index.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/iterators/pack-iterator/pack-iterator.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/otel/instruments.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/packers/array/array-packer.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/packers/base/base-packer.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/packers/bigint-array/bigint-array-packer.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/packers/bigint/bigint-packer.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/packers/bit-array/bit-array-packer.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/packers/bit-operations/bit-operations.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/packers/boolean/boolean-packer.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/packers/datetime/datetime-packer.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/packers/enum/enum-packer.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/packers/float/float-packer.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/packers/index.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/packers/integer/integer-packer.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/packers/map/map-packer.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/packers/set/set-packer.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/packers/string/string-packer.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/packers/uuid/uuid-packer.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/packers/varint/varint-packer.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/performance/buffer-pool.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/performance/lru-cache.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/performance/performance-monitor.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/performance/performance.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/register-schemas/register-schemas.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/serialization/serialization.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/types.schema/types.schema.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/types/base-types.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/types/common.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/types/index.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/types/key-types.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/types/packer-types.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/types/schema-versioning-types.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/types/schemas.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/types/validation-types.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/utils/float-utils.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/utils/pack-bits.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/utils/schema-validators.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/utils/type-guards.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/utils/utils.md create mode 100644 docs/foundation/bitpacker/bitpacker/src/utils/zigzag.md create mode 100644 docs/foundation/core/README.md create mode 100644 docs/foundation/core/_intro.md create mode 100644 docs/foundation/core/config/README.md create mode 100644 docs/foundation/core/config/src/core/config-builder/config-builder.md create mode 100644 docs/foundation/core/config/src/core/config-store/config-store.md create mode 100644 docs/foundation/core/config/src/layers/cli-layer/cli-layer.md create mode 100644 docs/foundation/core/config/src/layers/defaults-layer/defaults-layer.md create mode 100644 docs/foundation/core/config/src/layers/env-layer/env-layer.md create mode 100644 docs/foundation/core/config/src/layers/file-layer/file-layer.md create mode 100644 docs/foundation/core/config/src/layers/object-layer/object-layer.md create mode 100644 docs/foundation/core/config/src/types/common.md create mode 100644 docs/foundation/core/config/src/types/schemas.md create mode 100644 docs/foundation/core/config/src/utils/mask.md create mode 100644 docs/foundation/core/config/src/utils/merge.md create mode 100644 docs/foundation/core/env/README.md create mode 100644 docs/foundation/core/env/src/core/create-env/create-env.md create mode 100644 docs/foundation/core/env/src/core/field/field.md create mode 100644 docs/foundation/core/env/src/core/validator/validator.md create mode 100644 docs/foundation/core/env/src/errors/env-error.md create mode 100644 docs/foundation/core/env/src/errors/error-codes.md create mode 100644 docs/foundation/core/env/src/fields/array-field/array-field.md create mode 100644 docs/foundation/core/env/src/fields/boolean-field/boolean-field.md create mode 100644 docs/foundation/core/env/src/fields/email-field/email-field.md create mode 100644 docs/foundation/core/env/src/fields/enum-field/enum-field.md create mode 100644 docs/foundation/core/env/src/fields/json-field/json-field.md create mode 100644 docs/foundation/core/env/src/fields/number-field/number-field.md create mode 100644 docs/foundation/core/env/src/fields/port-field/port-field.md create mode 100644 docs/foundation/core/env/src/fields/string-field/string-field.md create mode 100644 docs/foundation/core/env/src/fields/url-field/url-field.md create mode 100644 docs/foundation/core/env/src/loaders/dotenv/dotenv.md create mode 100644 docs/foundation/core/env/src/loaders/object/object.md create mode 100644 docs/foundation/core/env/src/presets/common/common.md create mode 100644 docs/foundation/core/env/src/presets/server/server.md create mode 100644 docs/foundation/core/env/src/schemas/env.schemas.md create mode 100644 docs/foundation/core/env/src/transforms/coerce/coerce.md create mode 100644 docs/foundation/core/env/src/types/common.md create mode 100644 docs/foundation/core/env/src/utils/interpolation.md create mode 100644 docs/foundation/core/error/README.md create mode 100644 docs/foundation/core/error/src/base/package-error.md create mode 100644 docs/foundation/core/error/src/base/suaveplan-error.md create mode 100644 docs/foundation/core/error/src/causes/walk-causes.md create mode 100644 docs/foundation/core/error/src/codes/define-codes.md create mode 100644 docs/foundation/core/error/src/codes/error-codes.md create mode 100644 docs/foundation/core/error/src/i18n/resolver.md create mode 100644 docs/foundation/core/error/src/otel/to-span-event.md create mode 100644 docs/foundation/core/error/src/redact/sensitive.md create mode 100644 docs/foundation/core/error/src/serialize/from-binary.md create mode 100644 docs/foundation/core/error/src/serialize/from-json.md create mode 100644 docs/foundation/core/error/src/serialize/to-binary.md create mode 100644 docs/foundation/core/error/src/serialize/to-json.md create mode 100644 docs/foundation/core/schema-registry/README.md create mode 100644 docs/foundation/core/schema-registry/src/core/compatibility/compatibility.md create mode 100644 docs/foundation/core/schema-registry/src/core/registry/schema-registry.md create mode 100644 docs/foundation/core/schema-registry/src/errors/schema-registry-error.md create mode 100644 docs/foundation/core/schema-registry/src/types/schema-registry.types.md create mode 100644 docs/foundation/core/types/README.md create mode 100644 docs/foundation/core/types/src/aead-ops.md create mode 100644 docs/foundation/core/types/src/authority.md create mode 100644 docs/foundation/core/types/src/chunk-presence.md create mode 100644 docs/foundation/core/types/src/chunk-ref.md create mode 100644 docs/foundation/core/types/src/chunk-source.md create mode 100644 docs/foundation/core/types/src/clock.md create mode 100644 docs/foundation/core/types/src/database-like.md create mode 100644 docs/foundation/core/types/src/dir-entry.md create mode 100644 docs/foundation/core/types/src/domain-tag.md create mode 100644 docs/foundation/core/types/src/drive-stats.md create mode 100644 docs/foundation/core/types/src/events-bus-like.md create mode 100644 docs/foundation/core/types/src/fetch-like/fetch-like.md create mode 100644 docs/foundation/core/types/src/framing.md create mode 100644 docs/foundation/core/types/src/hash-like.md create mode 100644 docs/foundation/core/types/src/health-status.md create mode 100644 docs/foundation/core/types/src/i18n-backend.md create mode 100644 docs/foundation/core/types/src/i18n-catalog.md create mode 100644 docs/foundation/core/types/src/id-generator.md create mode 100644 docs/foundation/core/types/src/key-status.md create mode 100644 docs/foundation/core/types/src/logger-like.md create mode 100644 docs/foundation/core/types/src/message-envelope.md create mode 100644 docs/foundation/core/types/src/message-resolver.md create mode 100644 docs/foundation/core/types/src/middleware.md create mode 100644 docs/foundation/core/types/src/network-plugin.md create mode 100644 docs/foundation/core/types/src/options.md create mode 100644 docs/foundation/core/types/src/peer-id.md create mode 100644 docs/foundation/core/types/src/pipeline-stage.md create mode 100644 docs/foundation/core/types/src/plugin.md create mode 100644 docs/foundation/core/types/src/rng.md create mode 100644 docs/foundation/core/types/src/source-hint.md create mode 100644 docs/foundation/core/types/src/storage-capabilities.md create mode 100644 docs/foundation/core/types/src/storage-like.md create mode 100644 docs/foundation/core/types/src/stream-transformer.md create mode 100644 docs/foundation/core/types/src/streaming-aead-engine.md create mode 100644 docs/foundation/core/types/src/timers-like.md create mode 100644 docs/foundation/core/types/src/transform-progress.md create mode 100644 docs/foundation/core/types/src/translation-record.md create mode 100644 docs/foundation/core/types/src/transport.md create mode 100644 docs/foundation/core/typescript-config/README.md create mode 100644 docs/foundation/core/utils/README.md create mode 100644 docs/foundation/core/utils/src/debug/debug.md create mode 100644 docs/foundation/core/utils/src/email/email.md create mode 100644 docs/foundation/core/utils/src/errors/utils-error.md create mode 100644 docs/foundation/core/utils/src/number/number.md create mode 100644 docs/foundation/core/utils/src/object/object.md create mode 100644 docs/foundation/core/utils/src/platform/platform.md create mode 100644 docs/foundation/core/utils/src/random/pseudo.md create mode 100644 docs/foundation/core/utils/src/sound/sound.md create mode 100644 docs/foundation/core/utils/src/string/string.md create mode 100644 docs/foundation/core/utils/src/types/types.md create mode 100644 docs/foundation/core/utils/src/validate/validate.md create mode 100644 docs/foundation/core/utils/src/validation/size.md create mode 100644 docs/foundation/data/README.md create mode 100644 docs/foundation/data/_intro.md create mode 100644 docs/foundation/data/bytes/README.md create mode 100644 docs/foundation/data/bytes/src/encoding/encoding.md create mode 100644 docs/foundation/data/bytes/src/errors/bytes-error.md create mode 100644 docs/foundation/data/bytes/src/types/types.md create mode 100644 docs/foundation/data/bytes/src/uint8/uint8.md create mode 100644 docs/foundation/data/bytes/src/uuid/uuid.md create mode 100644 docs/foundation/data/clipboard/README.md create mode 100644 docs/foundation/data/clipboard/src/errors/errors.md create mode 100644 docs/foundation/data/clipboard/src/fallback/fallback.md create mode 100644 docs/foundation/data/clipboard/src/manager/helpers.md create mode 100644 docs/foundation/data/clipboard/src/manager/manager.md create mode 100644 docs/foundation/data/clipboard/src/manager/operations.md create mode 100644 docs/foundation/data/clipboard/src/observability/observability.md create mode 100644 docs/foundation/data/clipboard/src/permissions/permissions.md create mode 100644 docs/foundation/data/clipboard/src/queue/queue.md create mode 100644 docs/foundation/data/clipboard/src/sanitizer/sanitizer.md create mode 100644 docs/foundation/data/clipboard/src/security/security.md create mode 100644 docs/foundation/data/clipboard/src/types/clipboard.types.md create mode 100644 docs/foundation/data/data-masking/README.md create mode 100644 docs/foundation/data/data-masking/src/core/masker/object-masker.md create mode 100644 docs/foundation/data/data-masking/src/errors/data-masking-error.md create mode 100644 docs/foundation/data/data-masking/src/schemas/mask-rule.schema.md create mode 100644 docs/foundation/data/data-masking/src/strategies/credit-card.md create mode 100644 docs/foundation/data/data-masking/src/strategies/email.md create mode 100644 docs/foundation/data/data-masking/src/strategies/full.md create mode 100644 docs/foundation/data/data-masking/src/strategies/hash.md create mode 100644 docs/foundation/data/data-masking/src/strategies/partial.md create mode 100644 docs/foundation/data/data-masking/src/strategies/phone.md create mode 100644 docs/foundation/data/data-masking/src/strategies/preserve-format.md create mode 100644 docs/foundation/data/data-masking/src/strategies/tokenize.md create mode 100644 docs/foundation/data/data-masking/src/types/mask-types.md create mode 100644 docs/foundation/data/data-masking/src/utils/path-matcher.md create mode 100644 docs/foundation/data/dedup/README.md create mode 100644 docs/foundation/data/dedup/src/core/engine/dedup-engine.md create mode 100644 docs/foundation/data/dedup/src/core/merge/merge-strategies.md create mode 100644 docs/foundation/data/dedup/src/core/scoring/similarity.md create mode 100644 docs/foundation/data/dedup/src/errors/dedup-error.md create mode 100644 docs/foundation/data/dedup/src/schemas/dedup.schema.md create mode 100644 docs/foundation/data/diff/README.md create mode 100644 docs/foundation/data/diff/src/diff/diff.md create mode 100644 docs/foundation/data/diff/src/errors/diff-error.md create mode 100644 docs/foundation/data/diff/src/history/history.md create mode 100644 docs/foundation/data/diff/src/operations/operations.md create mode 100644 docs/foundation/data/diff/src/patch/patch.md create mode 100644 docs/foundation/data/diff/src/path/path.md create mode 100644 docs/foundation/data/diff/src/sync/sync.md create mode 100644 docs/foundation/data/diff/src/utils/utils.md create mode 100644 docs/foundation/data/json/README.md create mode 100644 docs/foundation/data/json/src/errors/json-error.md create mode 100644 docs/foundation/data/json/src/safe-json/safe-json.md create mode 100644 docs/foundation/data/json/src/types/types.md create mode 100644 docs/foundation/data/media/README.md create mode 100644 docs/foundation/data/media/src/detection/detection.md create mode 100644 docs/foundation/data/media/src/errors/errors.md create mode 100644 docs/foundation/data/media/src/metadata/metadata.md create mode 100644 docs/foundation/data/media/src/observability/observability.md create mode 100644 docs/foundation/data/media/src/signatures/signatures.md create mode 100644 docs/foundation/data/media/src/types/media.types.md create mode 100644 docs/foundation/data/media/src/validation/validation.md create mode 100644 docs/foundation/data/mime/README.md create mode 100644 docs/foundation/data/mime/src/charset/sniff-bom.md create mode 100644 docs/foundation/data/mime/src/charset/sniff-html-meta.md create mode 100644 docs/foundation/data/mime/src/charset/sniff-xml-decl.md create mode 100644 docs/foundation/data/mime/src/content-type/content-type-equals.md create mode 100644 docs/foundation/data/mime/src/content-type/format-content-type.md create mode 100644 docs/foundation/data/mime/src/content-type/parse-content-type.md create mode 100644 docs/foundation/data/mime/src/db/builtin-db.md create mode 100644 docs/foundation/data/mime/src/db/registry.md create mode 100644 docs/foundation/data/mime/src/detection/detect.md create mode 100644 docs/foundation/data/mime/src/detection/from-content-type.md create mode 100644 docs/foundation/data/mime/src/detection/from-extension.md create mode 100644 docs/foundation/data/mime/src/detection/from-magic-bytes/from-magic-bytes.md create mode 100644 docs/foundation/data/mime/src/detection/from-magic-bytes/helpers.md create mode 100644 docs/foundation/data/mime/src/detection/from-magic-bytes/registry.md create mode 100644 docs/foundation/data/mime/src/detection/from-magic-bytes/signatures/archives.md create mode 100644 docs/foundation/data/mime/src/detection/from-magic-bytes/signatures/audio.md create mode 100644 docs/foundation/data/mime/src/detection/from-magic-bytes/signatures/data.md create mode 100644 docs/foundation/data/mime/src/detection/from-magic-bytes/signatures/documents.md create mode 100644 docs/foundation/data/mime/src/detection/from-magic-bytes/signatures/executables.md create mode 100644 docs/foundation/data/mime/src/detection/from-magic-bytes/signatures/fonts.md create mode 100644 docs/foundation/data/mime/src/detection/from-magic-bytes/signatures/images.md create mode 100644 docs/foundation/data/mime/src/detection/from-magic-bytes/signatures/model3d.md create mode 100644 docs/foundation/data/mime/src/detection/from-magic-bytes/signatures/video.md create mode 100644 docs/foundation/data/mime/src/detection/from-stream-reader.md create mode 100644 docs/foundation/data/mime/src/detection/from-stream.md create mode 100644 docs/foundation/data/mime/src/error-codes/error-codes.md create mode 100644 docs/foundation/data/mime/src/errors/insufficient-bytes-error.md create mode 100644 docs/foundation/data/mime/src/errors/invalid-content-type-error.md create mode 100644 docs/foundation/data/mime/src/errors/mime-error.md create mode 100644 docs/foundation/data/mime/src/errors/parse-error.md create mode 100644 docs/foundation/data/mime/src/errors/unknown-mime-type-error.md create mode 100644 docs/foundation/data/mime/src/errors/unknown-signature-error.md create mode 100644 docs/foundation/data/mime/src/legacy/get-mime-type.md create mode 100644 docs/foundation/data/mime/src/reverse/reverse.md create mode 100644 docs/foundation/data/mime/src/telemetry/meters.md create mode 100644 docs/foundation/data/packer-browser/README.md create mode 100644 docs/foundation/data/packer-browser/src/adaptive-cache/adaptive-cache.md create mode 100644 docs/foundation/data/packer-browser/src/cache/cache.md create mode 100644 docs/foundation/data/packer-browser/src/content-address/content-address.md create mode 100644 docs/foundation/data/packer-browser/src/diagnostics/diagnostics.md create mode 100644 docs/foundation/data/packer-browser/src/encrypted-archive/encrypted-archive.md create mode 100644 docs/foundation/data/packer-browser/src/error-codes/error-codes.md create mode 100644 docs/foundation/data/packer-browser/src/flags/flags.md create mode 100644 docs/foundation/data/packer-browser/src/i18n/messages.md create mode 100644 docs/foundation/data/packer-browser/src/keyring/keyring.md create mode 100644 docs/foundation/data/packer-browser/src/loader/loader-helpers.md create mode 100644 docs/foundation/data/packer-browser/src/loader/loader-stream.md create mode 100644 docs/foundation/data/packer-browser/src/loader/loader.md create mode 100644 docs/foundation/data/packer-browser/src/manager/manager-helpers.md create mode 100644 docs/foundation/data/packer-browser/src/manager/manager-stream.md create mode 100644 docs/foundation/data/packer-browser/src/manager/manager.md create mode 100644 docs/foundation/data/packer-browser/src/manager/tiny-emitter.md create mode 100644 docs/foundation/data/packer-browser/src/observability/observability.md create mode 100644 docs/foundation/data/packer-browser/src/prefetch/prefetch.md create mode 100644 docs/foundation/data/packer-browser/src/preload/preload.md create mode 100644 docs/foundation/data/packer-browser/src/range-response/range-response.md create mode 100644 docs/foundation/data/packer-browser/src/runtime/runtime.md create mode 100644 docs/foundation/data/packer-browser/src/service-worker/service-worker.md create mode 100644 docs/foundation/data/packer-browser/src/service-worker/sw-shim.md create mode 100644 docs/foundation/data/packer-browser/src/signature/signature.md create mode 100644 docs/foundation/data/packer-browser/src/singleton/singleton.md create mode 100644 docs/foundation/data/packer-browser/src/utils/cross-origin.md create mode 100644 docs/foundation/data/packer-browser/src/utils/register-service-worker.md create mode 100644 docs/foundation/data/packer-browser/test-results/content-address-content-ad-2a9c0-ndler-drops-outdated-caches-chromium/error-context.md create mode 100644 docs/foundation/data/packer-browser/test-results/diagnostics-diagnostics-ov-35ec4-mounts-and-unmounts-cleanly-chromium/error-context.md create mode 100644 docs/foundation/data/packer-browser/test-results/encrypted-encrypted-archiv-ad9c4-chive-and-yields-a-Blob-URL-chromium/error-context.md create mode 100644 docs/foundation/data/packer-browser/test-results/preload-preload-hint-injec-e29f5-d-elements-to-document-head-chromium/error-context.md create mode 100644 docs/foundation/data/packer-browser/test-results/range-packed-resource-SW-r-6f9d4-for-a-ranged-packed-request-chromium/error-context.md create mode 100644 docs/foundation/data/packer-browser/test-results/sw-packed-resource-SW-inte-a1bac-and-intercepts-a-packed-URL-chromium/error-context.md create mode 100644 docs/foundation/data/packer/README.md create mode 100644 docs/foundation/data/packer/src/abstract/abstract.md create mode 100644 docs/foundation/data/packer/src/chunked/codec/chunk.md create mode 100644 docs/foundation/data/packer/src/chunked/codec/header.md create mode 100644 docs/foundation/data/packer/src/chunked/crypto/aead.md create mode 100644 docs/foundation/data/packer/src/chunked/manifest/manifest.md create mode 100644 docs/foundation/data/packer/src/chunked/packer/packer.md create mode 100644 docs/foundation/data/packer/src/chunked/unpacker/unpacker.md create mode 100644 docs/foundation/data/packer/src/chunked/verifier/chunk-verifier.md create mode 100644 docs/foundation/data/packer/src/error-codes.md create mode 100644 docs/foundation/data/packer/src/flags/flags.md create mode 100644 docs/foundation/data/packer/src/i18n/messages.md create mode 100644 docs/foundation/data/packer/src/idempotency/idempotency.md create mode 100644 docs/foundation/data/packer/src/integrity/integrity.md create mode 100644 docs/foundation/data/packer/src/observability/observability.md create mode 100644 docs/foundation/data/packer/src/packer/packer.md create mode 100644 docs/foundation/data/packer/src/plugins/plugins.md create mode 100644 docs/foundation/data/packer/src/retry/retryable-read.md create mode 100644 docs/foundation/data/packer/src/runtime/runtime.md create mode 100644 docs/foundation/data/packer/src/schemas/registration.md create mode 100644 docs/foundation/data/packer/src/streaming/normalize-source.md create mode 100644 docs/foundation/data/packer/src/unpacker/unpacker.md create mode 100644 docs/foundation/data/pagination/README.md create mode 100644 docs/foundation/data/pagination/src/adapters/database-adapter.md create mode 100644 docs/foundation/data/pagination/src/cursor/cursor-pagination.md create mode 100644 docs/foundation/data/pagination/src/cursor/cursor.md create mode 100644 docs/foundation/data/pagination/src/errors/codes.md create mode 100644 docs/foundation/data/pagination/src/errors/pagination-error.md create mode 100644 docs/foundation/data/pagination/src/helpers/helpers.md create mode 100644 docs/foundation/data/pagination/src/keyset/keyset-pagination.md create mode 100644 docs/foundation/data/pagination/src/offset/offset.md create mode 100644 docs/foundation/data/pagination/src/otel/pagination-otel.md create mode 100644 docs/foundation/data/pagination/src/tokens/page-tokens.md create mode 100644 docs/foundation/data/pagination/src/types/pagination.types.md create mode 100644 docs/foundation/data/pwa/README.md create mode 100644 docs/foundation/data/pwa/src/caching-strategies/caching-strategies.md create mode 100644 docs/foundation/data/pwa/src/caching-strategies/router.md create mode 100644 docs/foundation/data/pwa/src/errors/errors.md create mode 100644 docs/foundation/data/pwa/src/install-prompt/install-prompt.md create mode 100644 docs/foundation/data/pwa/src/manifest/manifest.md create mode 100644 docs/foundation/data/pwa/src/observability/observability.md create mode 100644 docs/foundation/data/pwa/src/push-notifications/push-notifications.md create mode 100644 docs/foundation/data/pwa/src/push-notifications/vapid.md create mode 100644 docs/foundation/data/pwa/src/schemas/schemas.md create mode 100644 docs/foundation/data/pwa/src/service-worker/service-worker.md create mode 100644 docs/foundation/data/pwa/src/sync-queue/background-sync.md create mode 100644 docs/foundation/data/pwa/src/sync-queue/indexeddb-store.md create mode 100644 docs/foundation/data/pwa/src/sync-queue/local-storage-store.md create mode 100644 docs/foundation/data/pwa/src/sync-queue/memory-store.md create mode 100644 docs/foundation/data/pwa/src/sync-queue/sync-queue.md create mode 100644 docs/foundation/data/pwa/src/sync-queue/version-migration.md create mode 100644 docs/foundation/data/pwa/src/types/common.md create mode 100644 docs/foundation/data/pwa/src/update-controller/update-controller.md create mode 100644 docs/foundation/data/react-packer/README.md create mode 100644 docs/foundation/data/react-packer/src/error-codes/error-codes.md create mode 100644 docs/foundation/data/react-packer/src/hooks/use-packed-audio/use-packed-audio.md create mode 100644 docs/foundation/data/react-packer/src/hooks/use-packed-font/use-packed-font.md create mode 100644 docs/foundation/data/react-packer/src/hooks/use-packed-image/use-packed-image.md create mode 100644 docs/foundation/data/react-packer/src/hooks/use-packed-resource/use-packed-resource.md create mode 100644 docs/foundation/data/react-packer/src/hooks/use-packed-video/use-packed-video.md create mode 100644 docs/foundation/data/react-packer/src/provider/packed-resource-provider/packed-resource-provider.md create mode 100644 docs/foundation/data/react-packer/src/types/react-packer.types.md create mode 100644 docs/foundation/data/serialize/README.md create mode 100644 docs/foundation/data/serialize/src/adapters/eval-safe/eval-safe.md create mode 100644 docs/foundation/data/serialize/src/codec/json/json-decode.md create mode 100644 docs/foundation/data/serialize/src/codec/json/json-encode.md create mode 100644 docs/foundation/data/serialize/src/codec/msgpack/msgpack-decode.md create mode 100644 docs/foundation/data/serialize/src/codec/msgpack/msgpack-encode.md create mode 100644 docs/foundation/data/serialize/src/codec/stream/stream.md create mode 100644 docs/foundation/data/serialize/src/codec/wire/wire.schemas.md create mode 100644 docs/foundation/data/serialize/src/error-codes/error-codes.md create mode 100644 docs/foundation/data/serialize/src/errors/codes.md create mode 100644 docs/foundation/data/serialize/src/errors/serialize-error.md create mode 100644 docs/foundation/data/serialize/src/legacy/legacy.md create mode 100644 docs/foundation/data/serialize/src/observability/metrics.md create mode 100644 docs/foundation/data/serialize/src/registry/registry.md create mode 100644 docs/foundation/data/templates/README.md create mode 100644 docs/foundation/data/templates/src/engine/ParseState.md create mode 100644 docs/foundation/data/templates/src/engine/TemplateEngine.md create mode 100644 docs/foundation/data/templates/src/engine/apply-plugin.md create mode 100644 docs/foundation/data/templates/src/errors/error-codes.md create mode 100644 docs/foundation/data/templates/src/errors/template-error.md create mode 100644 docs/foundation/data/templates/src/otel/templates-otel.md create mode 100644 docs/foundation/data/templates/src/plugins/control/ConditionalPlugin.md create mode 100644 docs/foundation/data/templates/src/plugins/control/LoopPlugin.md create mode 100644 docs/foundation/data/templates/src/plugins/dynamic/CounterPlugin.md create mode 100644 docs/foundation/data/templates/src/plugins/dynamic/DateTimePlugin.md create mode 100644 docs/foundation/data/templates/src/plugins/dynamic/UuidPlugin.md create mode 100644 docs/foundation/data/templates/src/plugins/transform/CaseTransformPlugin.md create mode 100644 docs/foundation/data/templates/src/plugins/transform/RegexPlugin.md create mode 100644 docs/foundation/data/templates/src/plugins/transform/StringSplitPlugin.md create mode 100644 docs/foundation/data/templates/src/plugins/variables/ArrayIndexPlugin.md create mode 100644 docs/foundation/data/templates/src/plugins/variables/DotNotationPlugin.md create mode 100644 docs/foundation/data/templates/src/presets/full.md create mode 100644 docs/foundation/data/templates/src/presets/minimal.md create mode 100644 docs/foundation/data/templates/src/presets/standard.md create mode 100644 docs/foundation/data/templates/src/schemas/templates.schemas.md create mode 100644 docs/foundation/data/templates/src/types/index.md create mode 100644 docs/foundation/data/templates/src/utils/escape.md create mode 100644 docs/foundation/data/templates/src/utils/format.md create mode 100644 docs/foundation/data/templates/src/utils/nested-value.md create mode 100644 docs/foundation/data/validation/README.md create mode 100644 docs/foundation/data/validation/src/core/schema/schema.md create mode 100644 docs/foundation/data/validation/src/errors/errors.md create mode 100644 docs/foundation/data/validation/src/otel/validation-otel.md create mode 100644 docs/foundation/data/validation/src/schemas/array/array.md create mode 100644 docs/foundation/data/validation/src/schemas/boolean/boolean.md create mode 100644 docs/foundation/data/validation/src/schemas/date/date.md create mode 100644 docs/foundation/data/validation/src/schemas/enum/enum.md create mode 100644 docs/foundation/data/validation/src/schemas/intersection/intersection.md create mode 100644 docs/foundation/data/validation/src/schemas/literal/literal.md create mode 100644 docs/foundation/data/validation/src/schemas/nullable/nullable.md create mode 100644 docs/foundation/data/validation/src/schemas/number/number.md create mode 100644 docs/foundation/data/validation/src/schemas/object/object.md create mode 100644 docs/foundation/data/validation/src/schemas/optional/optional.md create mode 100644 docs/foundation/data/validation/src/schemas/record/record.md create mode 100644 docs/foundation/data/validation/src/schemas/string/string.md create mode 100644 docs/foundation/data/validation/src/schemas/tuple/tuple.md create mode 100644 docs/foundation/data/validation/src/schemas/union/union.md create mode 100644 docs/foundation/data/validation/src/types/common.md create mode 100644 docs/foundation/data/validation/src/types/validation-hooks.md create mode 100644 docs/foundation/data/validation/src/utils/coerce.md create mode 100644 docs/foundation/data/validation/src/utils/compose.md create mode 100644 docs/foundation/data/web-workers/README.md create mode 100644 docs/foundation/data/web-workers/src/base-manager/base-manager.md create mode 100644 docs/foundation/data/web-workers/src/base-manager/helpers.md create mode 100644 docs/foundation/data/web-workers/src/circuit-breaker/circuit-breaker.md create mode 100644 docs/foundation/data/web-workers/src/errors/errors.md create mode 100644 docs/foundation/data/web-workers/src/helpers/define-worker.md create mode 100644 docs/foundation/data/web-workers/src/message-bus/message-bus.md create mode 100644 docs/foundation/data/web-workers/src/observability/observability.md create mode 100644 docs/foundation/data/web-workers/src/shared-worker-manager/shared-worker-manager.md create mode 100644 docs/foundation/data/web-workers/src/streaming/stream.md create mode 100644 docs/foundation/data/web-workers/src/types/web-workers.types.md create mode 100644 docs/foundation/data/web-workers/src/worker-manager/worker-manager.md create mode 100644 docs/foundation/data/web-workers/src/worker-pool/internals.md create mode 100644 docs/foundation/data/web-workers/src/worker-pool/scheduler.md create mode 100644 docs/foundation/data/web-workers/src/worker-pool/worker-pool.md create mode 100644 docs/foundation/etl/README.md create mode 100644 docs/foundation/etl/_intro.md create mode 100644 docs/foundation/etl/etl/README.md create mode 100644 docs/foundation/etl/etl/src/core/pipeline/pipeline.md create mode 100644 docs/foundation/etl/etl/src/errors/etl-error.md create mode 100644 docs/foundation/etl/etl/src/schemas/etl.schemas.md create mode 100644 docs/foundation/etl/etl/src/stages/sink/sink.md create mode 100644 docs/foundation/etl/etl/src/stages/source/source.md create mode 100644 docs/foundation/etl/etl/src/stages/transform/transform.md create mode 100644 docs/foundation/etl/etl/src/types/etl.types.md create mode 100644 docs/foundation/feature-flags/README.md create mode 100644 docs/foundation/feature-flags/_intro.md create mode 100644 docs/foundation/feature-flags/feature-flags/README.md create mode 100644 docs/foundation/feature-flags/feature-flags/src/core/evaluator/evaluator.md create mode 100644 docs/foundation/feature-flags/feature-flags/src/core/manager/flag-manager.md create mode 100644 docs/foundation/feature-flags/feature-flags/src/core/registry/flag-registry.md create mode 100644 docs/foundation/feature-flags/feature-flags/src/errors/feature-flags-error.md create mode 100644 docs/foundation/feature-flags/feature-flags/src/providers/json/json.md create mode 100644 docs/foundation/feature-flags/feature-flags/src/providers/memory/memory.md create mode 100644 docs/foundation/feature-flags/feature-flags/src/strategies/attribute/attribute.md create mode 100644 docs/foundation/feature-flags/feature-flags/src/strategies/composite/composite.md create mode 100644 docs/foundation/feature-flags/feature-flags/src/strategies/percentage/percentage.md create mode 100644 docs/foundation/feature-flags/feature-flags/src/strategies/schedule/schedule.md create mode 100644 docs/foundation/feature-flags/feature-flags/src/strategies/user-target/user-target.md create mode 100644 docs/foundation/feature-flags/feature-flags/src/types/common.md create mode 100644 docs/foundation/feature-flags/feature-flags/src/utils/hash.md create mode 100644 docs/foundation/flow/README.md create mode 100644 docs/foundation/flow/_intro.md create mode 100644 docs/foundation/flow/cbor/README.md create mode 100644 docs/foundation/flow/cbor/src/cddl/ast.md create mode 100644 docs/foundation/flow/cbor/src/cddl/lexer.md create mode 100644 docs/foundation/flow/cbor/src/cddl/parser.md create mode 100644 docs/foundation/flow/cbor/src/cddl/validate.md create mode 100644 docs/foundation/flow/cbor/src/cose/alg-map.md create mode 100644 docs/foundation/flow/cbor/src/cose/cose-key.md create mode 100644 docs/foundation/flow/cbor/src/cose/encrypt.md create mode 100644 docs/foundation/flow/cbor/src/cose/encrypt0.md create mode 100644 docs/foundation/flow/cbor/src/cose/headers.md create mode 100644 docs/foundation/flow/cbor/src/cose/jwk.md create mode 100644 docs/foundation/flow/cbor/src/cose/mac.md create mode 100644 docs/foundation/flow/cbor/src/cose/mac0.md create mode 100644 docs/foundation/flow/cbor/src/cose/sig-structure.md create mode 100644 docs/foundation/flow/cbor/src/cose/sign.md create mode 100644 docs/foundation/flow/cbor/src/cose/sign1.md create mode 100644 docs/foundation/flow/cbor/src/cwt/claims.md create mode 100644 docs/foundation/flow/cbor/src/cwt/verify.md create mode 100644 docs/foundation/flow/cbor/src/decoder/decoder.md create mode 100644 docs/foundation/flow/cbor/src/decoder/half-float.md create mode 100644 docs/foundation/flow/cbor/src/decoder/well-formed.md create mode 100644 docs/foundation/flow/cbor/src/deterministic/deterministic.md create mode 100644 docs/foundation/flow/cbor/src/diagnostic/diagnostic.md create mode 100644 docs/foundation/flow/cbor/src/encoder/encoder.md create mode 100644 docs/foundation/flow/cbor/src/encoder/half-float.md create mode 100644 docs/foundation/flow/cbor/src/errors/error-codes.md create mode 100644 docs/foundation/flow/cbor/src/sequences/sequences.md create mode 100644 docs/foundation/flow/cbor/src/streaming/chunk-decoder.md create mode 100644 docs/foundation/flow/cbor/src/streaming/pull-decoder.md create mode 100644 docs/foundation/flow/cbor/src/tags/builtin.md create mode 100644 docs/foundation/flow/cbor/src/tags/registry.md create mode 100644 docs/foundation/flow/cbor/src/tags/tagged.md create mode 100644 docs/foundation/flow/crdt/README.md create mode 100644 docs/foundation/flow/crdt/src/core/sync-manager/sync-manager.md create mode 100644 docs/foundation/flow/crdt/src/core/vector-clock/vector-clock.md create mode 100644 docs/foundation/flow/crdt/src/crdts/g-counter/g-counter.md create mode 100644 docs/foundation/flow/crdt/src/crdts/lww-register/lww-register.md create mode 100644 docs/foundation/flow/crdt/src/crdts/mv-register/mv-register.md create mode 100644 docs/foundation/flow/crdt/src/crdts/or-set/or-set.md create mode 100644 docs/foundation/flow/crdt/src/crdts/pn-counter/pn-counter.md create mode 100644 docs/foundation/flow/crdt/src/crdts/rga/rga.md create mode 100644 docs/foundation/flow/crdt/src/crdts/two-p-set/two-p-set.md create mode 100644 docs/foundation/flow/crdt/src/errors/crdt-error.md create mode 100644 docs/foundation/flow/crdt/src/types/crdt.types.md create mode 100644 docs/foundation/flow/fsm/README.md create mode 100644 docs/foundation/flow/fsm/src/core/interpreter/fsm-interpreter.md create mode 100644 docs/foundation/flow/fsm/src/errors/fsm-error.md create mode 100644 docs/foundation/flow/fsm/src/types/fsm.types.md create mode 100644 docs/foundation/flow/fsm/src/utils/context-helpers.md create mode 100644 docs/foundation/flow/fsm/src/utils/definition-validator.md create mode 100644 docs/foundation/flow/idempotency/README.md create mode 100644 docs/foundation/flow/idempotency/src/distributed/distributed-guard.md create mode 100644 docs/foundation/flow/idempotency/src/distributed/redis-lock-provider.md create mode 100644 docs/foundation/flow/idempotency/src/error-codes/error-codes.md create mode 100644 docs/foundation/flow/idempotency/src/errors/idempotency-error.md create mode 100644 docs/foundation/flow/idempotency/src/guard/idempotency-guard.md create mode 100644 docs/foundation/flow/idempotency/src/key/key-generator.md create mode 100644 docs/foundation/flow/idempotency/src/metrics/idempotency-metrics.md create mode 100644 docs/foundation/flow/idempotency/src/middleware/idempotency-middleware.md create mode 100644 docs/foundation/flow/idempotency/src/store/database-store.md create mode 100644 docs/foundation/flow/idempotency/src/store/memory-store.md create mode 100644 docs/foundation/flow/idempotency/src/store/redis-store.md create mode 100644 docs/foundation/flow/idempotency/src/types/idempotency.types.md create mode 100644 docs/foundation/flow/idempotency/src/versioning/key-versioning.md create mode 100644 docs/foundation/flow/job-scheduler/README.md create mode 100644 docs/foundation/flow/job-scheduler/src/errors/job-scheduler-error.md create mode 100644 docs/foundation/flow/job-scheduler/src/events/events.md create mode 100644 docs/foundation/flow/job-scheduler/src/execution/job-execution.md create mode 100644 docs/foundation/flow/job-scheduler/src/otel/job-scheduler-otel.md create mode 100644 docs/foundation/flow/job-scheduler/src/queue/job-queue.md create mode 100644 docs/foundation/flow/job-scheduler/src/registry/job-registry.md create mode 100644 docs/foundation/flow/job-scheduler/src/scheduler/cron-rescheduler.md create mode 100644 docs/foundation/flow/job-scheduler/src/scheduler/job-dispatcher.md create mode 100644 docs/foundation/flow/job-scheduler/src/scheduler/job-scheduler.md create mode 100644 docs/foundation/flow/job-scheduler/src/scheduler/job-snapshot.md create mode 100644 docs/foundation/flow/queue-distribution-http/README.md create mode 100644 docs/foundation/flow/queue-distribution-http/src/communicator/base/base.md create mode 100644 docs/foundation/flow/queue-distribution-http/src/communicator/http/http-communicator.md create mode 100644 docs/foundation/flow/queue-distribution-http/src/errors/queue-distribution-http-error.md create mode 100644 docs/foundation/flow/queue-distribution-http/src/observability/instruments.md create mode 100644 docs/foundation/flow/queue-distribution-http/src/worker/remote/remote.md create mode 100644 docs/foundation/flow/queue-distribution-worker-thread/README.md create mode 100644 docs/foundation/flow/queue-distribution-worker-thread/src/communicator/worker-thread/worker-thread-communicator.md create mode 100644 docs/foundation/flow/queue-distribution-worker-thread/src/errors/queue-distribution-worker-thread-error.md create mode 100644 docs/foundation/flow/queue-distribution-worker-thread/src/observability/instruments.md create mode 100644 docs/foundation/flow/queue-distribution-worker-thread/src/worker/worker-thread/worker-thread-worker.md create mode 100644 docs/foundation/flow/queue-distribution/README.md create mode 100644 docs/foundation/flow/queue-distribution/src/errors/queue-distribution-error.md create mode 100644 docs/foundation/flow/queue-distribution/src/health-checker/health-checker.md create mode 100644 docs/foundation/flow/queue-distribution/src/internal/noop-logger.md create mode 100644 docs/foundation/flow/queue-distribution/src/load-balancing/base/base.md create mode 100644 docs/foundation/flow/queue-distribution/src/load-balancing/least-busy/least-busy.md create mode 100644 docs/foundation/flow/queue-distribution/src/load-balancing/round-robin/round-robin.md create mode 100644 docs/foundation/flow/queue-distribution/src/load-balancing/weighted/weighted.md create mode 100644 docs/foundation/flow/queue-distribution/src/manager/manager-dispatch.md create mode 100644 docs/foundation/flow/queue-distribution/src/manager/manager-supervisor.md create mode 100644 docs/foundation/flow/queue-distribution/src/manager/manager.md create mode 100644 docs/foundation/flow/queue-distribution/src/observability/instruments.md create mode 100644 docs/foundation/flow/queue-distribution/src/pool/pool.md create mode 100644 docs/foundation/flow/queue-distribution/src/task/task.md create mode 100644 docs/foundation/flow/queue-distribution/src/worker/abstract/abstract-metrics.md create mode 100644 docs/foundation/flow/queue-distribution/src/worker/abstract/abstract.md create mode 100644 docs/foundation/flow/queue-distribution/src/worker/local/local.md create mode 100644 docs/foundation/flow/queue-distribution/src/worker/worker.md create mode 100644 docs/foundation/flow/queue/README.md create mode 100644 docs/foundation/flow/queue/src/errors/queue-error.md create mode 100644 docs/foundation/flow/queue/src/job/job.md create mode 100644 docs/foundation/flow/queue/src/queue/delayed-queue.md create mode 100644 docs/foundation/flow/queue/src/queue/memory-queue.md create mode 100644 docs/foundation/flow/queue/src/queue/priority-queue.md create mode 100644 docs/foundation/flow/queue/src/types/queue-types.md create mode 100644 docs/foundation/flow/queue/src/worker/queue-worker.md create mode 100644 docs/foundation/flow/rate-limiter/README.md create mode 100644 docs/foundation/flow/rate-limiter/src/core/fixed-window/fixed-window.md create mode 100644 docs/foundation/flow/rate-limiter/src/core/rate-limiter/rate-limiter.md create mode 100644 docs/foundation/flow/rate-limiter/src/core/sliding-window/sliding-window.md create mode 100644 docs/foundation/flow/rate-limiter/src/core/token-bucket/token-bucket.md create mode 100644 docs/foundation/flow/rate-limiter/src/errors/rate-limiter-error.md create mode 100644 docs/foundation/flow/rate-limiter/src/middleware/rate-limit-middleware/rate-limit-middleware.md create mode 100644 docs/foundation/flow/rate-limiter/src/schemas/rate-limiter.schemas.md create mode 100644 docs/foundation/flow/rate-limiter/src/storage/adapter/adapter.md create mode 100644 docs/foundation/flow/rate-limiter/src/storage/memory-storage/memory-storage.md create mode 100644 docs/foundation/flow/rate-limiter/src/types/rate-limiter.types.md create mode 100644 docs/foundation/flow/retry/README.md create mode 100644 docs/foundation/flow/retry/src/circuit-breaker/circuit-breaker.md create mode 100644 docs/foundation/flow/retry/src/errors/retry-error.md create mode 100644 docs/foundation/flow/retry/src/otel/retry-otel.md create mode 100644 docs/foundation/flow/retry/src/retry/retry.md create mode 100644 docs/foundation/flow/retry/src/strategies/constant/constant.md create mode 100644 docs/foundation/flow/retry/src/strategies/exponential/exponential.md create mode 100644 docs/foundation/flow/retry/src/strategies/linear/linear.md create mode 100644 docs/foundation/flow/retry/src/types/retry.types.md create mode 100644 docs/foundation/flow/rules-hono/README.md create mode 100644 docs/foundation/flow/rules-hono/src/engine/default.md create mode 100644 docs/foundation/flow/rules-hono/src/middleware/middleware.md create mode 100644 docs/foundation/flow/rules/README.md create mode 100644 docs/foundation/flow/rules/src/actions/actions.md create mode 100644 docs/foundation/flow/rules/src/builder/builder.md create mode 100644 docs/foundation/flow/rules/src/constants.md create mode 100644 docs/foundation/flow/rules/src/context/context.md create mode 100644 docs/foundation/flow/rules/src/engine/engine.md create mode 100644 docs/foundation/flow/rules/src/engine/operators-internal.md create mode 100644 docs/foundation/flow/rules/src/errors/rules-error.md create mode 100644 docs/foundation/flow/rules/src/events/event-bus.md create mode 100644 docs/foundation/flow/rules/src/operators/operators.md create mode 100644 docs/foundation/flow/rules/src/optimizer/optimizer.md create mode 100644 docs/foundation/flow/rules/src/otel/otel.md create mode 100644 docs/foundation/flow/rules/src/serializer/serializer.md create mode 100644 docs/foundation/flow/rules/src/validators/custom/custom.md create mode 100644 docs/foundation/flow/rules/src/validators/field/field.md create mode 100644 docs/foundation/flow/rules/src/validators/schema/schema.md create mode 100644 docs/foundation/flow/streams-chunk-queue/README.md create mode 100644 docs/foundation/flow/streams-chunk-queue/src/binary-protocol/encoder.md create mode 100644 docs/foundation/flow/streams-chunk-queue/src/decryptor/decryptor.md create mode 100644 docs/foundation/flow/streams-chunk-queue/src/errors/streams-chunk-queue-error.md create mode 100644 docs/foundation/flow/streams-chunk-queue/src/events/events.md create mode 100644 docs/foundation/flow/streams-chunk-queue/src/hooks/hooks.md create mode 100644 docs/foundation/flow/streams-chunk-queue/src/queue/pipeline.md create mode 100644 docs/foundation/flow/streams-chunk-queue/src/queue/storage-ops.md create mode 100644 docs/foundation/flow/streams-chunk-queue/src/queue/streaming-chunk-queue.md create mode 100644 docs/foundation/flow/streams-chunk-queue/src/rate-limiter/adapter.md create mode 100644 docs/foundation/flow/streams-chunk-queue/src/storage-adapter/persister.md create mode 100644 docs/foundation/flow/streams-chunk-queue/src/telemetry/telemetry.md create mode 100644 docs/foundation/flow/streams-chunk-queue/src/types/types.md create mode 100644 docs/foundation/flow/streams-chunk-queue/src/validator/chunk-verifier-validator.md create mode 100644 docs/foundation/flow/streams-chunk-queue/src/validator/validator.md create mode 100644 docs/foundation/flow/streams-metadata/README.md create mode 100644 docs/foundation/flow/streams-metadata/src/errors/errors.md create mode 100644 docs/foundation/flow/streams-metadata/src/events/events.md create mode 100644 docs/foundation/flow/streams-metadata/src/exif/exif.md create mode 100644 docs/foundation/flow/streams-metadata/src/metadata/metadata.md create mode 100644 docs/foundation/flow/streams-metadata/src/mime/mime.md create mode 100644 docs/foundation/flow/streams-metadata/src/types/payload.md create mode 100644 docs/foundation/flow/streams-metadata/src/types/process-options.md create mode 100644 docs/foundation/flow/streams/README.md create mode 100644 docs/foundation/flow/streams/src/base/transform/transform.md create mode 100644 docs/foundation/flow/streams/src/errors/stream-error.md create mode 100644 docs/foundation/flow/streams/src/factory/factory/factory.md create mode 100644 docs/foundation/flow/streams/src/instrument/transform/transform.md create mode 100644 docs/foundation/flow/streams/src/manager/manager/manager.md create mode 100644 docs/foundation/flow/streams/src/node/node-adapters.md create mode 100644 docs/foundation/flow/streams/src/pipeline/builder/builder.md create mode 100644 docs/foundation/flow/streams/src/pipeline/concat/concat.md create mode 100644 docs/foundation/flow/streams/src/pipeline/fan-out/fan-out.md create mode 100644 docs/foundation/flow/streams/src/pipeline/merge-ordered/merge-ordered.md create mode 100644 docs/foundation/flow/streams/src/pipeline/merge/merge.md create mode 100644 docs/foundation/flow/streams/src/pipeline/partition/partition.md create mode 100644 docs/foundation/flow/streams/src/pipeline/route/route.md create mode 100644 docs/foundation/flow/streams/src/pipeline/safe-branch/safe-branch.md create mode 100644 docs/foundation/flow/streams/src/pipeline/zip/zip.md create mode 100644 docs/foundation/flow/streams/src/primitives/duplex/duplex.md create mode 100644 docs/foundation/flow/streams/src/primitives/network/network.md create mode 100644 docs/foundation/flow/streams/src/readable/from-array/from-array.md create mode 100644 docs/foundation/flow/streams/src/readable/from-bytes/from-bytes.md create mode 100644 docs/foundation/flow/streams/src/readable/from-generator/from-generator.md create mode 100644 docs/foundation/flow/streams/src/sinks/for-each/for-each.md create mode 100644 docs/foundation/flow/streams/src/sinks/to-array/to-array.md create mode 100644 docs/foundation/flow/streams/src/sinks/to-async-iterable/to-async-iterable.md create mode 100644 docs/foundation/flow/streams/src/sinks/to-bytes/to-bytes.md create mode 100644 docs/foundation/flow/streams/src/transforms/batch/batch.md create mode 100644 docs/foundation/flow/streams/src/transforms/chunk-bytes/chunk-bytes.md create mode 100644 docs/foundation/flow/streams/src/transforms/coalesce-bytes/coalesce-bytes.md create mode 100644 docs/foundation/flow/streams/src/transforms/compress/compress.md create mode 100644 docs/foundation/flow/streams/src/transforms/crypto/crypto.md create mode 100644 docs/foundation/flow/streams/src/transforms/dedup/dedup.md create mode 100644 docs/foundation/flow/streams/src/transforms/filter/filter.md create mode 100644 docs/foundation/flow/streams/src/transforms/flat-map/flat-map.md create mode 100644 docs/foundation/flow/streams/src/transforms/length-prefix-decode/length-prefix-decode.md create mode 100644 docs/foundation/flow/streams/src/transforms/length-prefix-encode/length-prefix-encode.md create mode 100644 docs/foundation/flow/streams/src/transforms/limit/limit.md create mode 100644 docs/foundation/flow/streams/src/transforms/map/map.md create mode 100644 docs/foundation/flow/streams/src/transforms/sliding-bytes/sliding-bytes.md create mode 100644 docs/foundation/flow/streams/src/transforms/split-join/split-join.md create mode 100644 docs/foundation/flow/streams/src/transforms/tap/tap.md create mode 100644 docs/foundation/flow/streams/src/transforms/text-codec/text-codec.md create mode 100644 docs/foundation/flow/streams/src/transforms/throttle/throttle.md create mode 100644 docs/foundation/flow/streams/src/transforms/window/window.md create mode 100644 docs/foundation/flow/streams/src/types/common.md create mode 100644 docs/foundation/flow/streams/src/utils/buffer/buffer-to-uint8/buffer-to-uint8.md create mode 100644 docs/foundation/flow/streams/src/utils/buffer/get-data-from-file/get-data-from-file.md create mode 100644 docs/foundation/flow/streams/src/utils/buffer/uint8-slice/uint8-slice.md create mode 100644 docs/foundation/flow/streams/src/utils/stream/create-data-stream/create-data-stream.md create mode 100644 docs/foundation/flow/streams/src/utils/stream/process-data-stream/process-data-stream.md create mode 100644 docs/foundation/flow/streams/src/utils/stream/round-trip/round-trip.md create mode 100644 docs/foundation/flow/streams/src/utils/stream/validate-integrity/validate-integrity.md create mode 100644 docs/foundation/flow/undo/README.md create mode 100644 docs/foundation/flow/undo/src/async/async-command.md create mode 100644 docs/foundation/flow/undo/src/async/async-stack.md create mode 100644 docs/foundation/flow/undo/src/branch/branch.md create mode 100644 docs/foundation/flow/undo/src/command/command.md create mode 100644 docs/foundation/flow/undo/src/compression/history-compressor.md create mode 100644 docs/foundation/flow/undo/src/errors/undo-error.md create mode 100644 docs/foundation/flow/undo/src/merge/command-merger.md create mode 100644 docs/foundation/flow/undo/src/schemas/undo.schemas.md create mode 100644 docs/foundation/flow/undo/src/selective/selective-undo.md create mode 100644 docs/foundation/flow/undo/src/stack/stack.md create mode 100644 docs/foundation/flow/undo/src/types/undo.types.md create mode 100644 docs/foundation/flow/workflow/README.md create mode 100644 docs/foundation/flow/workflow/src/compensation/compensator/compensator.md create mode 100644 docs/foundation/flow/workflow/src/compensation/saga/saga.md create mode 100644 docs/foundation/flow/workflow/src/core/context/context.md create mode 100644 docs/foundation/flow/workflow/src/core/workflow-builder/workflow-builder.md create mode 100644 docs/foundation/flow/workflow/src/core/workflow-engine/transition-hooks.md create mode 100644 docs/foundation/flow/workflow/src/core/workflow-engine/workflow-engine.md create mode 100644 docs/foundation/flow/workflow/src/errors/workflow-error.md create mode 100644 docs/foundation/flow/workflow/src/middleware/hook/hook.md create mode 100644 docs/foundation/flow/workflow/src/middleware/retry/retry.md create mode 100644 docs/foundation/flow/workflow/src/otel/instruments.md create mode 100644 docs/foundation/flow/workflow/src/steps/conditional-step/conditional-step.md create mode 100644 docs/foundation/flow/workflow/src/steps/parallel-step/parallel-step.md create mode 100644 docs/foundation/flow/workflow/src/steps/step/step.md create mode 100644 docs/foundation/flow/workflow/src/types/common.md create mode 100644 docs/foundation/flow/workflow/src/types/workflow-hooks.md create mode 100644 docs/foundation/flow/workflow/src/utils/utils.md create mode 100644 docs/foundation/random/README.md create mode 100644 docs/foundation/random/_intro.md create mode 100644 docs/foundation/random/noise/README.md create mode 100644 docs/foundation/random/noise/src/blue/blue.md create mode 100644 docs/foundation/random/noise/src/errors/noise-error.md create mode 100644 docs/foundation/random/noise/src/fbm/fbm.md create mode 100644 docs/foundation/random/noise/src/perlin/perlin.md create mode 100644 docs/foundation/random/noise/src/simplex/simplex.md create mode 100644 docs/foundation/random/noise/src/types/noise.types.md create mode 100644 docs/foundation/random/noise/src/utils/permutation.md create mode 100644 docs/foundation/random/noise/src/value/value.md create mode 100644 docs/foundation/random/noise/src/worley/worley.md create mode 100644 docs/foundation/random/pseudo-random/README.md create mode 100644 docs/foundation/random/pseudo-random/src/algorithms/counter-rng.md create mode 100644 docs/foundation/random/pseudo-random/src/algorithms/mulberry32.md create mode 100644 docs/foundation/random/pseudo-random/src/algorithms/sfc32.md create mode 100644 docs/foundation/random/pseudo-random/src/algorithms/xoshiro256.md create mode 100644 docs/foundation/random/pseudo-random/src/errors/pseudo-random-error.md create mode 100644 docs/foundation/random/pseudo-random/src/seed/normalize.md create mode 100644 docs/foundation/random/pseudo-random/src/types/seeded-rng.types.md create mode 100644 docs/foundation/random/pseudo-random/src/utils/sample.md create mode 100644 docs/foundation/random/pseudo-random/src/utils/shuffle.md create mode 100644 docs/foundation/random/random/README.md create mode 100644 docs/foundation/random/random/src/collections/collections.md create mode 100644 docs/foundation/random/random/src/distributions/continuous/continuous.md create mode 100644 docs/foundation/random/random/src/distributions/discrete/discrete.md create mode 100644 docs/foundation/random/random/src/distributions/sampler/sampler.md create mode 100644 docs/foundation/random/random/src/errors/random-error.md create mode 100644 docs/foundation/random/random/src/game/dice.md create mode 100644 docs/foundation/random/random/src/ids/nanoid.md create mode 100644 docs/foundation/random/random/src/ids/ulid.md create mode 100644 docs/foundation/random/random/src/ids/uuid.md create mode 100644 docs/foundation/random/random/src/numbers/random-float.md create mode 100644 docs/foundation/random/random/src/numbers/random-int.md create mode 100644 docs/foundation/random/random/src/objects/objects.md create mode 100644 docs/foundation/random/random/src/source/crypto-rng.md create mode 100644 docs/foundation/random/random/src/source/default-rng.md create mode 100644 docs/foundation/random/random/src/strings/random-string.md create mode 100644 docs/foundation/timing/README.md create mode 100644 docs/foundation/timing/_intro.md create mode 100644 docs/foundation/timing/cron/README.md create mode 100644 docs/foundation/timing/cron/src/errors/cron-error.md create mode 100644 docs/foundation/timing/cron/src/fields/cron-fields.md create mode 100644 docs/foundation/timing/cron/src/macros/macros.md create mode 100644 docs/foundation/timing/cron/src/next-run/next-run-fields.md create mode 100644 docs/foundation/timing/cron/src/next-run/next-run.md create mode 100644 docs/foundation/timing/cron/src/otel/cron-otel.md create mode 100644 docs/foundation/timing/cron/src/parse/parse-cron.md create mode 100644 docs/foundation/timing/cron/src/scheduler/cron-scheduler.md create mode 100644 docs/foundation/timing/cron/src/timezone/timezone.md create mode 100644 docs/foundation/timing/datetime/README.md create mode 100644 docs/foundation/timing/datetime/src/business-days/business-days.md create mode 100644 docs/foundation/timing/datetime/src/calendar/calendar-boundary.md create mode 100644 docs/foundation/timing/datetime/src/calendar/calendar-core.md create mode 100644 docs/foundation/timing/datetime/src/calendar/calendar-duration.md create mode 100644 docs/foundation/timing/datetime/src/calendar/calendar-grid.md create mode 100644 docs/foundation/timing/datetime/src/calendar/calendar.md create mode 100644 docs/foundation/timing/datetime/src/errors/datetime-error.md create mode 100644 docs/foundation/timing/datetime/src/otel/datetime-otel.md create mode 100644 docs/foundation/timing/datetime/src/recurrence/recurrence-generate.md create mode 100644 docs/foundation/timing/datetime/src/recurrence/recurrence-helpers.md create mode 100644 docs/foundation/timing/datetime/src/recurrence/recurrence.md create mode 100644 docs/foundation/timing/datetime/src/relative/relative.md create mode 100644 docs/foundation/timing/datetime/src/types/datetime.types.md create mode 100644 docs/foundation/timing/timing/README.md create mode 100644 docs/foundation/timing/timing/src/decay/decay.md create mode 100644 docs/foundation/timing/timing/src/errors/timing-error.md create mode 100644 docs/foundation/timing/timing/src/otel/timing-otel.md create mode 100644 docs/foundation/timing/timing/src/scheduler/scheduler.md create mode 100644 docs/foundation/timing/timing/src/stopwatch/stopwatch.md create mode 100644 docs/foundation/timing/timing/src/throttle/once/once.md create mode 100644 docs/foundation/timing/timing/src/throttle/rate-limit/rate-limit.md create mode 100644 docs/foundation/timing/timing/src/throttle/throttle.md create mode 100644 docs/foundation/timing/timing/src/throttle/times/times.md create mode 100644 docs/foundation/timing/timing/src/timer/timer.md create mode 100644 docs/foundation/timing/timing/src/vector-clock/vector-clock.md create mode 100644 docs/gaming/README.md create mode 100644 docs/gaming/_intro.md create mode 100644 docs/gaming/games/README.md create mode 100644 docs/gaming/games/_intro.md create mode 100644 docs/gaming/games/controller/README.md create mode 100644 docs/gaming/games/controller/src/base/base.md create mode 100644 docs/gaming/games/controller/src/error-codes/error-codes.md create mode 100644 docs/gaming/games/controller/src/events/events.md create mode 100644 docs/gaming/games/controller/src/gamepad/gamepad.internal.md create mode 100644 docs/gaming/games/controller/src/gamepad/gamepad.md create mode 100644 docs/gaming/games/controller/src/keyboard/keyboard.md create mode 100644 docs/gaming/games/controller/src/merger/merger.md create mode 100644 docs/gaming/games/controller/src/telemetry/telemetry.md create mode 100644 docs/gaming/games/controller/src/types/controller.types.md create mode 100644 docs/gaming/games/controller/src/types/keys.md create mode 100644 docs/gaming/games/ecs/README.md create mode 100644 docs/gaming/games/ecs/src/archetype/archetype.md create mode 100644 docs/gaming/games/ecs/src/bitset/bitset.md create mode 100644 docs/gaming/games/ecs/src/component-registry/component-registry.md create mode 100644 docs/gaming/games/ecs/src/entity-pool/entity-pool.md create mode 100644 docs/gaming/games/ecs/src/errors/ecs-error.md create mode 100644 docs/gaming/games/ecs/src/observability/otel.md create mode 100644 docs/gaming/games/ecs/src/query/query.md create mode 100644 docs/gaming/games/ecs/src/schema/schema.md create mode 100644 docs/gaming/games/ecs/src/system/system.md create mode 100644 docs/gaming/games/ecs/src/types/ecs.types.md create mode 100644 docs/gaming/games/ecs/src/world/world.md create mode 100644 docs/gaming/games/game-server/README.md create mode 100644 docs/gaming/games/game-server/src/core/abstract-game-logic/abstract-game-logic.md create mode 100644 docs/gaming/games/game-server/src/core/events/game-event-emitter/game-event-emitter.md create mode 100644 docs/gaming/games/game-server/src/core/events/game-events/game-events.md create mode 100644 docs/gaming/games/game-server/src/core/interfaces/i-game-logic/i-game-logic.md create mode 100644 docs/gaming/games/game-server/src/core/interfaces/i-player-manager/i-player-manager.md create mode 100644 docs/gaming/games/game-server/src/core/interfaces/i-session-manager/i-session-manager.md create mode 100644 docs/gaming/games/game-server/src/core/interfaces/i-state-manager/i-state-manager.md create mode 100644 docs/gaming/games/game-server/src/engine/di-container/di-container.md create mode 100644 docs/gaming/games/game-server/src/engine/game-engine/game-engine.md create mode 100644 docs/gaming/games/game-server/src/engine/game-loop/game-loop.md create mode 100644 docs/gaming/games/game-server/src/engine/player-manager/player-manager.md create mode 100644 docs/gaming/games/game-server/src/engine/plugin-manager/plugin-manager.md create mode 100644 docs/gaming/games/game-server/src/engine/session-lifecycle/session-lifecycle.md create mode 100644 docs/gaming/games/game-server/src/engine/session-node/session-node.md create mode 100644 docs/gaming/games/game-server/src/engine/session-store/session-store.md create mode 100644 docs/gaming/games/game-server/src/engine/session-tree/session-tree.md create mode 100644 docs/gaming/games/game-server/src/enhanced/anti-cheat/anti-cheat-validator/anti-cheat-validator.internal.md create mode 100644 docs/gaming/games/game-server/src/enhanced/anti-cheat/anti-cheat-validator/anti-cheat-validator.md create mode 100644 docs/gaming/games/game-server/src/enhanced/interest-management/interest-manager/interest-manager.internal.md create mode 100644 docs/gaming/games/game-server/src/enhanced/interest-management/interest-manager/interest-manager.md create mode 100644 docs/gaming/games/game-server/src/enhanced/lag-compensation/lag-compensator/lag-compensator.internal.md create mode 100644 docs/gaming/games/game-server/src/enhanced/lag-compensation/lag-compensator/lag-compensator.md create mode 100644 docs/gaming/games/game-server/src/enhanced/leaderboard/leaderboard-manager/leaderboard-manager.md create mode 100644 docs/gaming/games/game-server/src/enhanced/persistence/game-persistence/game-persistence.md create mode 100644 docs/gaming/games/game-server/src/enhanced/replay/replay-player/replay-player.md create mode 100644 docs/gaming/games/game-server/src/enhanced/replay/replay-recorder/replay-recorder.md create mode 100644 docs/gaming/games/game-server/src/enhanced/service-discovery/game-instance-registry/game-instance-registry.internal.md create mode 100644 docs/gaming/games/game-server/src/enhanced/service-discovery/game-instance-registry/game-instance-registry.md create mode 100644 docs/gaming/games/game-server/src/enhanced/state-sync/bitpacker-state-sync/bitpacker-state-sync.md create mode 100644 docs/gaming/games/game-server/src/enhanced/timing/vector-clock-sync/vector-clock-sync.internal.md create mode 100644 docs/gaming/games/game-server/src/enhanced/timing/vector-clock-sync/vector-clock-sync.md create mode 100644 docs/gaming/games/game-server/src/enhanced/tournament/tournament-manager/tournament-bracket.internal.md create mode 100644 docs/gaming/games/game-server/src/enhanced/tournament/tournament-manager/tournament-manager.md create mode 100644 docs/gaming/games/game-server/src/enhanced/tournament/tournament-manager/tournament-standings.internal.md create mode 100644 docs/gaming/games/game-server/src/errors/game-server-error.md create mode 100644 docs/gaming/games/game-server/src/integrations/enhanced-server/enhanced-server.md create mode 100644 docs/gaming/games/game-server/src/matchmaking/matchmaking-engine/matchmaking-engine.md create mode 100644 docs/gaming/games/game-server/src/matchmaking/queue-manager/queue-manager.md create mode 100644 docs/gaming/games/game-server/src/matchmaking/skill-matcher/skill-matcher.md create mode 100644 docs/gaming/games/game-server/src/matchmaking/spectator-manager/spectator-manager.md create mode 100644 docs/gaming/games/game-server/src/matchmaking/winner-stays-on/winner-stays-on.md create mode 100644 docs/gaming/games/game-server/src/network/network-adapter/network-adapter.md create mode 100644 docs/gaming/games/game-server/src/network/reconnection-manager/reconnection-manager.md create mode 100644 docs/gaming/games/game-server/src/network/webrtc-transport/webrtc-transport.md create mode 100644 docs/gaming/games/game-server/src/network/websocket-transport/websocket-transport.md create mode 100644 docs/gaming/games/game-server/src/observability/otel.md create mode 100644 docs/gaming/games/game-server/src/performance/network-tier-adapter/network-tier-adapter.md create mode 100644 docs/gaming/games/game-server/src/performance/object-pool/object-pool.md create mode 100644 docs/gaming/games/game-server/src/performance/session-pool/session-pool.md create mode 100644 docs/gaming/games/game-server/src/plugins/ab-test-plugin/ab-test-plugin.md create mode 100644 docs/gaming/games/game-server/src/plugins/analytics-plugin/analytics-plugin.md create mode 100644 docs/gaming/games/game-server/src/plugins/base-plugin/base-plugin.md create mode 100644 docs/gaming/games/game-server/src/plugins/feature-flag-plugin/feature-flag-plugin.md create mode 100644 docs/gaming/games/game-server/src/plugins/logging-plugin/logging-plugin.md create mode 100644 docs/gaming/games/game-server/src/plugins/persistence-plugin/persistence-plugin.md create mode 100644 docs/gaming/games/game-server/src/plugins/rules-plugin/rules-plugin.md create mode 100644 docs/gaming/games/game-server/src/plugins/workflow-plugin/workflow-plugin.md create mode 100644 docs/gaming/games/game-server/src/state/delta-compressor/delta-compressor.md create mode 100644 docs/gaming/games/game-server/src/state/state-differ/state-differ.md create mode 100644 docs/gaming/games/game-server/src/state/state-manager/state-manager.md create mode 100644 docs/gaming/games/game-server/src/state/state-sync/state-sync.md create mode 100644 docs/gaming/games/game-server/src/types/common.md create mode 100644 docs/gaming/games/game-server/src/types/common.types.md create mode 100644 docs/geospatial/README.md create mode 100644 docs/geospatial/_intro.md create mode 100644 docs/geospatial/geo/README.md create mode 100644 docs/geospatial/geo/_intro.md create mode 100644 docs/geospatial/geo/geo-earth/README.md create mode 100644 docs/geospatial/geo/geo-earth/src/coordinates/coordinates.md create mode 100644 docs/geospatial/geo/geo-earth/src/earth-config/earth-config.md create mode 100644 docs/geospatial/geo/geo-earth/src/geocoding/geocoding.md create mode 100644 docs/geospatial/geo/geo-earth/src/geohash/geohash.md create mode 100644 docs/geospatial/geo/geo-planet/README.md create mode 100644 docs/geospatial/geo/geo-planet/src/atmospheric/atmospheric.md create mode 100644 docs/geospatial/geo/geo-planet/src/planet-surface/planet-surface.md create mode 100644 docs/geospatial/geo/geo-planet/src/types/schemas.md create mode 100644 docs/geospatial/geo/geo-planet/src/types/types.md create mode 100644 docs/geospatial/geo/geo/README.md create mode 100644 docs/geospatial/geo/geo/src/angular/angular.md create mode 100644 docs/geospatial/geo/geo/src/bearing/bearing.md create mode 100644 docs/geospatial/geo/geo/src/bounds/bounds.md create mode 100644 docs/geospatial/geo/geo/src/distance/distance.md create mode 100644 docs/geospatial/geo/geo/src/ellipsoid/ellipsoid.md create mode 100644 docs/geospatial/geo/geo/src/observability/observability.md create mode 100644 docs/geospatial/geo/geo/src/polygon/polygon.md create mode 100644 docs/geospatial/geo/geo/src/transforms/transforms.md create mode 100644 docs/geospatial/geo/geo/src/types/schemas.md create mode 100644 docs/geospatial/geo/geo/src/types/types.md create mode 100644 docs/geospatial/geo/geo/src/units/units.md create mode 100644 docs/geospatial/geo/solar-system/README.md create mode 100644 docs/geospatial/geo/solar-system/src/provider/provider.md create mode 100644 docs/geospatial/geo/solar-system/src/seasons/seasons.md create mode 100644 docs/geospatial/geo/stars/README.md create mode 100644 docs/geospatial/geo/stars/src/catalog/catalog.md create mode 100644 docs/geospatial/geo/stars/src/provider/provider.md create mode 100644 docs/geospatial/geo/stars/src/types.md create mode 100644 docs/geospatial/geo/tides/README.md create mode 100644 docs/geospatial/geo/tides/src/admiralty/admiralty.md create mode 100644 docs/geospatial/geo/tides/src/harmonic/harmonic-constituents.md create mode 100644 docs/geospatial/geo/tides/src/harmonic/harmonic.md create mode 100644 docs/geospatial/geo/tides/src/physics/physics.md create mode 100644 docs/geospatial/geo/tides/src/provider/provider.md create mode 100644 docs/geospatial/geo/tides/src/stations/stations.md create mode 100644 docs/geospatial/geo/tides/src/types/types.md create mode 100644 docs/geospatial/geo/universe/README.md create mode 100644 docs/geospatial/geo/universe/src/client/client.md create mode 100644 docs/geospatial/geo/universe/src/frames/frames.md create mode 100644 docs/geospatial/geo/universe/src/observer/observer.md create mode 100644 docs/geospatial/geo/universe/src/packets/packets.md create mode 100644 docs/geospatial/geo/universe/src/providers/providers.md create mode 100644 docs/geospatial/geo/universe/src/types/types.md create mode 100644 docs/geospatial/logistics/README.md create mode 100644 docs/geospatial/logistics/_intro.md create mode 100644 docs/geospatial/logistics/ports/README.md create mode 100644 docs/geospatial/logistics/ports/src/data/airports/airports.md create mode 100644 docs/geospatial/logistics/ports/src/data/all-ports/all-ports.md create mode 100644 docs/geospatial/logistics/ports/src/data/rail-terminals/rail-terminals.md create mode 100644 docs/geospatial/logistics/ports/src/data/sea-ports-africa-mena/sea-ports-africa-mena.md create mode 100644 docs/geospatial/logistics/ports/src/data/sea-ports-americas/sea-ports-americas.md create mode 100644 docs/geospatial/logistics/ports/src/data/sea-ports-asia/sea-ports-asia.md create mode 100644 docs/geospatial/logistics/ports/src/data/sea-ports-europe/sea-ports-europe.md create mode 100644 docs/geospatial/logistics/ports/src/data/sea-ports-oceania/sea-ports-oceania.md create mode 100644 docs/geospatial/logistics/ports/src/data/sea-ports/sea-ports.md create mode 100644 docs/geospatial/logistics/ports/src/data/shipping-lanes/shipping-lanes.md create mode 100644 docs/geospatial/logistics/ports/src/distance/distance.md create mode 100644 docs/geospatial/logistics/ports/src/error-codes/error-codes.md create mode 100644 docs/geospatial/logistics/ports/src/eta/eta.md create mode 100644 docs/geospatial/logistics/ports/src/find-port/find-port.md create mode 100644 docs/geospatial/logistics/ports/src/lane-distance/lane-distance.md create mode 100644 docs/geospatial/logistics/ports/src/lane-lookup/lane-lookup.md create mode 100644 docs/geospatial/logistics/ports/src/lane-progress/lane-progress.md create mode 100644 docs/geospatial/logistics/ports/src/nearest-port/nearest-port.md create mode 100644 docs/geospatial/logistics/ports/src/otel/otel.md create mode 100644 docs/geospatial/logistics/ports/src/schemas/schemas.md create mode 100644 docs/geospatial/logistics/ports/src/spatial-index/spatial-index.md create mode 100644 docs/geospatial/logistics/ports/src/types/port.types.md create mode 100644 docs/identity/README.md create mode 100644 docs/identity/_intro.md create mode 100644 docs/identity/auth/README.md create mode 100644 docs/identity/auth/_intro.md create mode 100644 docs/identity/auth/auth/README.md create mode 100644 docs/identity/auth/auth/src/adapters/auth/auth.md create mode 100644 docs/identity/auth/auth/src/adapters/memory/memory.md create mode 100644 docs/identity/auth/auth/src/api-keys/api-keys.md create mode 100644 docs/identity/auth/auth/src/errors/auth-error.md create mode 100644 docs/identity/auth/auth/src/jwt/token-lifecycle.md create mode 100644 docs/identity/auth/auth/src/middleware/auth-middleware.md create mode 100644 docs/identity/auth/auth/src/schemas/auth.schemas.md create mode 100644 docs/identity/auth/auth/src/types/auth.types.md create mode 100644 docs/identity/auth/better-auth-surrealdb/README.md create mode 100644 docs/identity/auth/better-auth-surrealdb/src/adapter/adapter.md create mode 100644 docs/identity/auth/better-auth-surrealdb/src/adapter/internals.md create mode 100644 docs/identity/auth/better-auth-surrealdb/src/adapter/model-to-table.md create mode 100644 docs/identity/auth/better-auth-surrealdb/src/adapter/operations.md create mode 100644 docs/identity/auth/better-auth-surrealdb/src/adapter/v1.6.md create mode 100644 docs/identity/auth/better-auth-surrealdb/src/compile/compile-select.md create mode 100644 docs/identity/auth/better-auth-surrealdb/src/compile/compile-sort.md create mode 100644 docs/identity/auth/better-auth-surrealdb/src/compile/compile-where.md create mode 100644 docs/identity/auth/better-auth-surrealdb/src/error-codes/error-codes.md create mode 100644 docs/identity/auth/better-auth-surrealdb/src/id-strategy/id-strategy.md create mode 100644 docs/identity/auth/better-auth-surrealdb/src/link-fields/link-fields.md create mode 100644 docs/identity/auth/better-auth-surrealdb/src/otel/instruments.md create mode 100644 docs/identity/auth/better-auth-surrealdb/src/schema/schema.md create mode 100644 docs/identity/auth/better-auth-surrealdb/src/schemas/link-fields.md create mode 100644 docs/identity/auth/better-auth-surrealdb/src/schemas/options.md create mode 100644 docs/identity/auth/better-auth-surrealdb/src/testing/run-adapter-conformance.md create mode 100644 docs/identity/auth/better-auth-surrealdb/src/types/adapter.md create mode 100644 docs/identity/auth/jwt-tenant/README.md create mode 100644 docs/identity/auth/jwt-tenant/src/errors/jwt-tenant-error.md create mode 100644 docs/identity/auth/jwt-tenant/src/jwks/in-memory-key-store/in-memory-key-store.md create mode 100644 docs/identity/auth/jwt-tenant/src/jwks/jwks-endpoint/jwks-endpoint.md create mode 100644 docs/identity/auth/jwt-tenant/src/keys/key-generator/key-generator.md create mode 100644 docs/identity/auth/jwt-tenant/src/schemas/jwt-tenant.schemas.md create mode 100644 docs/identity/auth/jwt-tenant/src/token/token-issuer/token-issuer.md create mode 100644 docs/identity/auth/jwt-tenant/src/token/token-verifier/token-verifier.md create mode 100644 docs/identity/auth/jwt-tenant/src/types/jwt-tenant.types.md create mode 100644 docs/identity/auth/macos-keychain/README.md create mode 100644 docs/identity/auth/macos-keychain/src/core/error-classifier/error-classifier.md create mode 100644 docs/identity/auth/macos-keychain/src/core/keychain-bridge/default-executor.md create mode 100644 docs/identity/auth/macos-keychain/src/core/keychain-bridge/keychain-bridge.md create mode 100644 docs/identity/auth/macos-keychain/src/core/output-parser/output-parser.md create mode 100644 docs/identity/auth/macos-keychain/src/error-codes.md create mode 100644 docs/identity/auth/macos-keychain/src/errors/keychain-errors.md create mode 100644 docs/identity/auth/macos-keychain/src/schemas/macos-keychain.schemas.md create mode 100644 docs/identity/auth/macos-keychain/src/types/macos-keychain.types.md create mode 100644 docs/identity/auth/oauth-client/README.md create mode 100644 docs/identity/auth/oauth-client/src/core/authorization-code/authorization-code.md create mode 100644 docs/identity/auth/oauth-client/src/core/client-credentials/client-credentials.md create mode 100644 docs/identity/auth/oauth-client/src/core/client/oauth-client.md create mode 100644 docs/identity/auth/oauth-client/src/core/discovery/discovery.md create mode 100644 docs/identity/auth/oauth-client/src/core/provider/provider.md create mode 100644 docs/identity/auth/oauth-client/src/core/token-refresh/token-refresh.md create mode 100644 docs/identity/auth/oauth-client/src/errors/oauth-client-error.md create mode 100644 docs/identity/auth/oauth-client/src/types/oauth-client.types.md create mode 100644 docs/identity/auth/oauth-client/src/utils/jwt.md create mode 100644 docs/identity/auth/oauth-client/src/utils/pkce.md create mode 100644 docs/identity/auth/oauth-client/src/utils/url-builder.md create mode 100644 docs/identity/auth/permissions/README.md create mode 100644 docs/identity/auth/permissions/src/adapters/adapter-interface/adapter-interface.md create mode 100644 docs/identity/auth/permissions/src/adapters/memory/memory.md create mode 100644 docs/identity/auth/permissions/src/cache/permission-cache/permission-cache.md create mode 100644 docs/identity/auth/permissions/src/conditions/condition-matcher/condition-matcher.md create mode 100644 docs/identity/auth/permissions/src/conditions/field-matcher/field-matcher.md create mode 100644 docs/identity/auth/permissions/src/conditions/subject-detector/subject-detector.md create mode 100644 docs/identity/auth/permissions/src/core/ability-builder/ability-builder.md create mode 100644 docs/identity/auth/permissions/src/core/ability/ability.md create mode 100644 docs/identity/auth/permissions/src/core/permission-manager/permission-manager.md create mode 100644 docs/identity/auth/permissions/src/core/policy-engine/policy-engine.md create mode 100644 docs/identity/auth/permissions/src/core/role-manager/role-manager.md create mode 100644 docs/identity/auth/permissions/src/core/rule/rule.md create mode 100644 docs/identity/auth/permissions/src/errors/permission-error.md create mode 100644 docs/identity/auth/permissions/src/events/permission-events.md create mode 100644 docs/identity/auth/permissions/src/middleware/permission-middleware/permission-middleware.md create mode 100644 docs/identity/auth/permissions/src/presets/role-presets/role-presets.md create mode 100644 docs/identity/auth/permissions/src/schemas/permissions.schemas.md create mode 100644 docs/identity/auth/permissions/src/types/permissions.types.md create mode 100644 docs/identity/auth/webauthn/README.md create mode 100644 docs/identity/auth/webauthn/src/adapter/adapter.md create mode 100644 docs/identity/auth/webauthn/src/adapter/dom-exception-mapper.md create mode 100644 docs/identity/auth/webauthn/src/attestation/android-key/android-key.md create mode 100644 docs/identity/auth/webauthn/src/attestation/android-safetynet/android-safetynet.md create mode 100644 docs/identity/auth/webauthn/src/attestation/apple/apple.md create mode 100644 docs/identity/auth/webauthn/src/attestation/fido-u2f/fido-u2f.md create mode 100644 docs/identity/auth/webauthn/src/attestation/none/none.md create mode 100644 docs/identity/auth/webauthn/src/attestation/packed/packed.md create mode 100644 docs/identity/auth/webauthn/src/attestation/tpm/tpm.md create mode 100644 docs/identity/auth/webauthn/src/authenticate/authenticate.md create mode 100644 docs/identity/auth/webauthn/src/errors/error-codes.md create mode 100644 docs/identity/auth/webauthn/src/extensions/large-blob/large-blob.md create mode 100644 docs/identity/auth/webauthn/src/extensions/prf/prf.md create mode 100644 docs/identity/auth/webauthn/src/observability/metrics.md create mode 100644 docs/identity/auth/webauthn/src/parser/attestation-object.md create mode 100644 docs/identity/auth/webauthn/src/parser/authenticator-data.md create mode 100644 docs/identity/auth/webauthn/src/parser/client-data.md create mode 100644 docs/identity/auth/webauthn/src/parser/cose-key.md create mode 100644 docs/identity/auth/webauthn/src/register/register.md create mode 100644 docs/identity/auth/webauthn/src/schemas/schemas.md create mode 100644 docs/identity/auth/webauthn/src/verifier/registry.md create mode 100644 docs/identity/auth/webauthn/src/verifier/sign-counter.md create mode 100644 docs/identity/auth/webauthn/src/verifier/verify-assertion.md create mode 100644 docs/identity/auth/webauthn/src/verifier/verify-attestation.md create mode 100644 docs/localization/README.md create mode 100644 docs/localization/_intro.md create mode 100644 docs/localization/i18n/README.md create mode 100644 docs/localization/i18n/_intro.md create mode 100644 docs/localization/i18n/i18n-backend-chained/README.md create mode 100644 docs/localization/i18n/i18n-backend-chained/src/backend/backend.md create mode 100644 docs/localization/i18n/i18n-backend-chained/src/factory/factory.md create mode 100644 docs/localization/i18n/i18n-backend-chained/src/observability/observability.md create mode 100644 docs/localization/i18n/i18n-backend-fs-multifile/README.md create mode 100644 docs/localization/i18n/i18n-backend-fs-multifile/src/backend/backend.md create mode 100644 docs/localization/i18n/i18n-backend-fs-multifile/src/factory/factory.md create mode 100644 docs/localization/i18n/i18n-backend-fs-multifile/src/observability/observability.md create mode 100644 docs/localization/i18n/i18n-backend-http/README.md create mode 100644 docs/localization/i18n/i18n-backend-http/src/backend/backend.md create mode 100644 docs/localization/i18n/i18n-backend-http/src/factory/factory.md create mode 100644 docs/localization/i18n/i18n-backend-http/src/observability/observability.md create mode 100644 docs/localization/i18n/i18n-backend-memory/README.md create mode 100644 docs/localization/i18n/i18n-backend-memory/src/backend/backend.md create mode 100644 docs/localization/i18n/i18n-backend-memory/src/factory/factory.md create mode 100644 docs/localization/i18n/i18n-backend-memory/src/observability/observability.md create mode 100644 docs/localization/i18n/i18n-backend-storage/README.md create mode 100644 docs/localization/i18n/i18n-backend-storage/src/backend/backend.md create mode 100644 docs/localization/i18n/i18n-backend-storage/src/factory/factory.md create mode 100644 docs/localization/i18n/i18n-backend-storage/src/observability/observability.md create mode 100644 docs/localization/i18n/i18n-detector/README.md create mode 100644 docs/localization/i18n/i18n-detector/src/chain/bcp47-negotiate.md create mode 100644 docs/localization/i18n/i18n-detector/src/chain/chain.md create mode 100644 docs/localization/i18n/i18n-detector/src/default-chain/default-chain.md create mode 100644 docs/localization/i18n/i18n-detector/src/detectors/accept-language/accept-language.md create mode 100644 docs/localization/i18n/i18n-detector/src/detectors/cloudflare-ip-geo/cloudflare-ip-geo.md create mode 100644 docs/localization/i18n/i18n-detector/src/detectors/cookie/cookie.md create mode 100644 docs/localization/i18n/i18n-detector/src/detectors/fallback/fallback.md create mode 100644 docs/localization/i18n/i18n-detector/src/detectors/html-lang/html-lang.md create mode 100644 docs/localization/i18n/i18n-detector/src/detectors/local-storage/local-storage.md create mode 100644 docs/localization/i18n/i18n-detector/src/detectors/navigator/navigator.md create mode 100644 docs/localization/i18n/i18n-detector/src/detectors/querystring/querystring.md create mode 100644 docs/localization/i18n/i18n-detector/src/detectors/user-preference/user-preference.md create mode 100644 docs/localization/i18n/i18n-detector/src/direction/direction.md create mode 100644 docs/localization/i18n/i18n-detector/src/observability/metrics.md create mode 100644 docs/localization/i18n/i18n-formatter-collator/README.md create mode 100644 docs/localization/i18n/i18n-formatter-collator/src/formatter/formatter.md create mode 100644 docs/localization/i18n/i18n-formatter-collator/src/helpers/helpers.md create mode 100644 docs/localization/i18n/i18n-formatter-collator/src/observability/observability.md create mode 100644 docs/localization/i18n/i18n-formatter-currency/README.md create mode 100644 docs/localization/i18n/i18n-formatter-currency/src/formatter/formatter.md create mode 100644 docs/localization/i18n/i18n-formatter-currency/src/helpers/helpers.md create mode 100644 docs/localization/i18n/i18n-formatter-currency/src/observability/observability.md create mode 100644 docs/localization/i18n/i18n-formatter-date/README.md create mode 100644 docs/localization/i18n/i18n-formatter-date/src/day-month-names/day-month-names.md create mode 100644 docs/localization/i18n/i18n-formatter-date/src/formatter/formatter.md create mode 100644 docs/localization/i18n/i18n-formatter-date/src/helpers/helpers.md create mode 100644 docs/localization/i18n/i18n-formatter-date/src/observability/observability.md create mode 100644 docs/localization/i18n/i18n-formatter-date/src/presets/presets.md create mode 100644 docs/localization/i18n/i18n-formatter-display-name/README.md create mode 100644 docs/localization/i18n/i18n-formatter-display-name/src/formatter/formatter.md create mode 100644 docs/localization/i18n/i18n-formatter-display-name/src/helpers/helpers.md create mode 100644 docs/localization/i18n/i18n-formatter-display-name/src/observability/observability.md create mode 100644 docs/localization/i18n/i18n-formatter-list/README.md create mode 100644 docs/localization/i18n/i18n-formatter-list/src/formatter/formatter.md create mode 100644 docs/localization/i18n/i18n-formatter-list/src/helpers/helpers.md create mode 100644 docs/localization/i18n/i18n-formatter-list/src/observability/observability.md create mode 100644 docs/localization/i18n/i18n-formatter-number/README.md create mode 100644 docs/localization/i18n/i18n-formatter-number/src/formatter/formatter.md create mode 100644 docs/localization/i18n/i18n-formatter-number/src/helpers/helpers.md create mode 100644 docs/localization/i18n/i18n-formatter-number/src/observability/observability.md create mode 100644 docs/localization/i18n/i18n-formatter-relative-time/README.md create mode 100644 docs/localization/i18n/i18n-formatter-relative-time/src/formatter/formatter.md create mode 100644 docs/localization/i18n/i18n-formatter-relative-time/src/helpers/helpers.md create mode 100644 docs/localization/i18n/i18n-formatter-relative-time/src/observability/observability.md create mode 100644 docs/localization/i18n/i18n-formatter-segmenter/README.md create mode 100644 docs/localization/i18n/i18n-formatter-segmenter/src/formatter/formatter.md create mode 100644 docs/localization/i18n/i18n-formatter-segmenter/src/helpers/helpers.md create mode 100644 docs/localization/i18n/i18n-formatter-segmenter/src/observability/observability.md create mode 100644 docs/localization/i18n/i18n-icu-parser/README.md create mode 100644 docs/localization/i18n/i18n-icu-parser/src/interpolation/escape-html.md create mode 100644 docs/localization/i18n/i18n-icu-parser/src/interpolation/escape-regex.md create mode 100644 docs/localization/i18n/i18n-icu-parser/src/interpolation/interpolation.md create mode 100644 docs/localization/i18n/i18n-icu-parser/src/observability/metrics.md create mode 100644 docs/localization/i18n/i18n-icu-parser/src/parser/format-bridge.md create mode 100644 docs/localization/i18n/i18n-icu-parser/src/parser/message-render.md create mode 100644 docs/localization/i18n/i18n-icu-parser/src/parser/message.md create mode 100644 docs/localization/i18n/i18n-icu-parser/src/pluralization/pluralization.md create mode 100644 docs/localization/i18n/i18n-shared/README.md create mode 100644 docs/localization/i18n/i18n-shared/src/constants/interpolation-defaults.md create mode 100644 docs/localization/i18n/i18n-shared/src/constants/locale-bcp47-map.md create mode 100644 docs/localization/i18n/i18n-shared/src/constants/locale-descriptors.md create mode 100644 docs/localization/i18n/i18n-shared/src/constants/rtl-locales.md create mode 100644 docs/localization/i18n/i18n-shared/src/errors/error-codes.md create mode 100644 docs/localization/i18n/i18n-shared/src/errors/i18n-error.md create mode 100644 docs/localization/i18n/i18n-shared/src/testing/conformance.md create mode 100644 docs/localization/i18n/i18n/README.md create mode 100644 docs/localization/i18n/i18n/src/core/catalog/catalog.md create mode 100644 docs/localization/i18n/i18n/src/core/plugin/instance.md create mode 100644 docs/localization/i18n/i18n/src/locale/negotiation/negotiation.md create mode 100644 docs/localization/i18n/i18n/src/locale/resolver/resolver.md create mode 100644 docs/localization/i18n/i18n/src/middleware/server/server.md create mode 100644 docs/localization/i18n/i18n/src/observability/backend-metrics.md create mode 100644 docs/localization/i18n/i18n/src/observability/detector-metrics.md create mode 100644 docs/localization/i18n/i18n/src/observability/metrics.md create mode 100644 docs/localization/i18n/i18n/src/parser/format-bridge-default/format-bridge-default.md create mode 100644 docs/localization/i18n/i18n/src/post-processors/missing-key-reporter.md create mode 100644 docs/localization/i18n/i18n/src/post-processors/pseudo-localize.md create mode 100644 docs/localization/i18n/i18n/src/schemas/i18n.schemas.md create mode 100644 docs/localization/i18n/i18n/src/utils/utils.md create mode 100644 docs/localization/i18n/locale-data/README.md create mode 100644 docs/localization/i18n/locale-data/src/countries/countries.data.md create mode 100644 docs/localization/i18n/locale-data/src/countries/countries.md create mode 100644 docs/localization/i18n/locale-data/src/errors/locale-data-error.md create mode 100644 docs/localization/i18n/locale-data/src/languages/languages.data.md create mode 100644 docs/localization/i18n/locale-data/src/languages/languages.md create mode 100644 docs/localization/i18n/locale-data/src/types/types.md create mode 100644 docs/localization/i18n/react-i18n/README.md create mode 100644 docs/localization/i18n/react-i18n/src/components/i18n-suspense/fallback-bundle.md create mode 100644 docs/localization/i18n/react-i18n/src/components/i18n-suspense/i18n-suspense.md create mode 100644 docs/localization/i18n/react-i18n/src/components/language-switcher/language-switcher.md create mode 100644 docs/localization/i18n/react-i18n/src/components/missing-key-overlay/missing-key-overlay.md create mode 100644 docs/localization/i18n/react-i18n/src/components/trans/stringify-children.md create mode 100644 docs/localization/i18n/react-i18n/src/components/trans/trans.md create mode 100644 docs/localization/i18n/react-i18n/src/config/create-i18n-config.md create mode 100644 docs/localization/i18n/react-i18n/src/config/to-i18n-instance-options.md create mode 100644 docs/localization/i18n/react-i18n/src/detector/accept-language/accept-language.md create mode 100644 docs/localization/i18n/react-i18n/src/detector/cloudflare-ip-geo/cloudflare-ip-geo.md create mode 100644 docs/localization/i18n/react-i18n/src/detector/cookie/cookie.md create mode 100644 docs/localization/i18n/react-i18n/src/detector/default-chain/default-chain.md create mode 100644 docs/localization/i18n/react-i18n/src/detector/fallback/fallback.md create mode 100644 docs/localization/i18n/react-i18n/src/detector/html-lang/html-lang.md create mode 100644 docs/localization/i18n/react-i18n/src/detector/local-storage/local-storage.md create mode 100644 docs/localization/i18n/react-i18n/src/detector/navigator/navigator.md create mode 100644 docs/localization/i18n/react-i18n/src/detector/querystring/querystring.md create mode 100644 docs/localization/i18n/react-i18n/src/detector/user-preference/user-preference.md create mode 100644 docs/localization/i18n/react-i18n/src/errors/error-codes.md create mode 100644 docs/localization/i18n/react-i18n/src/hoc/with-translation/with-translation.md create mode 100644 docs/localization/i18n/react-i18n/src/hooks/use-currency/use-currency.md create mode 100644 docs/localization/i18n/react-i18n/src/hooks/use-date/use-date.md create mode 100644 docs/localization/i18n/react-i18n/src/hooks/use-direction/use-direction.md create mode 100644 docs/localization/i18n/react-i18n/src/hooks/use-error-message/use-error-message.md create mode 100644 docs/localization/i18n/react-i18n/src/hooks/use-formatter/use-formatter.md create mode 100644 docs/localization/i18n/react-i18n/src/hooks/use-i18n/use-i18n.md create mode 100644 docs/localization/i18n/react-i18n/src/hooks/use-list/use-list.md create mode 100644 docs/localization/i18n/react-i18n/src/hooks/use-locale-adapter/use-locale-adapter.md create mode 100644 docs/localization/i18n/react-i18n/src/hooks/use-locale-detection/detector-chain-context.md create mode 100644 docs/localization/i18n/react-i18n/src/hooks/use-locale-detection/use-locale-detection.md create mode 100644 docs/localization/i18n/react-i18n/src/hooks/use-locale/use-locale.md create mode 100644 docs/localization/i18n/react-i18n/src/hooks/use-number/use-number.md create mode 100644 docs/localization/i18n/react-i18n/src/hooks/use-plural/use-plural.md create mode 100644 docs/localization/i18n/react-i18n/src/hooks/use-relative-time/use-relative-time.md create mode 100644 docs/localization/i18n/react-i18n/src/hooks/use-translate/use-translate.md create mode 100644 docs/localization/i18n/react-i18n/src/hooks/use-translation/use-translation.md create mode 100644 docs/localization/i18n/react-i18n/src/observability/react-i18n-metrics.md create mode 100644 docs/localization/i18n/react-i18n/src/provider/provider-context.md create mode 100644 docs/localization/i18n/react-i18n/src/provider/provider.md create mode 100644 docs/localization/i18n/react-i18n/src/registry/formatters/built-in/built-in.md create mode 100644 docs/localization/i18n/react-i18n/src/registry/locale-adapters/built-in/built-in.md create mode 100644 docs/localization/i18n/react-i18n/src/registry/post-processors/post-processors.md create mode 100644 docs/localization/i18n/react-i18n/src/registry/registry-context.md create mode 100644 docs/localization/i18n/react-i18n/src/registry/registry-provider.md create mode 100644 docs/localization/i18n/react-i18n/src/registry/registry.md create mode 100644 docs/localization/i18n/react-i18n/src/registry/registry.schemas.md create mode 100644 docs/localization/i18n/react-i18n/src/registry/use-registry.md create mode 100644 docs/localization/i18n/react-i18n/src/schemas/i18n-config.schemas.md create mode 100644 docs/localization/i18n/react-i18n/src/translation-key/t-dynamic.md create mode 100644 docs/localization/i18n/react-i18n/src/translation-key/translation-key.md create mode 100644 docs/localization/i18n/react-i18n/src/utils/env.md create mode 100644 docs/localization/i18n/react-i18n/src/utils/identity-instance.md create mode 100644 docs/localization/i18n/react-i18n/src/utils/warn-once-per-process.md create mode 100644 docs/media/README.md create mode 100644 docs/media/_intro.md create mode 100644 docs/media/audio-fx/README.md create mode 100644 docs/media/audio-fx/_intro.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-audio-analyzer/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-audio-analyzer/src/audio-analyzer.types.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-audio-analyzer/src/audio-analyzer/audio-analyzer.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-audio-analyzer/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-audio-player/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-audio-player/src/audio-player.types.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-audio-player/src/audio-player/audio-player.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-audio-player/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-auto-filter/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-auto-filter/src/auto-filter.types.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-auto-filter/src/auto-filter/auto-filter.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-auto-filter/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-base/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-base/src/base/audio-fx-plugin.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-base/src/base/capabilities.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-base/src/base/parameter-schedule.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-base/src/base/plugin-internals/plugin-internals.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-base/src/base/plugin-io.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-base/src/base/preset.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-base/src/biquad/biquad.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-base/src/chain/ambient-state.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-base/src/chain/bus-registry.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-base/src/chain/chain.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-base/src/chain/context/context.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-base/src/chain/event-bus/event-bus.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-base/src/chain/insert/insert.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-base/src/chain/lifecycle/lifecycle.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-base/src/chain/snapshot/snapshot.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-base/src/error-codes/error-codes.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-base/src/registry/registry.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-chorus/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-chorus/src/chorus.types.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-chorus/src/chorus/chorus.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-chorus/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-compressor/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-compressor/src/compressor/compressor.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-compressor/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-delay/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-delay/src/delay/delay.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-delay/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-distortion/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-distortion/src/distortion.types.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-distortion/src/distortion/distortion.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-distortion/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-eq/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-eq/src/eq/eq.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-eq/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-filter/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-filter/src/filter/filter.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-filter/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-flanger/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-flanger/src/flanger.types.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-flanger/src/flanger/flanger.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-flanger/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-game-audio/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-game-audio/src/game-audio.types.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-game-audio/src/game-audio/game-audio.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-game-audio/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-gate/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-gate/src/gate/gate.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-gate/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-glados/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-glados/src/glados.types.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-glados/src/glados/glados.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-glados/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-limiter/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-limiter/src/limiter.types.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-limiter/src/limiter/limiter.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-limiter/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-microphone/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-microphone/src/microphone.types.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-microphone/src/microphone/microphone.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-microphone/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-mixer/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-mixer/src/mixer.types.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-mixer/src/mixer/mixer.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-mixer/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-phaser/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-phaser/src/phaser.types.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-phaser/src/phaser/phaser.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-phaser/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-pitch-shifter/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-pitch-shifter/src/pitch-shifter.types.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-pitch-shifter/src/pitch-shifter/pitch-shifter.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-pitch-shifter/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-reverb/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-reverb/src/engines/engines.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-reverb/src/reverb/reverb.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-reverb/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-sampler/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-sampler/src/sampler.types.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-sampler/src/sampler/sampler.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-sampler/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-spatial/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-spatial/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-spatial/src/spatial.types.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-spatial/src/spatial/spatial.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-spessasynth/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-spessasynth/src/error-codes/error-codes.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-spessasynth/src/loader/soundfont-loader.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-spessasynth/src/midi-router/midi-router.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-spessasynth/src/parameters/parameters.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-spessasynth/src/plugin/spessasynth-plugin.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-spessasynth/src/register/register.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-spessasynth/src/telemetry/telemetry.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-spessasynth/src/types/midi.types.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-spessasynth/src/voice-manager/voice-manager.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-synthesizer/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-synthesizer/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-synthesizer/src/synthesizer.types.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-synthesizer/src/synthesizer/synthesizer.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-tremolo/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-tremolo/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-tremolo/src/tremolo.types.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-tremolo/src/tremolo/tremolo.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-widener/README.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-widener/src/schemas/schemas.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-widener/src/widener.types.md create mode 100644 docs/media/audio-fx/audio-fx-plugin-widener/src/widener/widener.md create mode 100644 docs/media/audio-ir/README.md create mode 100644 docs/media/audio-ir/_intro.md create mode 100644 docs/media/audio-ir/audio-ir-core/README.md create mode 100644 docs/media/audio-ir/audio-ir-core/src/error-codes/error-codes.md create mode 100644 docs/media/audio-ir/audio-ir-core/src/otel/otel.md create mode 100644 docs/media/audio-ir/audio-ir-core/src/registrar/registrar.md create mode 100644 docs/media/audio-ir/audio-ir-core/src/registry/register-manifest.md create mode 100644 docs/media/audio-ir/audio-ir-core/src/registry/registry.md create mode 100644 docs/media/audio-ir/audio-ir-core/src/types/impulse-response.md create mode 100644 docs/media/audio-ir/audio-ir-core/src/types/manifest-entry.md create mode 100644 docs/media/audio-ir/audio-ir-core/src/types/manifest.md create mode 100644 docs/media/audio-ir/audio-ir-loader/README.md create mode 100644 docs/media/audio-ir/audio-ir-loader/src/cache/cache.md create mode 100644 docs/media/audio-ir/audio-ir-loader/src/error-codes/error-codes.md create mode 100644 docs/media/audio-ir/audio-ir-loader/src/loader/extension.md create mode 100644 docs/media/audio-ir/audio-ir-loader/src/loader/loader.md create mode 100644 docs/media/audio-ir/audio-ir-loader/src/loader/manifest-validation.md create mode 100644 docs/media/audio-ir/audio-ir-loader/src/loader/preload.md create mode 100644 docs/media/audio-ir/audio-ir-loader/src/otel/otel.md create mode 100644 docs/media/audio-ir/audio-ir-room-plugin-club/README.md create mode 100644 docs/media/audio-ir/audio-ir-room-plugin-club/src/manifest/manifest.md create mode 100644 docs/media/audio-ir/audio-ir-room-plugin-club/src/register/register.md create mode 100644 docs/media/audio-ir/audio-ir-room-plugin-pool/README.md create mode 100644 docs/media/audio-ir/audio-ir-room-plugin-pool/src/manifest/manifest.md create mode 100644 docs/media/audio-ir/audio-ir-room-plugin-pool/src/register/register.md create mode 100644 docs/media/audio/README.md create mode 100644 docs/media/audio/_intro.md create mode 100644 docs/media/audio/audio-analysis-beat/README.md create mode 100644 docs/media/audio/audio-analysis-beat/src/algorithms/beat-grid.md create mode 100644 docs/media/audio/audio-analysis-beat/src/algorithms/comb-tempo.md create mode 100644 docs/media/audio/audio-analysis-beat/src/algorithms/energy-odf.md create mode 100644 docs/media/audio/audio-analysis-beat/src/algorithms/spectral-flux.md create mode 100644 docs/media/audio/audio-analysis-beat/src/detector/beat-detector.md create mode 100644 docs/media/audio/audio-analysis-beat/src/error-codes/error-codes.md create mode 100644 docs/media/audio/audio-analysis-loudness/README.md create mode 100644 docs/media/audio/audio-analysis-loudness/src/algorithms/loudness-range.md create mode 100644 docs/media/audio/audio-analysis-loudness/src/algorithms/lufs.md create mode 100644 docs/media/audio/audio-analysis-loudness/src/algorithms/true-peak.md create mode 100644 docs/media/audio/audio-analysis-loudness/src/error-codes/error-codes.md create mode 100644 docs/media/audio/audio-analysis-loudness/src/filters/k-weighting.md create mode 100644 docs/media/audio/audio-analysis-loudness/src/meter/loudness-meter.md create mode 100644 docs/media/audio/audio-analysis-pitch/README.md create mode 100644 docs/media/audio/audio-analysis-pitch/src/algorithms/chord-matching.md create mode 100644 docs/media/audio/audio-analysis-pitch/src/algorithms/chromagram.md create mode 100644 docs/media/audio/audio-analysis-pitch/src/algorithms/downmix.md create mode 100644 docs/media/audio/audio-analysis-pitch/src/algorithms/key-finding.md create mode 100644 docs/media/audio/audio-analysis-pitch/src/algorithms/yin.md create mode 100644 docs/media/audio/audio-analysis-pitch/src/detector/chord-detector.md create mode 100644 docs/media/audio/audio-analysis-pitch/src/detector/key-detector.md create mode 100644 docs/media/audio/audio-analysis-pitch/src/detector/pitch-detector.md create mode 100644 docs/media/audio/audio-analysis-pitch/src/error-codes/error-codes.md create mode 100644 docs/media/audio/audio-analysis-spectrum/README.md create mode 100644 docs/media/audio/audio-analysis-spectrum/src/algorithms/dct.md create mode 100644 docs/media/audio/audio-analysis-spectrum/src/algorithms/fft.md create mode 100644 docs/media/audio/audio-analysis-spectrum/src/algorithms/mel-scale.md create mode 100644 docs/media/audio/audio-analysis-spectrum/src/algorithms/window.md create mode 100644 docs/media/audio/audio-analysis-spectrum/src/analyzer/dsp.md create mode 100644 docs/media/audio/audio-analysis-spectrum/src/analyzer/mfcc.md create mode 100644 docs/media/audio/audio-analysis-spectrum/src/analyzer/runtime.md create mode 100644 docs/media/audio/audio-analysis-spectrum/src/analyzer/spectrogram.md create mode 100644 docs/media/audio/audio-analysis-spectrum/src/analyzer/spectrum-analyzer.md create mode 100644 docs/media/audio/audio-analysis-spectrum/src/error-codes/error-codes.md create mode 100644 docs/media/audio/audio-cli/README.md create mode 100644 docs/media/audio/audio-cli/src/bin/bin.md create mode 100644 docs/media/audio/audio-cli/src/cli/cli.md create mode 100644 docs/media/audio/audio-cli/src/commands/analyze.md create mode 100644 docs/media/audio/audio-cli/src/commands/batch.md create mode 100644 docs/media/audio/audio-cli/src/commands/convert.md create mode 100644 docs/media/audio/audio-cli/src/commands/info.md create mode 100644 docs/media/audio/audio-cli/src/commands/play.md create mode 100644 docs/media/audio/audio-cli/src/commands/process.md create mode 100644 docs/media/audio/audio-cli/src/commands/record.md create mode 100644 docs/media/audio/audio-cli/src/error-codes/error-codes.md create mode 100644 docs/media/audio/audio-cli/src/pipeline/parser.md create mode 100644 docs/media/audio/audio-codec-ffmpeg-native/README.md create mode 100644 docs/media/audio/audio-codec-ffmpeg-native/src/binary/binary.md create mode 100644 docs/media/audio/audio-codec-ffmpeg-native/src/codec/codec.md create mode 100644 docs/media/audio/audio-codec-ffmpeg-native/src/codec/pcm.md create mode 100644 docs/media/audio/audio-codec-ffmpeg-native/src/error-codes/error-codes.md create mode 100644 docs/media/audio/audio-codec-ffmpeg-native/src/register/register.md create mode 100644 docs/media/audio/audio-codec-ffmpeg-native/src/runner/runner.md create mode 100644 docs/media/audio/audio-codec-ffmpeg-native/src/stream/stream-decoder.md create mode 100644 docs/media/audio/audio-codec-ffmpeg-native/src/stream/stream-encoder.md create mode 100644 docs/media/audio/audio-codec-ffmpeg-wasm/README.md create mode 100644 docs/media/audio/audio-codec-ffmpeg-wasm/src/codec/ffmpeg-wasm-codec.md create mode 100644 docs/media/audio/audio-codec-ffmpeg-wasm/src/core-loader/core-loader.md create mode 100644 docs/media/audio/audio-codec-ffmpeg-wasm/src/decode/decode-pipeline.md create mode 100644 docs/media/audio/audio-codec-ffmpeg-wasm/src/encode/encode-pipeline.md create mode 100644 docs/media/audio/audio-codec-ffmpeg-wasm/src/error-codes/error-codes.md create mode 100644 docs/media/audio/audio-codec-ffmpeg-wasm/src/register/register.md create mode 100644 docs/media/audio/audio-codec-ffmpeg-wasm/src/streaming/streaming-decoder.md create mode 100644 docs/media/audio/audio-codec-ffmpeg-wasm/src/streaming/streaming-encoder.md create mode 100644 docs/media/audio/audio-codec-ffmpeg-wasm/src/worker/worker-host.md create mode 100644 docs/media/audio/audio-codecs/README.md create mode 100644 docs/media/audio/audio-codecs/src/codecs/aac.md create mode 100644 docs/media/audio/audio-codecs/src/codecs/aiff.md create mode 100644 docs/media/audio/audio-codecs/src/codecs/caf.md create mode 100644 docs/media/audio/audio-codecs/src/codecs/flac.md create mode 100644 docs/media/audio/audio-codecs/src/codecs/mp3.md create mode 100644 docs/media/audio/audio-codecs/src/codecs/ogg-vorbis.md create mode 100644 docs/media/audio/audio-codecs/src/codecs/opus.md create mode 100644 docs/media/audio/audio-codecs/src/codecs/qoa.md create mode 100644 docs/media/audio/audio-codecs/src/codecs/wasm-base.md create mode 100644 docs/media/audio/audio-codecs/src/codecs/wav.md create mode 100644 docs/media/audio/audio-codecs/src/codecs/webm.md create mode 100644 docs/media/audio/audio-codecs/src/decode/decode-source.md create mode 100644 docs/media/audio/audio-codecs/src/detect/detect-format.md create mode 100644 docs/media/audio/audio-codecs/src/encode/encode-to.md create mode 100644 docs/media/audio/audio-codecs/src/error-codes/error-codes.md create mode 100644 docs/media/audio/audio-codecs/src/registry/registry.md create mode 100644 docs/media/audio/audio-codecs/src/stream/stream-decoder.md create mode 100644 docs/media/audio/audio-codecs/src/stream/stream-encoder.md create mode 100644 docs/media/audio/audio-controllers/README.md create mode 100644 docs/media/audio/audio-controllers/src/arpeggiator/arpeggiator.md create mode 100644 docs/media/audio/audio-controllers/src/base/connection-fsm.md create mode 100644 docs/media/audio/audio-controllers/src/base/midi-controller-plugin.md create mode 100644 docs/media/audio/audio-controllers/src/base/otel.md create mode 100644 docs/media/audio/audio-controllers/src/binding/bind-parameter.md create mode 100644 docs/media/audio/audio-controllers/src/error-codes/error-codes.md create mode 100644 docs/media/audio/audio-controllers/src/learn/learn-mode.md create mode 100644 docs/media/audio/audio-controllers/src/plugins/kontrol-s88/kontrol-s88.md create mode 100644 docs/media/audio/audio-controllers/src/plugins/maschine/maschine.md create mode 100644 docs/media/audio/audio-controllers/src/plugins/traktor-s4/traktor-s4.md create mode 100644 docs/media/audio/audio-controllers/src/sequencer/sequencer.md create mode 100644 docs/media/audio/audio-core/README.md create mode 100644 docs/media/audio/audio-core/src/analysis/analysis-op.md create mode 100644 docs/media/audio/audio-core/src/document/document.md create mode 100644 docs/media/audio/audio-core/src/error-codes/error-codes.md create mode 100644 docs/media/audio/audio-core/src/page/page.md create mode 100644 docs/media/audio/audio-core/src/plan/plan-engine.md create mode 100644 docs/media/audio/audio-core/src/plan/segment.md create mode 100644 docs/media/audio/audio-core/src/process/block-processor.md create mode 100644 docs/media/audio/audio-core/src/process/process-pipeline.md create mode 100644 docs/media/audio/audio-core/src/registry/built-in/crop.md create mode 100644 docs/media/audio/audio-core/src/registry/built-in/dither.md create mode 100644 docs/media/audio/audio-core/src/registry/built-in/fade.md create mode 100644 docs/media/audio/audio-core/src/registry/built-in/gain.md create mode 100644 docs/media/audio/audio-core/src/registry/built-in/insert.md create mode 100644 docs/media/audio/audio-core/src/registry/built-in/mix.md create mode 100644 docs/media/audio/audio-core/src/registry/built-in/normalize.md create mode 100644 docs/media/audio/audio-core/src/registry/built-in/pad.md create mode 100644 docs/media/audio/audio-core/src/registry/built-in/pan.md create mode 100644 docs/media/audio/audio-core/src/registry/built-in/remove.md create mode 100644 docs/media/audio/audio-core/src/registry/built-in/repeat.md create mode 100644 docs/media/audio/audio-core/src/registry/built-in/resample.md create mode 100644 docs/media/audio/audio-core/src/registry/built-in/reverse.md create mode 100644 docs/media/audio/audio-core/src/registry/built-in/speed.md create mode 100644 docs/media/audio/audio-core/src/registry/built-in/stretch.md create mode 100644 docs/media/audio/audio-core/src/registry/built-in/transform.md create mode 100644 docs/media/audio/audio-core/src/registry/built-in/trim.md create mode 100644 docs/media/audio/audio-core/src/registry/op-registry.md create mode 100644 docs/media/audio/audio-core/src/render/render.md create mode 100644 docs/media/audio/audio-core/src/stats/stats.md create mode 100644 docs/media/audio/audio-core/src/stream/stream.md create mode 100644 docs/media/audio/audio-core/src/telemetry/telemetry.md create mode 100644 docs/media/audio/audio-decode-wav/README.md create mode 100644 docs/media/audio/audio-decode-wav/src/decode-wav/decode-wav.md create mode 100644 docs/media/audio/audio-decode-wav/src/error-codes/error-codes.md create mode 100644 docs/media/audio/audio-decode-wav/src/otel/otel.md create mode 100644 docs/media/audio/audio-decode-wav/src/stream/stream.md create mode 100644 docs/media/audio/audio-decode-wav/src/types/decoded-audio.md create mode 100644 docs/media/audio/audio-decode-wav/src/types/options.md create mode 100644 docs/media/audio/audio-decode-wav/src/utils/inspect.md create mode 100644 docs/media/audio/audio-engine-browser/README.md create mode 100644 docs/media/audio/audio-engine-browser/src/adapter/adapter-introspection.md create mode 100644 docs/media/audio/audio-engine-browser/src/adapter/adapter-lifecycle.md create mode 100644 docs/media/audio/audio-engine-browser/src/adapter/adapter-track-ops.md create mode 100644 docs/media/audio/audio-engine-browser/src/adapter/browser-adapter.md create mode 100644 docs/media/audio/audio-engine-browser/src/adapter/bus-orchestrator.md create mode 100644 docs/media/audio/audio-engine-browser/src/adapter/fx-host.md create mode 100644 docs/media/audio/audio-engine-browser/src/adapter/mixer-state.md create mode 100644 docs/media/audio/audio-engine-browser/src/adapter/standardized-audio-context-bridge.md create mode 100644 docs/media/audio/audio-engine-browser/src/adapter/track-subgraph.md create mode 100644 docs/media/audio/audio-engine-browser/src/decode/decode.md create mode 100644 docs/media/audio/audio-engine-browser/src/error-codes/error-codes.md create mode 100644 docs/media/audio/audio-engine-browser/src/fallback/html5-fallback.md create mode 100644 docs/media/audio/audio-engine-browser/src/graph/web-audio-graph.md create mode 100644 docs/media/audio/audio-engine-browser/src/offline/offline-render.md create mode 100644 docs/media/audio/audio-engine-browser/src/worklet/worklet-manager.md create mode 100644 docs/media/audio/audio-engine-server/README.md create mode 100644 docs/media/audio/audio-engine-server/src/adapter/bus-orchestrator.md create mode 100644 docs/media/audio/audio-engine-server/src/adapter/server-adapter.md create mode 100644 docs/media/audio/audio-engine-server/src/fx/plugin-chain.md create mode 100644 docs/media/audio/audio-engine-server/src/internal/fs-like.md create mode 100644 docs/media/audio/audio-engine-server/src/internal/sanitize-path.md create mode 100644 docs/media/audio/audio-engine-server/src/sink/file-sink.md create mode 100644 docs/media/audio/audio-engine-server/src/source/file-source.md create mode 100644 docs/media/audio/audio-fingerprint/README.md create mode 100644 docs/media/audio/audio-fingerprint/src/api/app.md create mode 100644 docs/media/audio/audio-fingerprint/src/client/python-audio-service.md create mode 100644 docs/media/audio/audio-fingerprint/src/fingerprint.md create mode 100644 docs/media/audio/audio-metadata/README.md create mode 100644 docs/media/audio/audio-metadata/src/core/extractor/extractor.md create mode 100644 docs/media/audio/audio-metadata/src/errors/metadata-error.md create mode 100644 docs/media/audio/audio-metadata/src/parsers/aiff-id3/aiff-id3.md create mode 100644 docs/media/audio/audio-metadata/src/parsers/flac-vorbis/flac-vorbis.md create mode 100644 docs/media/audio/audio-metadata/src/parsers/format-detector/format-detector.md create mode 100644 docs/media/audio/audio-metadata/src/parsers/id3v1/id3v1.md create mode 100644 docs/media/audio/audio-metadata/src/parsers/id3v2/id3v2.md create mode 100644 docs/media/audio/audio-metadata/src/parsers/mp4-atom/mp4-atom.md create mode 100644 docs/media/audio/audio-metadata/src/parsers/ogg-vorbis/ogg-vorbis.md create mode 100644 docs/media/audio/audio-metadata/src/parsers/wav-riff/wav-riff.md create mode 100644 docs/media/audio/audio-metadata/src/types/metadata.types.md create mode 100644 docs/media/audio/audio-metadata/src/utils/buffer-utils.md create mode 100644 docs/media/audio/audio-sprite-packer/README.md create mode 100644 docs/media/audio/audio-sprite-packer/src/__benchmarks__/audio-sprite-packer.bench.md create mode 100644 docs/media/audio/audio-sprite-packer/src/adapters/null-adapter/null-adapter.md create mode 100644 docs/media/audio/audio-sprite-packer/src/core/audio-sprite-packer/audio-sprite-packer.md create mode 100644 docs/media/audio/audio-sprite-packer/src/error-codes/error-codes.md create mode 100644 docs/media/audio/audio-sprite-packer/src/types/common.md create mode 100644 docs/media/audio/audio-sprite-packer/src/utils/manifest/manifest.md create mode 100644 docs/media/audio/audio-sprite-player/README.md create mode 100644 docs/media/audio/audio-sprite-player/src/adapter/adapter.md create mode 100644 docs/media/audio/audio-sprite-player/src/adapter/null/null.md create mode 100644 docs/media/audio/audio-sprite-player/src/error-codes/error-codes.md create mode 100644 docs/media/audio/audio-sprite-player/src/events/events.md create mode 100644 docs/media/audio/audio-sprite-player/src/schemas/schemas.md create mode 100644 docs/media/audio/audio-sprite-player/src/sprite-player/sprite-player.md create mode 100644 docs/media/audio/audio-sprite-player/src/telemetry/telemetry.md create mode 100644 docs/media/audio/audio-sprite-player/src/voice-manager/voice-manager.md create mode 100644 docs/media/audio/audio-timeline/README.md create mode 100644 docs/media/audio/audio-timeline/SPEC_CHECKLIST.md create mode 100644 docs/media/audio/audio-timeline/src/adapter/adapter.md create mode 100644 docs/media/audio/audio-timeline/src/clip/clip.md create mode 100644 docs/media/audio/audio-timeline/src/engine/clip/clip.md create mode 100644 docs/media/audio/audio-timeline/src/engine/engine.md create mode 100644 docs/media/audio/audio-timeline/src/engine/mixer/mixer.md create mode 100644 docs/media/audio/audio-timeline/src/engine/state/state.md create mode 100644 docs/media/audio/audio-timeline/src/engine/transport-fsm/transport-fsm.md create mode 100644 docs/media/audio/audio-timeline/src/engine/transport/transport.md create mode 100644 docs/media/audio/audio-timeline/src/engine/undo/undo.md create mode 100644 docs/media/audio/audio-timeline/src/engine/zoom/zoom.md create mode 100644 docs/media/audio/audio-timeline/src/error-codes/error-codes.md create mode 100644 docs/media/audio/audio-timeline/src/mixer/mixer.md create mode 100644 docs/media/audio/audio-timeline/src/operations/clip-operations/clip-operations.md create mode 100644 docs/media/audio/audio-timeline/src/operations/timeline-operations/timeline-operations.md create mode 100644 docs/media/audio/audio-timeline/src/track/track.md create mode 100644 docs/media/audio/audio-timeline/src/zoom/zoom.md create mode 100644 docs/media/audio/audio-transport/README.md create mode 100644 docs/media/audio/audio-transport/src/error-codes/error-codes.md create mode 100644 docs/media/audio/audio-transport/src/scheduler/scheduler.md create mode 100644 docs/media/audio/audio-transport/src/scheduler/scheduler.schemas.md create mode 100644 docs/media/audio/audio-transport/src/signal/signal.md create mode 100644 docs/media/audio/audio-transport/src/signal/signal.schemas.md create mode 100644 docs/media/audio/audio-transport/src/tick-source/tick-source.md create mode 100644 docs/media/audio/audio-transport/src/tick-source/tick-source.schemas.md create mode 100644 docs/media/audio/audio-transport/src/time/time.md create mode 100644 docs/media/audio/audio-transport/src/time/time.schemas.md create mode 100644 docs/media/audio/audio-transport/src/transport/transport.md create mode 100644 docs/media/audio/audio-transport/src/transport/transport.schemas.md create mode 100644 docs/media/audio/control-surface-schema/README.md create mode 100644 docs/media/audio/control-surface-schema/src/constants/constants.md create mode 100644 docs/media/audio/control-surface-schema/src/error-codes/error-codes.md create mode 100644 docs/media/audio/control-surface-schema/src/identity/identity.md create mode 100644 docs/media/audio/control-surface-schema/src/schemas/control-surface-schema.md create mode 100644 docs/media/audio/control-surface-schema/src/types/action.types.md create mode 100644 docs/media/audio/control-surface-schema/src/types/appearance.types.md create mode 100644 docs/media/audio/control-surface-schema/src/types/behaviour.types.md create mode 100644 docs/media/audio/control-surface-schema/src/types/binding.types.md create mode 100644 docs/media/audio/control-surface-schema/src/types/control-kind.types.md create mode 100644 docs/media/audio/control-surface-schema/src/types/control-node.types.md create mode 100644 docs/media/audio/control-surface-schema/src/types/control-surface.types.md create mode 100644 docs/media/audio/control-surface-schema/src/types/group-layout.types.md create mode 100644 docs/media/audio/control-surface-schema/src/types/range.types.md create mode 100644 docs/media/audio/control-surface-schema/src/types/transform.types.md create mode 100644 docs/media/audio/control-surface-schema/src/upgrade/upgrade.md create mode 100644 docs/media/audio/control-surface-schema/src/validate/validate.md create mode 100644 docs/media/audio/control-surface-schema/src/walk/walk.md create mode 100644 docs/media/audio/midi/README.md create mode 100644 docs/media/audio/midi/src/clock/clock.md create mode 100644 docs/media/audio/midi/src/dispatch/cc14.md create mode 100644 docs/media/audio/midi/src/dispatch/nrpn.md create mode 100644 docs/media/audio/midi/src/dispatch/rpn.md create mode 100644 docs/media/audio/midi/src/dispatch/running-status.md create mode 100644 docs/media/audio/midi/src/error-codes/error-codes.md create mode 100644 docs/media/audio/midi/src/gm/gs.md create mode 100644 docs/media/audio/midi/src/gm/level1.md create mode 100644 docs/media/audio/midi/src/gm/level2.md create mode 100644 docs/media/audio/midi/src/gm/xg.md create mode 100644 docs/media/audio/midi/src/message/decode.md create mode 100644 docs/media/audio/midi/src/message/encode.md create mode 100644 docs/media/audio/midi/src/sysex/manufacturers.md create mode 100644 docs/media/audio/midi/src/sysex/sysex.md create mode 100644 docs/media/audio/midi/src/telemetry/telemetry.md create mode 100644 docs/media/audio/midi/src/ump/ump.md create mode 100644 docs/media/audio/third-party-elevenlabs/README.md create mode 100644 docs/media/audio/third-party-elevenlabs/src/client/client.md create mode 100644 docs/media/audio/third-party-elevenlabs/src/client/headers.md create mode 100644 docs/media/audio/third-party-elevenlabs/src/client/internals.md create mode 100644 docs/media/audio/third-party-elevenlabs/src/client/socket.md create mode 100644 docs/media/audio/third-party-elevenlabs/src/client/url.md create mode 100644 docs/media/audio/third-party-elevenlabs/src/errors/errors.md create mode 100644 docs/media/audio/third-party-elevenlabs/src/types/types.md create mode 100644 docs/media/audio/voice-elevenlabs/README.md create mode 100644 docs/media/audio/voice-elevenlabs/src/factory/create-elevenlabs-voice.md create mode 100644 docs/media/audio/voice-elevenlabs/src/models/models.md create mode 100644 docs/media/audio/voice-elevenlabs/src/sound-effects/sound-effects.md create mode 100644 docs/media/audio/voice-elevenlabs/src/speech-to-speech/speech-to-speech.md create mode 100644 docs/media/audio/voice-elevenlabs/src/stt/stt.md create mode 100644 docs/media/audio/voice-elevenlabs/src/tts/tts.md create mode 100644 docs/media/audio/voice-elevenlabs/src/voice-isolation/voice-isolation.md create mode 100644 docs/media/audio/voice-elevenlabs/src/voices/voices.md create mode 100644 docs/media/audio/voice/README.md create mode 100644 docs/media/audio/voice/src/effects/effects.md create mode 100644 docs/media/audio/voice/src/errors/errors.md create mode 100644 docs/media/audio/voice/src/isolation/isolation.md create mode 100644 docs/media/audio/voice/src/stt/stt.md create mode 100644 docs/media/audio/voice/src/tts/tts.md create mode 100644 docs/media/audio/voice/src/types/types.md create mode 100644 docs/media/audio/voice/src/voices/voices.md create mode 100644 docs/media/fonts/README.md create mode 100644 docs/media/fonts/_intro.md create mode 100644 docs/media/fonts/font-compress/README.md create mode 100644 docs/media/fonts/font-compress/src/bin/auto-boot.md create mode 100644 docs/media/fonts/font-compress/src/bin/dispatch.md create mode 100644 docs/media/fonts/font-compress/src/bin/format-utils.md create mode 100644 docs/media/fonts/font-compress/src/bin/parser.md create mode 100644 docs/media/fonts/font-compress/src/bin/printer.md create mode 100644 docs/media/fonts/font-compress/src/bin/suaveplan-font-compress.md create mode 100644 docs/media/fonts/font-compress/src/error-codes/error-codes.md create mode 100644 docs/media/fonts/font-compress/src/packer/binary-font-packer/binary-font-packer.md create mode 100644 docs/media/fonts/font-compress/src/utils/encode-string.md create mode 100644 docs/media/fonts/font-compress/src/utils/parse-path.md create mode 100644 docs/media/fonts/font-convert/README.md create mode 100644 docs/media/fonts/font-convert/src/core/batch-converter/batch-converter.md create mode 100644 docs/media/fonts/font-convert/src/core/font-converter/font-converter.md create mode 100644 docs/media/fonts/font-convert/src/types/typeface.md create mode 100644 docs/media/fonts/font-convert/src/utils/outline-to-string.md create mode 100644 docs/media/fonts/font-convert/src/utils/reverse-winding.md create mode 100644 docs/media/fonts/font-decompress/README.md create mode 100644 docs/media/fonts/font-decompress/src/error-codes/error-codes.md create mode 100644 docs/media/fonts/font-decompress/src/unpacker/binary-font-unpacker/binary-font-unpacker.md create mode 100644 docs/media/fonts/font-decompress/src/utils/decode-string.md create mode 100644 docs/media/fonts/font-subset/README.md create mode 100644 docs/media/fonts/font-subset/src/adapters/null/null.md create mode 100644 docs/media/fonts/font-subset/src/core/font-compressor/font-compressor.md create mode 100644 docs/media/fonts/font-subset/src/types/common.md create mode 100644 docs/media/fonts/font-subset/src/utils/format-detect.md create mode 100644 docs/media/fonts/font-subset/src/utils/unicode-ranges.md create mode 100644 docs/media/image/README.md create mode 100644 docs/media/image/_intro.md create mode 100644 docs/media/image/caddy-imgproxy/README.md create mode 100644 docs/media/image/caddy-imgproxy/src/config/config.md create mode 100644 docs/media/image/caddy-imgproxy/src/dimensions/calculate-dimensions.md create mode 100644 docs/media/image/caddy-imgproxy/src/domain/extract-domain.md create mode 100644 docs/media/image/caddy-imgproxy/src/error-codes/error-codes.md create mode 100644 docs/media/image/caddy-imgproxy/src/gravity/gravity.md create mode 100644 docs/media/image/caddy-imgproxy/src/handler/handler.md create mode 100644 docs/media/image/caddy-imgproxy/src/operation/operation.md create mode 100644 docs/media/image/caddy-imgproxy/src/parse/parse-url.md create mode 100644 docs/media/image/caddy-imgproxy/src/signing/sign-path.md create mode 100644 docs/media/image/caddy-imgproxy/src/telemetry/telemetry.md create mode 100644 docs/media/image/caddy-imgproxy/src/types/types.md create mode 100644 docs/media/image/caddy-imgproxy/src/url-builder/url-builder.md create mode 100644 docs/media/image/colour-convert-adapt/README.md create mode 100644 docs/media/image/colour-convert-adapt/src/adapt/adapt.md create mode 100644 docs/media/image/colour-convert-cieluv/README.md create mode 100644 docs/media/image/colour-convert-cieluv/src/colour-convert-cieluv/colour-convert-cieluv.md create mode 100644 docs/media/image/colour-convert-cmyk/README.md create mode 100644 docs/media/image/colour-convert-cmyk/src/cmyk/cmyk.md create mode 100644 docs/media/image/colour-convert-hsluv/README.md create mode 100644 docs/media/image/colour-convert-hsluv/src/colour-convert-hsluv/colour-convert-hsluv.md create mode 100644 docs/media/image/colour-filter-cct/README.md create mode 100644 docs/media/image/colour-filter-cct/src/colour-filter-cct/colour-filter-cct.md create mode 100644 docs/media/image/colour-filter-cmc/README.md create mode 100644 docs/media/image/colour-filter-cmc/src/colour-filter-cmc/colour-filter-cmc.md create mode 100644 docs/media/image/colour-filter-greyscale/README.md create mode 100644 docs/media/image/colour-filter-greyscale/src/greyscale/greyscale.md create mode 100644 docs/media/image/colour-filter-sepia/README.md create mode 100644 docs/media/image/colour-filter-sepia/src/sepia/sepia.md create mode 100644 docs/media/image/colours/README.md create mode 100644 docs/media/image/colours/src/colour-factories/colour-factories.md create mode 100644 docs/media/image/colours/src/colour/colour-formatters.md create mode 100644 docs/media/image/colours/src/colour/colour.md create mode 100644 docs/media/image/colours/src/conversions/conversions.md create mode 100644 docs/media/image/colours/src/error-codes/error-codes.md create mode 100644 docs/media/image/colours/src/errors/errors.md create mode 100644 docs/media/image/colours/src/parser/parser.md create mode 100644 docs/media/image/colours/src/types/colour-types/colour-types.md create mode 100644 docs/media/image/colours/src/utils/utils.md create mode 100644 docs/media/image/compress-image/README.md create mode 100644 docs/media/image/compress-image/src/adapters/memory/memory.md create mode 100644 docs/media/image/compress-image/src/adapters/sharp/sharp.md create mode 100644 docs/media/image/compress-image/src/core/compressor/compressor.md create mode 100644 docs/media/image/compress-image/src/errors/compress-image-error.md create mode 100644 docs/media/image/compress-image/src/schemas/compress-options.schema.md create mode 100644 docs/media/image/compress-image/src/types/compress-image.types.md create mode 100644 docs/media/image/compress-image/src/utils/image-utils.md create mode 100644 docs/media/image/emblem-solver/README.md create mode 100644 docs/media/image/emblem-solver/src/converter/converter.md create mode 100644 docs/media/image/emblem-solver/src/errors/errors.md create mode 100644 docs/media/image/emblem-solver/src/fixtures/fixtures.md create mode 100644 docs/media/image/emblem-solver/src/grid/analyse/analyse.md create mode 100644 docs/media/image/emblem-solver/src/helpers/helpers.md create mode 100644 docs/media/image/emblem-solver/src/io/parse/parse.md create mode 100644 docs/media/image/emblem-solver/src/optimizer/merge/merge.md create mode 100644 docs/media/image/emblem-solver/src/optimizer/overlap/overlap.md create mode 100644 docs/media/image/emblem-solver/src/optimizer/redundancy/redundancy.md create mode 100644 docs/media/image/emblem-solver/src/schemas/schemas.md create mode 100644 docs/media/image/emblem-solver/src/solver/greedy/greedy.md create mode 100644 docs/media/image/emblem-solver/src/solver/histogram/histogram.md create mode 100644 docs/media/image/emblem-solver/src/solver/layer/layer.md create mode 100644 docs/media/image/emblem-solver/src/solver/ordering/ordering.md create mode 100644 docs/media/image/emblem-solver/src/solver/strip/strip.md create mode 100644 docs/media/image/emblem-solver/src/svg/build/build.md create mode 100644 docs/media/image/emblem-solver/src/telemetry/telemetry.md create mode 100644 docs/media/image/emblem-solver/src/types/types.md create mode 100644 docs/media/image/exif/README.md create mode 100644 docs/media/image/exif/src/binary/crc32/crc32.md create mode 100644 docs/media/image/exif/src/binary/rational/rational.md create mode 100644 docs/media/image/exif/src/binary/reader/byte-reader.md create mode 100644 docs/media/image/exif/src/binary/writer/byte-writer.md create mode 100644 docs/media/image/exif/src/core/read-metadata.md create mode 100644 docs/media/image/exif/src/core/strip-metadata.md create mode 100644 docs/media/image/exif/src/core/write-metadata.md create mode 100644 docs/media/image/exif/src/errors/exif-error.md create mode 100644 docs/media/image/exif/src/exif/read-exif.md create mode 100644 docs/media/image/exif/src/format/detect.md create mode 100644 docs/media/image/exif/src/ifd/parse.md create mode 100644 docs/media/image/exif/src/iptc/read-iptc.md create mode 100644 docs/media/image/exif/src/jpeg/segments.md create mode 100644 docs/media/image/exif/src/xmp/read-xmp.md create mode 100644 docs/media/image/image-quantisation/README.md create mode 100644 docs/media/image/image-quantisation/src/analysis/classify/classify.md create mode 100644 docs/media/image/image-quantisation/src/analysis/colour/colour.md create mode 100644 docs/media/image/image-quantisation/src/analysis/edges/edges.md create mode 100644 docs/media/image/image-quantisation/src/analysis/pools/pools.md create mode 100644 docs/media/image/image-quantisation/src/errors/image-quantisation-error.md create mode 100644 docs/media/image/image-quantisation/src/pipeline/pipeline.md create mode 100644 docs/media/image/image-quantisation/src/quantise/quantise.md create mode 100644 docs/media/image/image-quantisation/src/schemas/options.schema.md create mode 100644 docs/media/image/image-quantisation/src/spatial/cleanup/cleanup.md create mode 100644 docs/media/image/image-quantisation/src/types/common.md create mode 100644 docs/media/image/image/README.md create mode 100644 docs/media/image/image/src/error-codes/error-codes.md create mode 100644 docs/media/image/image/src/errors/errors.md create mode 100644 docs/media/image/image/src/processor/dimensions/dimensions.md create mode 100644 docs/media/image/image/src/processor/instruments/instruments.md create mode 100644 docs/media/image/image/src/processor/pipeline-builder/pipeline-builder.md create mode 100644 docs/media/image/image/src/processor/processor/processor.md create mode 100644 docs/media/image/image/src/types/image-detect/image-detect.md create mode 100644 docs/media/image/image/src/types/image-types/image-types.md create mode 100644 docs/media/video/README.md create mode 100644 docs/media/video/_intro.md create mode 100644 docs/media/video/video-thumbnails/README.md create mode 100644 docs/media/video/video-thumbnails/src/error-codes/error-codes.md create mode 100644 docs/media/video/video-thumbnails/src/errors/video-thumbnails-error.md create mode 100644 docs/media/video/video-thumbnails/src/runner/fluent-ffmpeg-runner.md create mode 100644 docs/media/video/video-thumbnails/src/runner/runner.md create mode 100644 docs/media/video/video-thumbnails/src/schemas/schemas.md create mode 100644 docs/media/video/video-thumbnails/src/sprite-sheet/sprite-sheet.md create mode 100644 docs/media/video/video-thumbnails/src/telemetry/telemetry.md create mode 100644 docs/media/video/video-thumbnails/src/thumbnail-generator/thumbnail-generator.md create mode 100644 docs/media/video/video/README.md create mode 100644 docs/media/video/video/src/detection/detection.md create mode 100644 docs/media/video/video/src/duration/duration.md create mode 100644 docs/media/video/video/src/error-codes/error-codes.md create mode 100644 docs/media/video/video/src/errors/errors.md create mode 100644 docs/media/video/video/src/format/format.md create mode 100644 docs/media/video/video/src/instruments/instruments.md create mode 100644 docs/media/video/video/src/pipeline-builder/pipeline-builder.md create mode 100644 docs/media/video/video/src/processor/processor.md create mode 100644 docs/media/video/video/src/resize/resize.md create mode 100644 docs/media/video/video/src/trim/trim.md create mode 100644 docs/media/video/video/src/types/video-types/video-types.md create mode 100644 docs/money/README.md create mode 100644 docs/money/_intro.md create mode 100644 docs/money/finance/README.md create mode 100644 docs/money/finance/_intro.md create mode 100644 docs/money/finance/cryptocurrency/README.md create mode 100644 docs/money/finance/cryptocurrency/src/address/validator.md create mode 100644 docs/money/finance/cryptocurrency/src/chains/chain-data.md create mode 100644 docs/money/finance/cryptocurrency/src/chains/chain-registry.md create mode 100644 docs/money/finance/cryptocurrency/src/chains/registry.md create mode 100644 docs/money/finance/cryptocurrency/src/error-codes/error-codes.md create mode 100644 docs/money/finance/cryptocurrency/src/gas/gas-estimator.md create mode 100644 docs/money/finance/cryptocurrency/src/tokens/token-data.md create mode 100644 docs/money/finance/cryptocurrency/src/tokens/token-registry.md create mode 100644 docs/money/finance/cryptocurrency/src/transaction/tx-decoder.md create mode 100644 docs/money/finance/cryptocurrency/src/types/crypto.types.md create mode 100644 docs/money/finance/cryptocurrency/src/units/converter.md create mode 100644 docs/money/finance/currency-provider-binance/README.md create mode 100644 docs/money/finance/currency-provider-binance/src/binance/binance.md create mode 100644 docs/money/finance/currency-provider-coingecko/README.md create mode 100644 docs/money/finance/currency-provider-coingecko/src/coin-ids/coin-ids.md create mode 100644 docs/money/finance/currency-provider-coingecko/src/coingecko/coingecko.md create mode 100644 docs/money/finance/currency-provider-coinmarketcap/README.md create mode 100644 docs/money/finance/currency-provider-coinmarketcap/src/coinmarketcap/coinmarketcap.md create mode 100644 docs/money/finance/currency-provider-cryptocompare/README.md create mode 100644 docs/money/finance/currency-provider-cryptocompare/src/cryptocompare/cryptocompare.md create mode 100644 docs/money/finance/currency-provider-ecb/README.md create mode 100644 docs/money/finance/currency-provider-ecb/src/ecb/ecb.md create mode 100644 docs/money/finance/currency-provider-fixer/README.md create mode 100644 docs/money/finance/currency-provider-fixer/src/fixer/fixer.md create mode 100644 docs/money/finance/currency-provider-kraken/README.md create mode 100644 docs/money/finance/currency-provider-kraken/src/provider/provider.md create mode 100644 docs/money/finance/currency-provider-kraken/src/symbols/symbols.md create mode 100644 docs/money/finance/currency-provider-open-exchange-rates/README.md create mode 100644 docs/money/finance/currency-provider-open-exchange-rates/src/provider/provider.md create mode 100644 docs/money/finance/currency-provider-virtual/README.md create mode 100644 docs/money/finance/currency-provider-virtual/src/error-codes/error-codes.md create mode 100644 docs/money/finance/currency-provider-virtual/src/provider/provider.md create mode 100644 docs/money/finance/currency-providers/README.md create mode 100644 docs/money/finance/currency-providers/src/error-codes/error-codes.md create mode 100644 docs/money/finance/currency-providers/src/factory/factory.md create mode 100644 docs/money/finance/currency-providers/src/http/http.md create mode 100644 docs/money/finance/currency-providers/src/registry/registry.md create mode 100644 docs/money/finance/currency-providers/src/types/configs.md create mode 100644 docs/money/finance/currency/README.md create mode 100644 docs/money/finance/currency/src/converter/converter.md create mode 100644 docs/money/finance/currency/src/error-codes/error-codes.md create mode 100644 docs/money/finance/currency/src/provider/provider.md create mode 100644 docs/money/finance/currency/src/rate-cache/rate-cache.md create mode 100644 docs/money/finance/currency/src/schemas/schemas.md create mode 100644 docs/money/finance/currency/src/types/common.md create mode 100644 docs/money/finance/money/README.md create mode 100644 docs/money/finance/money/src/allocator/allocator.md create mode 100644 docs/money/finance/money/src/currencies/currencies.md create mode 100644 docs/money/finance/money/src/error-codes/error-codes.md create mode 100644 docs/money/finance/money/src/formatter/formatter.md create mode 100644 docs/money/finance/money/src/money/money.md create mode 100644 docs/money/finance/money/src/types/common.md create mode 100644 docs/money/payment/README.md create mode 100644 docs/money/payment/_intro.md create mode 100644 docs/money/payment/payment-provider-adyen/README.md create mode 100644 docs/money/payment/payment-provider-adyen/src/adyen/adyen.md create mode 100644 docs/money/payment/payment-provider-adyen/src/adyen/mapping.md create mode 100644 docs/money/payment/payment-provider-adyen/src/types/adyen.md create mode 100644 docs/money/payment/payment-provider-mollie/README.md create mode 100644 docs/money/payment/payment-provider-mollie/src/mollie/mollie.md create mode 100644 docs/money/payment/payment-provider-paypal/README.md create mode 100644 docs/money/payment/payment-provider-paypal/src/paypal/mapping.md create mode 100644 docs/money/payment/payment-provider-paypal/src/paypal/paypal.md create mode 100644 docs/money/payment/payment-provider-square/README.md create mode 100644 docs/money/payment/payment-provider-square/src/mapping/payment.md create mode 100644 docs/money/payment/payment-provider-square/src/mapping/refund.md create mode 100644 docs/money/payment/payment-provider-square/src/square/square.md create mode 100644 docs/money/payment/payment-provider-square/src/types/config.md create mode 100644 docs/money/payment/payment-provider-stripe/README.md create mode 100644 docs/money/payment/payment-provider-stripe/src/stripe/stripe.md create mode 100644 docs/money/payment/payment-providers/README.md create mode 100644 docs/money/payment/payment-providers/src/error-codes/error-codes.md create mode 100644 docs/money/payment/payment-providers/src/http/http.md create mode 100644 docs/money/payment/payment-providers/src/registry/define.md create mode 100644 docs/money/payment/payment-providers/src/registry/registry.md create mode 100644 docs/money/payment/payment-providers/src/types/provider.md create mode 100644 docs/money/payment/payment/README.md create mode 100644 docs/money/payment/payment/src/engine/engine.md create mode 100644 docs/money/payment/payment/src/error-codes/error-codes.md create mode 100644 docs/money/payment/payment/src/fraud/fraud.md create mode 100644 docs/money/payment/payment/src/gateway/paypal.md create mode 100644 docs/money/payment/payment/src/gateway/stripe.md create mode 100644 docs/money/payment/payment/src/gateway/test.md create mode 100644 docs/money/payment/payment/src/gateway/types.md create mode 100644 docs/money/payment/payment/src/hooks/hooks.md create mode 100644 docs/money/payment/payment/src/receipt/receipt.md create mode 100644 docs/money/payment/payment/src/reconciliation/reconciliation.md create mode 100644 docs/money/payment/payment/src/refund/refund.md create mode 100644 docs/money/payment/payment/src/retry/retry.md create mode 100644 docs/money/payment/payment/src/tax/tax.md create mode 100644 docs/money/payment/payment/src/tokenization/tokenization.md create mode 100644 docs/money/payment/payment/src/types/payment.md create mode 100644 docs/money/payment/payment/src/webhook/webhook.md create mode 100644 docs/networking/README.md create mode 100644 docs/networking/_intro.md create mode 100644 docs/networking/drive/README.md create mode 100644 docs/networking/drive/_intro.md create mode 100644 docs/networking/drive/drive-mesh-protocol/README.md create mode 100644 docs/networking/drive/drive-mesh-protocol/src/codec/advertise.md create mode 100644 docs/networking/drive/drive-mesh-protocol/src/codec/bitset.md create mode 100644 docs/networking/drive/drive-mesh-protocol/src/codec/common.md create mode 100644 docs/networking/drive/drive-mesh-protocol/src/codec/error.md create mode 100644 docs/networking/drive/drive-mesh-protocol/src/codec/request.md create mode 100644 docs/networking/drive/drive-mesh-protocol/src/codec/response.md create mode 100644 docs/networking/drive/drive-mesh-protocol/src/error-codes.md create mode 100644 docs/networking/drive/drive-mesh-protocol/src/generation/monotonic.md create mode 100644 docs/networking/drive/drive-mesh-protocol/src/generation/throttle.md create mode 100644 docs/networking/drive/drive-mesh-protocol/src/schemas/envelope.schema.md create mode 100644 docs/networking/drive/drive-mesh-protocol/src/select/form.md create mode 100644 docs/networking/drive/drive-mesh-protocol/src/trust/decay.md create mode 100644 docs/networking/drive/drive-mesh-protocol/src/trust/sample.md create mode 100644 docs/networking/drive/drive-mesh-protocol/src/trust/score.md create mode 100644 docs/networking/drive/drive-mesh-protocol/src/types/protocol.types.md create mode 100644 docs/networking/drive/drive-mesh/README.md create mode 100644 docs/networking/drive/drive-mesh/src/error-codes/error-codes.md create mode 100644 docs/networking/drive/drive-mesh/src/gossip/gossip-engine/gossip-engine.md create mode 100644 docs/networking/drive/drive-mesh/src/internal/typed-event-emitter/typed-event-emitter.md create mode 100644 docs/networking/drive/drive-mesh/src/mesh/drive-mesh/drive-mesh.md create mode 100644 docs/networking/drive/drive-mesh/src/peer-registry/peer-registry/peer-registry.md create mode 100644 docs/networking/drive/drive-mesh/src/scheduler/parallel-puller/parallel-puller.md create mode 100644 docs/networking/drive/drive-mesh/src/server-fallback/server-fallback/server-fallback.md create mode 100644 docs/networking/drive/drive-mesh/src/types/config.types.md create mode 100644 docs/networking/drive/drive-mesh/src/types/drive-transport.types.md create mode 100644 docs/networking/drive/drive-mesh/src/types/events.types.md create mode 100644 docs/networking/drive/drive-mesh/src/types/peer.types.md create mode 100644 docs/networking/drive/drive-plugin-cache/README.md create mode 100644 docs/networking/drive/drive-plugin-cache/src/error-codes/error-codes.md create mode 100644 docs/networking/drive/drive-plugin-cache/src/handle/handle.md create mode 100644 docs/networking/drive/drive-plugin-cache/src/middleware/middleware.invalidation.md create mode 100644 docs/networking/drive/drive-plugin-cache/src/middleware/middleware.md create mode 100644 docs/networking/drive/drive-plugin-cache/src/middleware/middleware.signal.md create mode 100644 docs/networking/drive/drive-plugin-cache/src/otel/otel.md create mode 100644 docs/networking/drive/drive-plugin-cache/src/plugin/plugin.md create mode 100644 docs/networking/drive/drive-plugin-cache/src/types/options.types.md create mode 100644 docs/networking/drive/drive-plugin-chunks/README.md create mode 100644 docs/networking/drive/drive-plugin-chunks/src/codec/chunk.md create mode 100644 docs/networking/drive/drive-plugin-chunks/src/codec/header.md create mode 100644 docs/networking/drive/drive-plugin-chunks/src/error-codes.md create mode 100644 docs/networking/drive/drive-plugin-chunks/src/inline/inline-hint.md create mode 100644 docs/networking/drive/drive-plugin-chunks/src/layout/auto.md create mode 100644 docs/networking/drive/drive-plugin-chunks/src/layout/chunk-keys.md create mode 100644 docs/networking/drive/drive-plugin-chunks/src/layout/sparse-file.md create mode 100644 docs/networking/drive/drive-plugin-chunks/src/manifest/build.md create mode 100644 docs/networking/drive/drive-plugin-chunks/src/manifest/load.md create mode 100644 docs/networking/drive/drive-plugin-chunks/src/manifest/source.md create mode 100644 docs/networking/drive/drive-plugin-chunks/src/pipeline/decrypt-chunk.md create mode 100644 docs/networking/drive/drive-plugin-chunks/src/pipeline/encrypt-stream.md create mode 100644 docs/networking/drive/drive-plugin-chunks/src/pipeline/sign-chunk.md create mode 100644 docs/networking/drive/drive-plugin-chunks/src/pipeline/verify-chunk.md create mode 100644 docs/networking/drive/drive-plugin-chunks/src/plugin.md create mode 100644 docs/networking/drive/drive-plugin-chunks/src/schemas/manifest.schema.md create mode 100644 docs/networking/drive/drive-plugin-chunks/src/types/chunks.types.md create mode 100644 docs/networking/drive/drive-react-sharing/README.md create mode 100644 docs/networking/drive/drive-react-sharing/src/components/file-access-list/file-access-list.md create mode 100644 docs/networking/drive/drive-react-sharing/src/components/partition-badge/partition-badge.md create mode 100644 docs/networking/drive/drive-react-sharing/src/components/share-dialog/share-dialog.md create mode 100644 docs/networking/drive/drive-react-sharing/src/error-codes.md create mode 100644 docs/networking/drive/drive-react-sharing/src/hooks/use-sharing/use-sharing.md create mode 100644 docs/networking/drive/drive-react-sharing/src/otel/instruments.md create mode 100644 docs/networking/drive/drive-react-sharing/src/types/sharing.types.md create mode 100644 docs/networking/drive/drive-sharing/README.md create mode 100644 docs/networking/drive/drive-sharing/src/encryption/envelope/envelope.md create mode 100644 docs/networking/drive/drive-sharing/src/encryption/key-ring/key-ring.md create mode 100644 docs/networking/drive/drive-sharing/src/error-codes/error-codes.md create mode 100644 docs/networking/drive/drive-sharing/src/otel/instruments.md create mode 100644 docs/networking/drive/drive-sharing/src/partitions/partition-manager/partition-manager.md create mode 100644 docs/networking/drive/drive-sharing/src/partitions/partition-policy/partition-policy.md create mode 100644 docs/networking/drive/drive-sharing/src/partitions/partition-store/partition-store.md create mode 100644 docs/networking/drive/drive-sharing/src/sharing/grants/grants.md create mode 100644 docs/networking/drive/drive-sharing/src/sharing/tokens/tokens.md create mode 100644 docs/networking/drive/drive-sharing/src/transfer/transfer/transfer.md create mode 100644 docs/networking/drive/drive-sharing/src/types/common.md create mode 100644 docs/networking/drive/drive-sharing/src/types/schemas.md create mode 100644 docs/networking/drive/drive-storage-archive-core/README.md create mode 100644 docs/networking/drive/drive-storage-archive-core/src/errors/error-codes.md create mode 100644 docs/networking/drive/drive-storage-archive-core/src/factory/open-archive-storage.md create mode 100644 docs/networking/drive/drive-storage-archive-core/src/modes/pending-mutations.md create mode 100644 docs/networking/drive/drive-storage-archive-core/src/modes/validate-mode.md create mode 100644 docs/networking/drive/drive-storage-archive-core/src/password/password-hook.md create mode 100644 docs/networking/drive/drive-storage-archive-core/src/resolvers/rar-sibling-resolver.md create mode 100644 docs/networking/drive/drive-storage-archive-core/src/resolvers/seven-zip-sibling-resolver.md create mode 100644 docs/networking/drive/drive-storage-archive-core/src/resolvers/sibling-host.md create mode 100644 docs/networking/drive/drive-storage-archive-core/src/resolvers/zip-sibling-resolver.md create mode 100644 docs/networking/drive/drive-storage-archive-core/src/sniff/sniff-format.md create mode 100644 docs/networking/drive/drive-storage-archive-core/src/testing/run-archive-conformance.md create mode 100644 docs/networking/drive/drive-storage-archive-core/src/types/archive-capabilities.md create mode 100644 docs/networking/drive/drive-storage-archive-core/src/types/archive-codec.md create mode 100644 docs/networking/drive/drive-storage-archive-core/src/types/archive-format.md create mode 100644 docs/networking/drive/drive-storage-archive-core/src/types/archive-mode.md create mode 100644 docs/networking/drive/drive-storage-archive-core/src/types/entry-reader.md create mode 100644 docs/networking/drive/drive-storage-archive-core/src/types/open-archive-storage-options.md create mode 100644 docs/networking/drive/drive-storage-archive-core/src/types/password-hook.md create mode 100644 docs/networking/drive/drive-storage-archive-core/src/types/resolve-sibling.md create mode 100644 docs/networking/drive/drive-storage-zip/README.md create mode 100644 docs/networking/drive/drive-storage-zip/src/errors/error-codes.md create mode 100644 docs/networking/drive/drive-storage-zip/src/parser/central-directory/parse-cdr-entry.md create mode 100644 docs/networking/drive/drive-storage-zip/src/parser/central-directory/walk-cdr.md create mode 100644 docs/networking/drive/drive-storage-zip/src/parser/compression/compress.md create mode 100644 docs/networking/drive/drive-storage-zip/src/parser/compression/decompress.md create mode 100644 docs/networking/drive/drive-storage-zip/src/parser/crc32.md create mode 100644 docs/networking/drive/drive-storage-zip/src/parser/crypto/aes/aes-decrypt.md create mode 100644 docs/networking/drive/drive-storage-zip/src/parser/crypto/aes/aes-write-block.md create mode 100644 docs/networking/drive/drive-storage-zip/src/parser/eocd/find-eocd.md create mode 100644 docs/networking/drive/drive-storage-zip/src/parser/eocd/parse-eocd.md create mode 100644 docs/networking/drive/drive-storage-zip/src/parser/eocd/parse-eocd64.md create mode 100644 docs/networking/drive/drive-storage-zip/src/parser/local-header/parse-local-header.md create mode 100644 docs/networking/drive/drive-storage-zip/src/parser/local-header/read-entry-bytes.md create mode 100644 docs/networking/drive/drive-storage-zip/src/parser/signatures.md create mode 100644 docs/networking/drive/drive-storage-zip/src/storage/encode-zip.md create mode 100644 docs/networking/drive/drive-storage-zip/src/storage/normalize-path.md create mode 100644 docs/networking/drive/drive-storage-zip/src/storage/zip-archive-storage.md create mode 100644 docs/networking/drive/drive-storage-zip/src/types/parser.types.md create mode 100644 docs/networking/drive/drive-storage-zip/src/types/storage.types.md create mode 100644 docs/networking/drive/drive-template/README.md create mode 100644 docs/networking/drive/drive-template/src/cdn/upload-token.md create mode 100644 docs/networking/drive/drive-template/src/cdn/url-builder.md create mode 100644 docs/networking/drive/drive-template/src/codec/canonical.md create mode 100644 docs/networking/drive/drive-template/src/codec/sign.md create mode 100644 docs/networking/drive/drive-template/src/codec/verify.md create mode 100644 docs/networking/drive/drive-template/src/error-codes.md create mode 100644 docs/networking/drive/drive-template/src/key/grant-validator.md create mode 100644 docs/networking/drive/drive-template/src/schemas/template.schema.md create mode 100644 docs/networking/drive/drive-template/src/types/template.types.md create mode 100644 docs/networking/drive/drive-template/src/validate/depth.md create mode 100644 docs/networking/drive/drive-template/src/validate/file.md create mode 100644 docs/networking/drive/drive-template/src/validate/order.md create mode 100644 docs/networking/drive/drive-template/src/validate/replay.md create mode 100644 docs/networking/drive/drive-transport-https/README.md create mode 100644 docs/networking/drive/drive-transport-https/src/error-codes.md create mode 100644 docs/networking/drive/drive-transport-https/src/schemas/transport.schema.md create mode 100644 docs/networking/drive/drive-transport-https/src/transport/defaults.md create mode 100644 docs/networking/drive/drive-transport-https/src/transport/https-transport.md create mode 100644 docs/networking/drive/drive-transport-https/src/types/transport.types.md create mode 100644 docs/networking/drive/drive-transport-webrtc/README.md create mode 100644 docs/networking/drive/drive-transport-webrtc/src/error-codes/error-codes.md create mode 100644 docs/networking/drive/drive-transport-webrtc/src/framing/frame/frame.md create mode 100644 docs/networking/drive/drive-transport-webrtc/src/schemas/frame.schemas.md create mode 100644 docs/networking/drive/drive-transport-webrtc/src/transport/webrtc-transport/bitset-codec.md create mode 100644 docs/networking/drive/drive-transport-webrtc/src/transport/webrtc-transport/hex.md create mode 100644 docs/networking/drive/drive-transport-webrtc/src/transport/webrtc-transport/payload-codec.md create mode 100644 docs/networking/drive/drive-transport-webrtc/src/transport/webrtc-transport/webrtc-transport.md create mode 100644 docs/networking/drive/drive-uri/README.md create mode 100644 docs/networking/drive/drive-uri/src/adapter/drive-storage-like.md create mode 100644 docs/networking/drive/drive-uri/src/conformance/conformance.md create mode 100644 docs/networking/drive/drive-uri/src/error-codes/error-codes.md create mode 100644 docs/networking/drive/drive-uri/src/otel/otel.md create mode 100644 docs/networking/drive/drive-uri/src/plugins/drive-mesh/drive-mesh.md create mode 100644 docs/networking/drive/drive-uri/src/plugins/drive-template/drive-template.md create mode 100644 docs/networking/drive/drive-uri/src/plugins/drive/drive.md create mode 100644 docs/networking/drive/drive-uri/src/plugins/drive/drive.streams.md create mode 100644 docs/networking/drive/drive-uri/src/types/plugin-options.types.md create mode 100644 docs/networking/drive/drive-webrtc/README.md create mode 100644 docs/networking/drive/drive-webrtc/src/chunk-source/chunk-source/chunk-source.md create mode 100644 docs/networking/drive/drive-webrtc/src/client/client/client.md create mode 100644 docs/networking/drive/drive-webrtc/src/client/ice/ice.md create mode 100644 docs/networking/drive/drive-webrtc/src/client/offer-answer/offer-answer.md create mode 100644 docs/networking/drive/drive-webrtc/src/client/reconnect/reconnect.md create mode 100644 docs/networking/drive/drive-webrtc/src/data-channel/data-channel-manager/data-channel-manager.md create mode 100644 docs/networking/drive/drive-webrtc/src/discovery/chunk-discovery-manager/chunk-discovery-manager.md create mode 100644 docs/networking/drive/drive-webrtc/src/error-codes/error-codes.md create mode 100644 docs/networking/drive/drive-webrtc/src/events/typed-event-emitter/typed-event-emitter.md create mode 100644 docs/networking/drive/drive-webrtc/src/integrity/chunk-integrity/chunk-integrity.md create mode 100644 docs/networking/drive/drive-webrtc/src/integrity/chunk-integrity/chunk-integrity.types.md create mode 100644 docs/networking/drive/drive-webrtc/src/lru-cache/lru-cache/lru-cache.md create mode 100644 docs/networking/drive/drive-webrtc/src/lru-cache/lru-cache/lru-cache.types.md create mode 100644 docs/networking/drive/drive-webrtc/src/peer-manager/peer-bandwidth-tracker/peer-bandwidth-tracker.md create mode 100644 docs/networking/drive/drive-webrtc/src/peer-manager/peer-bandwidth-tracker/peer-bandwidth-tracker.types.md create mode 100644 docs/networking/drive/drive-webrtc/src/peer-manager/peer-manager/peer-manager.md create mode 100644 docs/networking/drive/drive-webrtc/src/peer-manager/topology/full-mesh.md create mode 100644 docs/networking/drive/drive-webrtc/src/peer-manager/topology/hub-and-spoke.md create mode 100644 docs/networking/drive/drive-webrtc/src/peer-manager/topology/super-peer.md create mode 100644 docs/networking/drive/drive-webrtc/src/peer-manager/topology/topology-strategy.md create mode 100644 docs/networking/drive/drive-webrtc/src/plugin/webrtc-plugin/webrtc-plugin.md create mode 100644 docs/networking/drive/drive-webrtc/src/rate-limiter/rate-limiter/rate-limiter.md create mode 100644 docs/networking/drive/drive-webrtc/src/rate-limiter/rate-limiter/rate-limiter.types.md create mode 100644 docs/networking/drive/drive-webrtc/src/schemas/config.schemas.md create mode 100644 docs/networking/drive/drive-webrtc/src/schemas/signaling.schemas.md create mode 100644 docs/networking/drive/drive-webrtc/src/security/security-validator/security-validator.md create mode 100644 docs/networking/drive/drive-webrtc/src/signaling/signaling-client/signaling-client.md create mode 100644 docs/networking/drive/drive-webrtc/src/sub-chunk/sub-chunk/sub-chunk.md create mode 100644 docs/networking/drive/drive-webrtc/src/sub-chunk/sub-chunk/sub-chunk.types.md create mode 100644 docs/networking/drive/drive-webrtc/src/types/config.types.md create mode 100644 docs/networking/drive/drive-webrtc/src/types/drive.types.md create mode 100644 docs/networking/drive/drive-webrtc/src/types/events.types.md create mode 100644 docs/networking/drive/drive-webrtc/src/types/messages.types.md create mode 100644 docs/networking/drive/drive-webrtc/src/types/peer.types.md create mode 100644 docs/networking/drive/drive-webrtc/src/types/stats.types.md create mode 100644 docs/networking/drive/drive/README.md create mode 100644 docs/networking/drive/drive/src/drive/drive.md create mode 100644 docs/networking/drive/drive/src/drive/file-location-index.md create mode 100644 docs/networking/drive/drive/src/drive/get-key-status.md create mode 100644 docs/networking/drive/drive/src/drive/get-presence.md create mode 100644 docs/networking/drive/drive/src/drive/hydrate-from.md create mode 100644 docs/networking/drive/drive/src/error-codes/error-codes.md create mode 100644 docs/networking/drive/drive/src/file-operations/delete.md create mode 100644 docs/networking/drive/drive/src/file-operations/list.md create mode 100644 docs/networking/drive/drive/src/file-operations/read.md create mode 100644 docs/networking/drive/drive/src/file-operations/stat.md create mode 100644 docs/networking/drive/drive/src/file-operations/streams.md create mode 100644 docs/networking/drive/drive/src/file-operations/write.md create mode 100644 docs/networking/drive/drive/src/plugins/registry.md create mode 100644 docs/networking/drive/drive/src/schemas/drive-options.schema.md create mode 100644 docs/networking/drive/drive/src/types/drive.types.md create mode 100644 docs/networking/events/README.md create mode 100644 docs/networking/events/_intro.md create mode 100644 docs/networking/events/broadcast-channel/README.md create mode 100644 docs/networking/events/broadcast-channel/src/ask/ask.md create mode 100644 docs/networking/events/broadcast-channel/src/ask/responder.md create mode 100644 docs/networking/events/broadcast-channel/src/channel/channel.md create mode 100644 docs/networking/events/broadcast-channel/src/channel/heartbeat.md create mode 100644 docs/networking/events/broadcast-channel/src/errors/codes.md create mode 100644 docs/networking/events/broadcast-channel/src/id/id.md create mode 100644 docs/networking/events/broadcast-channel/src/logger/noop.md create mode 100644 docs/networking/events/broadcast-channel/src/otel/metrics.md create mode 100644 docs/networking/events/broadcast-channel/src/schemas/messages.md create mode 100644 docs/networking/events/broadcast-channel/src/transport/local-storage.md create mode 100644 docs/networking/events/broadcast-channel/src/transport/native.md create mode 100644 docs/networking/events/event-sourcing/README.md create mode 100644 docs/networking/events/event-sourcing/src/core/aggregate-repository/aggregate-repository.md create mode 100644 docs/networking/events/event-sourcing/src/core/aggregate/aggregate.md create mode 100644 docs/networking/events/event-sourcing/src/core/event-store/memory-event-store.md create mode 100644 docs/networking/events/event-sourcing/src/errors/event-sourcing-error.md create mode 100644 docs/networking/events/event-sourcing/src/projection/builder/builder.md create mode 100644 docs/networking/events/event-sourcing/src/schemas/event-sourcing.schemas.md create mode 100644 docs/networking/events/event-sourcing/src/types/event-sourcing.types.md create mode 100644 docs/networking/events/event-sourcing/src/upcasting/upcaster/upcaster.md create mode 100644 docs/networking/events/events-metrics/README.md create mode 100644 docs/networking/events/events-metrics/src/core/attach-event-metrics/attach-event-metrics.md create mode 100644 docs/networking/events/events-metrics/src/metrics/metric-names/metric-names.md create mode 100644 docs/networking/events/events-otel/README.md create mode 100644 docs/networking/events/events-otel/src/core/attach-event-tracing/attach-event-tracing.md create mode 100644 docs/networking/events/events-otel/src/propagation/trace-context/trace-context.md create mode 100644 docs/networking/events/events-otel/src/sampling/sampling-rule/sampling-rule.md create mode 100644 docs/networking/events/events-schema/README.md create mode 100644 docs/networking/events/events-schema/src/core/attach-event-schemas/attach-event-schemas.md create mode 100644 docs/networking/events/events-transport/README.md create mode 100644 docs/networking/events/events-transport/src/core/envelope/envelope.md create mode 100644 docs/networking/events/events-transport/src/core/nonce-window/nonce-window.md create mode 100644 docs/networking/events/events-transport/src/core/transport-interface/transport-interface.md create mode 100644 docs/networking/events/events-transport/src/transports/broadcast-channel/broadcast-channel-transport.md create mode 100644 docs/networking/events/events-transport/src/transports/message-channel/message-channel-transport.md create mode 100644 docs/networking/events/events-transport/src/utils/structured-clone-check.md create mode 100644 docs/networking/events/events/README.md create mode 100644 docs/networking/events/events/src/bus/event-bus.md create mode 100644 docs/networking/events/events/src/clock/default-clock.md create mode 100644 docs/networking/events/events/src/envelope/envelope.md create mode 100644 docs/networking/events/events/src/errors/codes.md create mode 100644 docs/networking/events/events/src/errors/events-error.md create mode 100644 docs/networking/events/events/src/id/id-generator.md create mode 100644 docs/networking/events/events/src/idempotent/idempotent.md create mode 100644 docs/networking/events/events/src/interceptor/compose.md create mode 100644 docs/networking/events/events/src/observability/with-observability.md create mode 100644 docs/networking/events/events/src/queue/bounded-queue.md create mode 100644 docs/networking/network/README.md create mode 100644 docs/networking/network/_intro.md create mode 100644 docs/networking/network/network-bootstrap/README.md create mode 100644 docs/networking/network/network-bootstrap/src/core/discovery-chain/discovery-chain.md create mode 100644 docs/networking/network/network-bootstrap/src/core/peer-cache/peer-cache.md create mode 100644 docs/networking/network/network-bootstrap/src/errors/errors.md create mode 100644 docs/networking/network/network-bootstrap/src/otel/otel.md create mode 100644 docs/networking/network/network-bootstrap/src/plugin/bootstrap-middleware/bootstrap-middleware.md create mode 100644 docs/networking/network/network-bootstrap/src/plugin/bootstrap-plugin/bootstrap-plugin.md create mode 100644 docs/networking/network/network-bootstrap/src/types/types.md create mode 100644 docs/networking/network/network-discovery-crdt/README.md create mode 100644 docs/networking/network/network-discovery-crdt/src/core/automerge-provider/automerge-provider.md create mode 100644 docs/networking/network/network-discovery-crdt/src/core/crdt-discovery/crdt-discovery.md create mode 100644 docs/networking/network/network-discovery-crdt/src/core/crdt-intervals/crdt-intervals.md create mode 100644 docs/networking/network/network-discovery-crdt/src/core/crdt-peer-manager/crdt-peer-manager.md create mode 100644 docs/networking/network/network-discovery-crdt/src/core/yjs-provider/yjs-provider.md create mode 100644 docs/networking/network/network-discovery-crdt/src/errors/errors.md create mode 100644 docs/networking/network/network-discovery-crdt/src/otel/otel.md create mode 100644 docs/networking/network/network-discovery-crdt/src/types/types.md create mode 100644 docs/networking/network/network-discovery-gundb/README.md create mode 100644 docs/networking/network/network-discovery-gundb/src/core/gundb-discovery/gundb-discovery.md create mode 100644 docs/networking/network/network-discovery-gundb/src/errors/errors.md create mode 100644 docs/networking/network/network-discovery-gundb/src/otel/otel.md create mode 100644 docs/networking/network/network-discovery-gundb/src/plugin/plugin.md create mode 100644 docs/networking/network/network-discovery-gundb/src/signing/signing.md create mode 100644 docs/networking/network/network-discovery-gundb/src/transport/envelope-signing.md create mode 100644 docs/networking/network/network-discovery-gundb/src/transport/transport.md create mode 100644 docs/networking/network/network-discovery-gundb/src/types/types.md create mode 100644 docs/networking/network/network-discovery-hybrid/README.md create mode 100644 docs/networking/network/network-discovery-hybrid/src/core/hybrid-discovery-manager/hybrid-discovery-manager.md create mode 100644 docs/networking/network/network-discovery-hybrid/src/core/lifecycle/lifecycle.md create mode 100644 docs/networking/network/network-discovery-hybrid/src/core/peer-tracker/peer-tracker.md create mode 100644 docs/networking/network/network-discovery-hybrid/src/core/strategy-loader/strategy-loader.md create mode 100644 docs/networking/network/network-discovery-hybrid/src/core/strategy-manager/strategy-manager.md create mode 100644 docs/networking/network/network-discovery-hybrid/src/errors/errors.md create mode 100644 docs/networking/network/network-discovery-hybrid/src/otel/otel.md create mode 100644 docs/networking/network/network-discovery-hybrid/src/types/types.md create mode 100644 docs/networking/network/network-discovery-peerjs/README.md create mode 100644 docs/networking/network/network-discovery-peerjs/src/core/peer-connection-manager/peer-connection-manager.md create mode 100644 docs/networking/network/network-discovery-peerjs/src/core/peerjs-connection/peerjs-connection.md create mode 100644 docs/networking/network/network-discovery-peerjs/src/core/peerjs-discovery/peerjs-discovery.md create mode 100644 docs/networking/network/network-discovery-peerjs/src/core/peerjs-intervals/peerjs-intervals.md create mode 100644 docs/networking/network/network-discovery-peerjs/src/core/peerjs-message-handlers/peerjs-message-handlers.md create mode 100644 docs/networking/network/network-discovery-peerjs/src/core/room-manager/room-manager.md create mode 100644 docs/networking/network/network-discovery-peerjs/src/errors/errors.md create mode 100644 docs/networking/network/network-discovery-peerjs/src/otel/otel.md create mode 100644 docs/networking/network/network-discovery-peerjs/src/plugin/plugin.md create mode 100644 docs/networking/network/network-discovery-peerjs/src/transport/transport.md create mode 100644 docs/networking/network/network-discovery-peerjs/src/types/types.md create mode 100644 docs/networking/network/network-discovery-trystero/README.md create mode 100644 docs/networking/network/network-discovery-trystero/src/core/ipfs-transport/ipfs-transport.md create mode 100644 docs/networking/network/network-discovery-trystero/src/core/mqtt-transport/mqtt-transport.md create mode 100644 docs/networking/network/network-discovery-trystero/src/core/nostr-transport/nostr-transport.md create mode 100644 docs/networking/network/network-discovery-trystero/src/core/torrent-transport/torrent-transport.md create mode 100644 docs/networking/network/network-discovery-trystero/src/core/trystero-discovery/trystero-discovery.md create mode 100644 docs/networking/network/network-discovery-trystero/src/core/trystero-fallback/trystero-fallback.md create mode 100644 docs/networking/network/network-discovery-trystero/src/core/trystero-intervals/trystero-intervals.md create mode 100644 docs/networking/network/network-discovery-trystero/src/core/trystero-message-handlers/trystero-message-handlers.md create mode 100644 docs/networking/network/network-discovery-trystero/src/core/trystero-peer-manager/trystero-peer-manager.md create mode 100644 docs/networking/network/network-discovery-trystero/src/errors/errors.md create mode 100644 docs/networking/network/network-discovery-trystero/src/otel/otel.md create mode 100644 docs/networking/network/network-discovery-trystero/src/plugin/plugin.md create mode 100644 docs/networking/network/network-discovery-trystero/src/transport/transport.md create mode 100644 docs/networking/network/network-discovery-trystero/src/types/types.md create mode 100644 docs/networking/network/network-discovery-webtorrent/README.md create mode 100644 docs/networking/network/network-discovery-webtorrent/src/core/webtorrent-discovery/webtorrent-discovery.md create mode 100644 docs/networking/network/network-discovery-webtorrent/src/errors/errors.md create mode 100644 docs/networking/network/network-discovery-webtorrent/src/otel/otel.md create mode 100644 docs/networking/network/network-discovery-webtorrent/src/plugin/plugin.md create mode 100644 docs/networking/network/network-discovery-webtorrent/src/transport/transport.md create mode 100644 docs/networking/network/network-discovery-webtorrent/src/types/types.md create mode 100644 docs/networking/network/network-gundb-server/README.md create mode 100644 docs/networking/network/network-gundb-server/src/errors/errors.md create mode 100644 docs/networking/network/network-gundb-server/src/health/health.md create mode 100644 docs/networking/network/network-gundb-server/src/otel/otel.md create mode 100644 docs/networking/network/network-gundb-server/src/server/listen-http.md create mode 100644 docs/networking/network/network-gundb-server/src/server/server.md create mode 100644 docs/networking/network/network-gundb-server/src/types/types.md create mode 100644 docs/networking/network/network-gundb-server/src/validation/validation.md create mode 100644 docs/networking/network/network-libp2p-server/README.md create mode 100644 docs/networking/network/network-libp2p-server/src/errors/errors.md create mode 100644 docs/networking/network/network-libp2p-server/src/health/health.md create mode 100644 docs/networking/network/network-libp2p-server/src/otel/otel.md create mode 100644 docs/networking/network/network-libp2p-server/src/server/health-listener.md create mode 100644 docs/networking/network/network-libp2p-server/src/server/peer-events.md create mode 100644 docs/networking/network/network-libp2p-server/src/server/server.md create mode 100644 docs/networking/network/network-libp2p-server/src/types/types.md create mode 100644 docs/networking/network/network-plugin-assignment/README.md create mode 100644 docs/networking/network/network-plugin-assignment/src/balancer/mesh-balancer.md create mode 100644 docs/networking/network/network-plugin-assignment/src/controller/admission-controller.md create mode 100644 docs/networking/network/network-plugin-assignment/src/engine/assignment-engine.md create mode 100644 docs/networking/network/network-plugin-assignment/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-assignment/src/tracker/mesh-capacity-tracker.md create mode 100644 docs/networking/network/network-plugin-audit-mesh/README.md create mode 100644 docs/networking/network/network-plugin-audit-mesh/src/compaction/log-compaction.md create mode 100644 docs/networking/network/network-plugin-audit-mesh/src/conflict/conflict-resolver.md create mode 100644 docs/networking/network/network-plugin-audit-mesh/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-audit-mesh/src/integrity/integrity-checker.md create mode 100644 docs/networking/network/network-plugin-audit-mesh/src/log/signed-log.md create mode 100644 docs/networking/network/network-plugin-audit-mesh/src/plugin/audit-mesh-plugin.md create mode 100644 docs/networking/network/network-plugin-audit-mesh/src/replicator/log-replicator.md create mode 100644 docs/networking/network/network-plugin-audit-mesh/src/retriever/log-retriever.md create mode 100644 docs/networking/network/network-plugin-audit-mesh/src/types/conflict.types.md create mode 100644 docs/networking/network/network-plugin-audit-mesh/src/types/log.types.md create mode 100644 docs/networking/network/network-plugin-audit-mesh/src/types/replication.types.md create mode 100644 docs/networking/network/network-plugin-auth/README.md create mode 100644 docs/networking/network/network-plugin-auth/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-auth/src/issuer/capability-token-issuer.md create mode 100644 docs/networking/network/network-plugin-auth/src/trust/cross-mesh-trust-validator.md create mode 100644 docs/networking/network/network-plugin-auth/src/verifier/mesh-membership-verifier.md create mode 100644 docs/networking/network/network-plugin-circuit-breaker/README.md create mode 100644 docs/networking/network/network-plugin-circuit-breaker/src/breaker/mesh-circuit-breaker.md create mode 100644 docs/networking/network/network-plugin-circuit-breaker/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-circuit-breaker/src/middleware/circuit-breaker-middleware.md create mode 100644 docs/networking/network/network-plugin-circuit-breaker/src/probe/half-open-probe.md create mode 100644 docs/networking/network/network-plugin-circuit-breaker/src/registry/circuit-breaker-registry.md create mode 100644 docs/networking/network/network-plugin-content-delivery/README.md create mode 100644 docs/networking/network/network-plugin-content-delivery/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-content-delivery/src/index/chunk-index.md create mode 100644 docs/networking/network/network-plugin-content-delivery/src/integrity/integrity-verifier.md create mode 100644 docs/networking/network/network-plugin-content-delivery/src/packer/packer-integration.md create mode 100644 docs/networking/network/network-plugin-content-delivery/src/plugin/content-delivery-plugin.md create mode 100644 docs/networking/network/network-plugin-content-delivery/src/prefetch/prefetch-engine.md create mode 100644 docs/networking/network/network-plugin-content-delivery/src/redundancy/redundancy-manager.md create mode 100644 docs/networking/network/network-plugin-content-delivery/src/router/chunk-request-router.md create mode 100644 docs/networking/network/network-plugin-content-delivery/src/store/chunk-store.md create mode 100644 docs/networking/network/network-plugin-content-delivery/src/throttle/bandwidth-throttler.md create mode 100644 docs/networking/network/network-plugin-content-delivery/src/types/chunk.types.md create mode 100644 docs/networking/network/network-plugin-content-delivery/src/types/redundancy.types.md create mode 100644 docs/networking/network/network-plugin-crypto-messages/README.md create mode 100644 docs/networking/network/network-plugin-crypto-messages/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-crypto-messages/src/identity/peer-identity-verifier.md create mode 100644 docs/networking/network/network-plugin-crypto-messages/src/key-rotation/key-rotation-manager.md create mode 100644 docs/networking/network/network-plugin-crypto-messages/src/log-chain/log-chain-signer.md create mode 100644 docs/networking/network/network-plugin-crypto-messages/src/plugin/crypto-messages-plugin.md create mode 100644 docs/networking/network/network-plugin-crypto-messages/src/signer/message-signer.md create mode 100644 docs/networking/network/network-plugin-crypto-messages/src/token/mesh-token-authority.md create mode 100644 docs/networking/network/network-plugin-crypto-messages/src/token/session-token-authority.md create mode 100644 docs/networking/network/network-plugin-crypto-messages/src/types/identity.types.md create mode 100644 docs/networking/network/network-plugin-crypto-messages/src/types/signature.types.md create mode 100644 docs/networking/network/network-plugin-crypto-messages/src/types/token.types.md create mode 100644 docs/networking/network/network-plugin-devtools/README.md create mode 100644 docs/networking/network/network-plugin-devtools/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-devtools/src/inspector/state-inspector.md create mode 100644 docs/networking/network/network-plugin-devtools/src/plugin/devtools-plugin.md create mode 100644 docs/networking/network/network-plugin-devtools/src/profiler/performance-profiler.md create mode 100644 docs/networking/network/network-plugin-devtools/src/profiler/performance-profiler.suggestions.md create mode 100644 docs/networking/network/network-plugin-devtools/src/simulator/simulation-config-tool.md create mode 100644 docs/networking/network/network-plugin-devtools/src/types/inspector.types.md create mode 100644 docs/networking/network/network-plugin-devtools/src/types/profiler.types.md create mode 100644 docs/networking/network/network-plugin-devtools/src/types/simulator.types.md create mode 100644 docs/networking/network/network-plugin-devtools/src/types/visualizer.types.md create mode 100644 docs/networking/network/network-plugin-devtools/src/visualizer/network-visualizer.md create mode 100644 docs/networking/network/network-plugin-devtools/src/visualizer/svg-renderer.md create mode 100644 docs/networking/network/network-plugin-failover/README.md create mode 100644 docs/networking/network/network-plugin-failover/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-failover/src/failover/failover-coordinator.md create mode 100644 docs/networking/network/network-plugin-failover/src/health/health-monitor.md create mode 100644 docs/networking/network/network-plugin-failover/src/heartbeat/heartbeat-manager.md create mode 100644 docs/networking/network/network-plugin-failover/src/plugin/failover-plugin.md create mode 100644 docs/networking/network/network-plugin-failover/src/promoter/promoter-manager.md create mode 100644 docs/networking/network/network-plugin-governance/README.md create mode 100644 docs/networking/network/network-plugin-governance/src/election/election-engine.md create mode 100644 docs/networking/network/network-plugin-governance/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-governance/src/plugin/governance-plugin.md create mode 100644 docs/networking/network/network-plugin-governance/src/reputation/reputation-tracker.md create mode 100644 docs/networking/network/network-plugin-governance/src/scoring/candidate-scorer.md create mode 100644 docs/networking/network/network-plugin-governance/src/transition/transition-manager.md create mode 100644 docs/networking/network/network-plugin-governance/src/voting/voting-manager.md create mode 100644 docs/networking/network/network-plugin-intra-relay/README.md create mode 100644 docs/networking/network/network-plugin-intra-relay/src/connection/relay-connection-manager.md create mode 100644 docs/networking/network/network-plugin-intra-relay/src/discovery/relay-discovery.md create mode 100644 docs/networking/network/network-plugin-intra-relay/src/envelope/relay-envelope.md create mode 100644 docs/networking/network/network-plugin-intra-relay/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-intra-relay/src/loop/loop-prevention.md create mode 100644 docs/networking/network/network-plugin-intra-relay/src/monitor/relay-performance-monitor.md create mode 100644 docs/networking/network/network-plugin-intra-relay/src/plugin/intra-relay-plugin.md create mode 100644 docs/networking/network/network-plugin-intra-relay/src/security/relay-security-manager.md create mode 100644 docs/networking/network/network-plugin-intra-relay/src/selector/relay-selector.md create mode 100644 docs/networking/network/network-plugin-intra-relay/src/types/relay.types.md create mode 100644 docs/networking/network/network-plugin-intra-relay/src/types/security.types.md create mode 100644 docs/networking/network/network-plugin-middleware/README.md create mode 100644 docs/networking/network/network-plugin-middleware/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-middleware/src/i18n/i18n-middleware.md create mode 100644 docs/networking/network/network-plugin-middleware/src/logging/logging-middleware.md create mode 100644 docs/networking/network/network-plugin-middleware/src/manager/middleware-manager.md create mode 100644 docs/networking/network/network-plugin-middleware/src/metrics/metrics-middleware.md create mode 100644 docs/networking/network/network-plugin-middleware/src/plugin/middleware-plugin.md create mode 100644 docs/networking/network/network-plugin-middleware/src/security/security-middleware.md create mode 100644 docs/networking/network/network-plugin-middleware/src/throttling/throttling-middleware.md create mode 100644 docs/networking/network/network-plugin-middleware/src/transformation/transformation-middleware.md create mode 100644 docs/networking/network/network-plugin-middleware/src/types/chain.types.md create mode 100644 docs/networking/network/network-plugin-middleware/src/types/middleware.types.md create mode 100644 docs/networking/network/network-plugin-middleware/src/validation/validation-middleware.md create mode 100644 docs/networking/network/network-plugin-migration/README.md create mode 100644 docs/networking/network/network-plugin-migration/src/coordinator/migration-coordinator.md create mode 100644 docs/networking/network/network-plugin-migration/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-migration/src/state-transfer/state-transfer-protocol.md create mode 100644 docs/networking/network/network-plugin-migration/src/tunnel/forwarding-tunnel.md create mode 100644 docs/networking/network/network-plugin-monitor/README.md create mode 100644 docs/networking/network/network-plugin-monitor/src/alert/alert-engine.md create mode 100644 docs/networking/network/network-plugin-monitor/src/collector/metric-collector.md create mode 100644 docs/networking/network/network-plugin-monitor/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-monitor/src/grafana/dashboard-generator.md create mode 100644 docs/networking/network/network-plugin-monitor/src/history/historical-data-store.md create mode 100644 docs/networking/network/network-plugin-monitor/src/monitor/network-monitor.md create mode 100644 docs/networking/network/network-plugin-monitor/src/plugin/monitor-plugin.md create mode 100644 docs/networking/network/network-plugin-monitor/src/prometheus/prometheus-exposition.md create mode 100644 docs/networking/network/network-plugin-monitor/src/quality/bandwidth-monitor.md create mode 100644 docs/networking/network/network-plugin-monitor/src/quality/degradation-manager.md create mode 100644 docs/networking/network/network-plugin-monitor/src/quality/quality-middleware.md create mode 100644 docs/networking/network/network-plugin-monitor/src/quality/quality-types.md create mode 100644 docs/networking/network/network-plugin-monitor/src/sampler/adaptive-sampler.md create mode 100644 docs/networking/network/network-plugin-monitor/src/tracer/network-tracer.md create mode 100644 docs/networking/network/network-plugin-monitor/src/types/alert.types.md create mode 100644 docs/networking/network/network-plugin-monitor/src/types/metric.types.md create mode 100644 docs/networking/network/network-plugin-monitor/src/types/trace.types.md create mode 100644 docs/networking/network/network-plugin-partition/README.md create mode 100644 docs/networking/network/network-plugin-partition/src/detector/partition-detector.md create mode 100644 docs/networking/network/network-plugin-partition/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-partition/src/merge/merge-protocol.md create mode 100644 docs/networking/network/network-plugin-partition/src/quorum/quorum-resolver.md create mode 100644 docs/networking/network/network-plugin-protocol/README.md create mode 100644 docs/networking/network/network-plugin-protocol/src/batcher/batcher.md create mode 100644 docs/networking/network/network-plugin-protocol/src/decoder/decoder.md create mode 100644 docs/networking/network/network-plugin-protocol/src/encoder/encoder.md create mode 100644 docs/networking/network/network-plugin-protocol/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-protocol/src/pipeline/pipeline.md create mode 100644 docs/networking/network/network-plugin-protocol/src/protocol/protocol-plugin.md create mode 100644 docs/networking/network/network-plugin-protocol/src/protocol/protocol.md create mode 100644 docs/networking/network/network-plugin-protocol/src/queue/queue.md create mode 100644 docs/networking/network/network-plugin-protocol/src/serializer/serializer.md create mode 100644 docs/networking/network/network-plugin-protocol/src/ttl/ttl.md create mode 100644 docs/networking/network/network-plugin-protocol/src/types/protocol.types.md create mode 100644 docs/networking/network/network-plugin-qos/README.md create mode 100644 docs/networking/network/network-plugin-qos/src/classifier/message-priority-classifier.md create mode 100644 docs/networking/network/network-plugin-qos/src/enforcer/bandwidth-quota-enforcer.md create mode 100644 docs/networking/network/network-plugin-qos/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-qos/src/monitor/congestion-monitor.md create mode 100644 docs/networking/network/network-plugin-qos/src/router/qos-router.md create mode 100644 docs/networking/network/network-plugin-registry/README.md create mode 100644 docs/networking/network/network-plugin-registry/src/encoder/encoder.md create mode 100644 docs/networking/network/network-plugin-registry/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-registry/src/registry-plugin.md create mode 100644 docs/networking/network/network-plugin-registry/src/registry/registry.md create mode 100644 docs/networking/network/network-plugin-registry/src/sync/sync.md create mode 100644 docs/networking/network/network-plugin-relay/README.md create mode 100644 docs/networking/network/network-plugin-relay/src/backbone/host-backbone-transport.md create mode 100644 docs/networking/network/network-plugin-relay/src/directory/mesh-directory.md create mode 100644 docs/networking/network/network-plugin-relay/src/envelope/cross-mesh-envelope.md create mode 100644 docs/networking/network/network-plugin-relay/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-relay/src/loop-prevention/loop-guard.md create mode 100644 docs/networking/network/network-plugin-relay/src/manager/relay-manager.md create mode 100644 docs/networking/network/network-plugin-relay/src/router/relay-router.md create mode 100644 docs/networking/network/network-plugin-server-bridge/README.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/buffer/log-buffer.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/command/command-dispatcher.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/command/command-dispatcher.types.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/error-codes/error-codes.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/fsm/graceful-degradation-fsm.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/gateway/server-gateway.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/gateway/server-gateway.types.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/hosting/backup-coordinator.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/hosting/failover-coordinator.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/hosting/hosting-model-config.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/hosting/pure-client-coordinator.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/hosting/server-based-coordinator.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/multiplexer/heartbeat-multiplexer.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/offline/offline-mode-coordinator.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/plugin/server-bridge-plugin.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/reconciliation/reconciliation-protocol.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/reconciliation/reconciliation-protocol.types.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/types/buffer.types.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/types/command.types.md create mode 100644 docs/networking/network/network-plugin-server-bridge/src/types/state.types.md create mode 100644 docs/networking/network/network-plugin-session/README.md create mode 100644 docs/networking/network/network-plugin-session/src/bridge/parent-state-bridge.md create mode 100644 docs/networking/network/network-plugin-session/src/capacity/session-capacity-enforcer.md create mode 100644 docs/networking/network/network-plugin-session/src/election/session-host-election.md create mode 100644 docs/networking/network/network-plugin-session/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-session/src/plugin/session-plugin.md create mode 100644 docs/networking/network/network-plugin-session/src/registry/session-registry.md create mode 100644 docs/networking/network/network-plugin-session/src/router/session-router.md create mode 100644 docs/networking/network/network-plugin-session/src/session/session-manager.md create mode 100644 docs/networking/network/network-plugin-session/src/transition/session-transition-manager.md create mode 100644 docs/networking/network/network-plugin-session/src/tree/session-tree.md create mode 100644 docs/networking/network/network-plugin-session/src/types/message.types.md create mode 100644 docs/networking/network/network-plugin-session/src/types/session.types.md create mode 100644 docs/networking/network/network-plugin-session/src/types/transition.types.md create mode 100644 docs/networking/network/network-plugin-session/src/types/tree.types.md create mode 100644 docs/networking/network/network-plugin-simulation/README.md create mode 100644 docs/networking/network/network-plugin-simulation/src/chaos/chaos-engine.md create mode 100644 docs/networking/network/network-plugin-simulation/src/conditions/network-condition-injector.md create mode 100644 docs/networking/network/network-plugin-simulation/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-simulation/src/plugin/simulation-plugin.md create mode 100644 docs/networking/network/network-plugin-simulation/src/scenario/scenario-runner.md create mode 100644 docs/networking/network/network-plugin-simulation/src/simulator/network-simulator.md create mode 100644 docs/networking/network/network-plugin-simulation/src/types/condition.types.md create mode 100644 docs/networking/network/network-plugin-simulation/src/types/scenario.types.md create mode 100644 docs/networking/network/network-plugin-simulation/src/types/simulation.types.md create mode 100644 docs/networking/network/network-plugin-simulation/src/virtual-node/virtual-node.md create mode 100644 docs/networking/network/network-plugin-state/README.md create mode 100644 docs/networking/network/network-plugin-state/src/bloom/bloom-filter-comparator.md create mode 100644 docs/networking/network/network-plugin-state/src/delta/delta-compressor.md create mode 100644 docs/networking/network/network-plugin-state/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-state/src/plugin/state-plugin.md create mode 100644 docs/networking/network/network-plugin-state/src/pruner/state-history-pruner.md create mode 100644 docs/networking/network/network-plugin-state/src/reconciler/state-reconciler.md create mode 100644 docs/networking/network/network-plugin-state/src/resource/resource-adapter.md create mode 100644 docs/networking/network/network-plugin-state/src/state/state-manager.md create mode 100644 docs/networking/network/network-plugin-state/src/strategy/path-strategy-registry.md create mode 100644 docs/networking/network/network-plugin-state/src/sync/state-sync-engine.md create mode 100644 docs/networking/network/network-plugin-state/src/types/reconciliation.types.md create mode 100644 docs/networking/network/network-plugin-state/src/types/state.types.md create mode 100644 docs/networking/network/network-plugin-state/src/types/sync.types.md create mode 100644 docs/networking/network/network-plugin-topology/README.md create mode 100644 docs/networking/network/network-plugin-topology/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-topology/src/group/group-manager.md create mode 100644 docs/networking/network/network-plugin-topology/src/latency/latency-assigner.md create mode 100644 docs/networking/network/network-plugin-topology/src/plugin/topology-plugin.md create mode 100644 docs/networking/network/network-plugin-topology/src/topology/hierarchical-topology.md create mode 100644 docs/networking/network/network-plugin-transport-manager/README.md create mode 100644 docs/networking/network/network-plugin-transport-manager/src/analyzer/quality-trend-analyzer.md create mode 100644 docs/networking/network/network-plugin-transport-manager/src/balancer/round-robin-balancer.md create mode 100644 docs/networking/network/network-plugin-transport-manager/src/error-codes.md create mode 100644 docs/networking/network/network-plugin-transport-manager/src/health/transport-health-monitor.md create mode 100644 docs/networking/network/network-plugin-transport-manager/src/negotiator/capability-negotiator.md create mode 100644 docs/networking/network/network-plugin-transport-manager/src/persistence/session-persistence-buffer.md create mode 100644 docs/networking/network/network-plugin-transport-manager/src/plugin/transport-manager-plugin.md create mode 100644 docs/networking/network/network-plugin-transport-manager/src/pool/transport-pool.md create mode 100644 docs/networking/network/network-plugin-transport-manager/src/priority/priority-router.md create mode 100644 docs/networking/network/network-plugin-transport-manager/src/recovery/connection-recovery-manager.md create mode 100644 docs/networking/network/network-plugin-transport-manager/src/recovery/session-continuity-guard.md create mode 100644 docs/networking/network/network-plugin-transport-manager/src/scheduler/bandwidth-conservator.md create mode 100644 docs/networking/network/network-plugin-transport-manager/src/scheduler/battery-aware-scheduler.md create mode 100644 docs/networking/network/network-plugin-transport-manager/src/selector/preemptive-selector.md create mode 100644 docs/networking/network/network-plugin-transport-manager/src/selector/transport-selector.md create mode 100644 docs/networking/network/network-plugin-transport-manager/src/types/priority.types.md create mode 100644 docs/networking/network/network-plugin-transport-manager/src/types/selector.types.md create mode 100644 docs/networking/network/network-plugin-transport-manager/src/types/transport.types.md create mode 100644 docs/networking/network/network-testing/README.md create mode 100644 docs/networking/network/network-testing/src/assertions/event-capture/event-capture.md create mode 100644 docs/networking/network/network-testing/src/error-codes.md create mode 100644 docs/networking/network/network-testing/src/factories/test-peer/test-peer.md create mode 100644 docs/networking/network/network-testing/src/simulators/condition-simulator/condition-simulator.md create mode 100644 docs/networking/network/network-testing/src/transports/fake-websocket/fake-websocket.md create mode 100644 docs/networking/network/network-testing/src/transports/memory-transport/memory-transport.md create mode 100644 docs/networking/network/network-testing/src/types/common.md create mode 100644 docs/networking/network/network-transport-hyperswarm/README.md create mode 100644 docs/networking/network/network-transport-hyperswarm/src/connections/connections.md create mode 100644 docs/networking/network/network-transport-hyperswarm/src/discovery/discovery.md create mode 100644 docs/networking/network/network-transport-hyperswarm/src/errors/errors.md create mode 100644 docs/networking/network/network-transport-hyperswarm/src/messaging/messaging.md create mode 100644 docs/networking/network/network-transport-hyperswarm/src/otel/otel.md create mode 100644 docs/networking/network/network-transport-hyperswarm/src/plugin/plugin.md create mode 100644 docs/networking/network/network-transport-hyperswarm/src/reputation/reputation.md create mode 100644 docs/networking/network/network-transport-hyperswarm/src/security/security.md create mode 100644 docs/networking/network/network-transport-hyperswarm/src/transport/transport.md create mode 100644 docs/networking/network/network-transport-hyperswarm/src/types/types.md create mode 100644 docs/networking/network/network-transport-libp2p/README.md create mode 100644 docs/networking/network/network-transport-libp2p/src/connection/connection.md create mode 100644 docs/networking/network/network-transport-libp2p/src/errors/errors.md create mode 100644 docs/networking/network/network-transport-libp2p/src/messaging/frame.md create mode 100644 docs/networking/network/network-transport-libp2p/src/messaging/peer-message.md create mode 100644 docs/networking/network/network-transport-libp2p/src/messaging/send.md create mode 100644 docs/networking/network/network-transport-libp2p/src/otel/otel.md create mode 100644 docs/networking/network/network-transport-libp2p/src/plugin/plugin.md create mode 100644 docs/networking/network/network-transport-libp2p/src/streams/streams.md create mode 100644 docs/networking/network/network-transport-libp2p/src/transport/transport.md create mode 100644 docs/networking/network/network-transport-libp2p/src/types/types.md create mode 100644 docs/networking/network/network-transport-standby/README.md create mode 100644 docs/networking/network/network-transport-standby/src/errors/errors.md create mode 100644 docs/networking/network/network-transport-standby/src/health/monitor.md create mode 100644 docs/networking/network/network-transport-standby/src/otel/otel.md create mode 100644 docs/networking/network/network-transport-standby/src/plugin/plugin.md create mode 100644 docs/networking/network/network-transport-standby/src/pool/pool.md create mode 100644 docs/networking/network/network-transport-standby/src/reconnect/reconnect.md create mode 100644 docs/networking/network/network-transport-standby/src/transport/transport.md create mode 100644 docs/networking/network/network-transport-standby/src/types/types.md create mode 100644 docs/networking/network/network-transport-webrtc/README.md create mode 100644 docs/networking/network/network-transport-webrtc/src/data-channel/data-channel-manager.md create mode 100644 docs/networking/network/network-transport-webrtc/src/error-codes.md create mode 100644 docs/networking/network/network-transport-webrtc/src/ice/ice-manager.md create mode 100644 docs/networking/network/network-transport-webrtc/src/mesh/webrtc-mesh.md create mode 100644 docs/networking/network/network-transport-webrtc/src/ping/ping-manager.md create mode 100644 docs/networking/network/network-transport-webrtc/src/plugin/plugin.md create mode 100644 docs/networking/network/network-transport-webrtc/src/signaling/signaling-client.md create mode 100644 docs/networking/network/network-transport-webrtc/src/signaling/websocket-signaling-client.md create mode 100644 docs/networking/network/network-transport-webrtc/src/transport/transport.md create mode 100644 docs/networking/network/network-transport-webrtc/src/types/types.md create mode 100644 docs/networking/network/network-transport-websockets/README.md create mode 100644 docs/networking/network/network-transport-websockets/src/adapters/native-adapter.md create mode 100644 docs/networking/network/network-transport-websockets/src/core/client/client.md create mode 100644 docs/networking/network/network-transport-websockets/src/core/heartbeat/heartbeat.md create mode 100644 docs/networking/network/network-transport-websockets/src/core/queue/queue.md create mode 100644 docs/networking/network/network-transport-websockets/src/error-codes.md create mode 100644 docs/networking/network/network-transport-websockets/src/otel/otel.md create mode 100644 docs/networking/network/network-transport-websockets/src/plugin/plugin.md create mode 100644 docs/networking/network/network-transport-websockets/src/transport/transport.md create mode 100644 docs/networking/network/network-transport-websockets/src/types/common.md create mode 100644 docs/networking/network/network-trystero-server/README.md create mode 100644 docs/networking/network/network-trystero-server/src/errors/errors.md create mode 100644 docs/networking/network/network-trystero-server/src/health/health.md create mode 100644 docs/networking/network/network-trystero-server/src/otel/otel.md create mode 100644 docs/networking/network/network-trystero-server/src/server/broker-select.md create mode 100644 docs/networking/network/network-trystero-server/src/server/health-listener.md create mode 100644 docs/networking/network/network-trystero-server/src/server/peer-events.md create mode 100644 docs/networking/network/network-trystero-server/src/server/server.md create mode 100644 docs/networking/network/network-trystero-server/src/types/types.md create mode 100644 docs/networking/network/network/README.md create mode 100644 docs/networking/network/network/src/bus/bus.md create mode 100644 docs/networking/network/network/src/envelope/envelope.md create mode 100644 docs/networking/network/network/src/error-codes.md create mode 100644 docs/networking/network/network/src/events/events.md create mode 100644 docs/networking/network/network/src/manager/manager.md create mode 100644 docs/networking/network/network/src/node/node.md create mode 100644 docs/networking/network/network/src/plugin/plugin.md create mode 100644 docs/networking/network/network/src/router/router.md create mode 100644 docs/networking/network/network/src/timestamp/timestamp.md create mode 100644 docs/networking/network/network/src/transport/transport.md create mode 100644 docs/networking/network/network/src/types/network.types.md create mode 100644 docs/networking/network/network/src/version/version.md create mode 100644 docs/networking/network/react-network-libp2p-demo/README.md create mode 100644 docs/networking/network/react-network-libp2p-demo/src/components/libp2p-demo/libp2p-demo.md create mode 100644 docs/networking/network/react-network-libp2p-demo/src/components/log-panel/log-panel.md create mode 100644 docs/networking/network/react-network-libp2p-demo/src/components/node-controls/node-controls.md create mode 100644 docs/networking/network/react-network-libp2p-demo/src/components/node-status-panel/node-status-panel.md create mode 100644 docs/networking/network/react-network-libp2p-demo/src/components/peer-interaction-panel/peer-interaction-panel.md create mode 100644 docs/networking/network/react-network-libp2p-demo/src/components/peer-list/peer-list.md create mode 100644 docs/networking/network/react-network-libp2p-demo/src/errors/errors.md create mode 100644 docs/networking/network/react-network-libp2p-demo/src/hooks/use-libp2p-demo/use-libp2p-demo.md create mode 100644 docs/networking/network/react-network-libp2p-demo/src/hooks/use-libp2p-demo/wire-peer-events.md create mode 100644 docs/networking/network/react-network-libp2p-demo/src/types/log-entry.types.md create mode 100644 docs/networking/network/react-network-libp2p-demo/src/types/peer-info.types.md create mode 100644 docs/networking/network/service-discovery/README.md create mode 100644 docs/networking/network/service-discovery/src/core/service-registry/service-registry.md create mode 100644 docs/networking/network/service-discovery/src/errors/errors.md create mode 100644 docs/networking/network/service-discovery/src/otel/otel.md create mode 100644 docs/networking/network/service-discovery/src/types/types.md create mode 100644 docs/networking/network/websocket-gateway/README.md create mode 100644 docs/networking/network/websocket-gateway/src/channel/channel.md create mode 100644 docs/networking/network/websocket-gateway/src/errors/errors.md create mode 100644 docs/networking/network/websocket-gateway/src/gateway/access-gate.md create mode 100644 docs/networking/network/websocket-gateway/src/gateway/channel-manager.md create mode 100644 docs/networking/network/websocket-gateway/src/gateway/channel-ops.md create mode 100644 docs/networking/network/websocket-gateway/src/gateway/client-lifecycle.md create mode 100644 docs/networking/network/websocket-gateway/src/gateway/defaults.md create mode 100644 docs/networking/network/websocket-gateway/src/gateway/gateway-deps.md create mode 100644 docs/networking/network/websocket-gateway/src/gateway/gateway.md create mode 100644 docs/networking/network/websocket-gateway/src/gateway/heartbeat.md create mode 100644 docs/networking/network/websocket-gateway/src/gateway/lifecycle.md create mode 100644 docs/networking/network/websocket-gateway/src/gateway/message-factory.md create mode 100644 docs/networking/network/websocket-gateway/src/gateway/presence-fire.md create mode 100644 docs/networking/network/websocket-gateway/src/gateway/presence-webhook.md create mode 100644 docs/networking/network/websocket-gateway/src/gateway/room-ops.md create mode 100644 docs/networking/network/websocket-gateway/src/health/health.md create mode 100644 docs/networking/network/websocket-gateway/src/otel/otel.md create mode 100644 docs/networking/network/websocket-gateway/src/presence/presence.md create mode 100644 docs/networking/network/websocket-gateway/src/room/room.md create mode 100644 docs/networking/network/websocket-gateway/src/types/types.md create mode 100644 docs/observability/README.md create mode 100644 docs/observability/_intro.md create mode 100644 docs/observability/monitor/README.md create mode 100644 docs/observability/monitor/_intro.md create mode 100644 docs/observability/monitor/analytics-browser/README.md create mode 100644 docs/observability/monitor/analytics-browser/src/consent/consent.md create mode 100644 docs/observability/monitor/analytics-browser/src/error-codes/error-codes.md create mode 100644 docs/observability/monitor/analytics-browser/src/internal/id/id.md create mode 100644 docs/observability/monitor/analytics-browser/src/pii/pii.md create mode 100644 docs/observability/monitor/analytics-browser/src/sampling/sampling.md create mode 100644 docs/observability/monitor/analytics-browser/src/schema/analytics-event-schema.md create mode 100644 docs/observability/monitor/analytics-browser/src/session/session.md create mode 100644 docs/observability/monitor/analytics-browser/src/storage/storage.md create mode 100644 docs/observability/monitor/analytics-browser/src/telemetry/telemetry.md create mode 100644 docs/observability/monitor/analytics-browser/src/tracker/tracker.md create mode 100644 docs/observability/monitor/analytics-browser/src/transport/batch.md create mode 100644 docs/observability/monitor/analytics-browser/src/transport/beacon.md create mode 100644 docs/observability/monitor/analytics-browser/src/types/analytics.types.md create mode 100644 docs/observability/monitor/audit-logging/README.md create mode 100644 docs/observability/monitor/audit-logging/src/adapters/memory/memory.md create mode 100644 docs/observability/monitor/audit-logging/src/adapters/storage/storage.md create mode 100644 docs/observability/monitor/audit-logging/src/core/audit-logger/audit-logger.md create mode 100644 docs/observability/monitor/audit-logging/src/core/chain-integrity/chain-integrity.md create mode 100644 docs/observability/monitor/audit-logging/src/errors/audit-error.md create mode 100644 docs/observability/monitor/audit-logging/src/schemas/audit-logging.schemas.md create mode 100644 docs/observability/monitor/audit-logging/src/types/audit-logging.types.md create mode 100644 docs/observability/monitor/health-check/README.md create mode 100644 docs/observability/monitor/health-check/src/error-codes/error-codes.md create mode 100644 docs/observability/monitor/health-check/src/health-checker/health-checker.helpers.md create mode 100644 docs/observability/monitor/health-check/src/health-checker/health-checker.md create mode 100644 docs/observability/monitor/health-check/src/http-check/http-check.md create mode 100644 docs/observability/monitor/health-check/src/response-builder/response-builder.md create mode 100644 docs/observability/monitor/health-check/src/tcp-check/tcp-check.md create mode 100644 docs/observability/monitor/health-check/src/telemetry/telemetry.md create mode 100644 docs/observability/monitor/logger/README.md create mode 100644 docs/observability/monitor/logger/src/abstract/abstract-logger.md create mode 100644 docs/observability/monitor/logger/src/console/console-logger.md create mode 100644 docs/observability/monitor/logger/src/error-bridge/error-bridge.md create mode 100644 docs/observability/monitor/logger/src/errors/logger-error.md create mode 100644 docs/observability/monitor/logger/src/event/event-logger.md create mode 100644 docs/observability/monitor/logger/src/factory/factory.md create mode 100644 docs/observability/monitor/logger/src/init/init.md create mode 100644 docs/observability/monitor/logger/src/otel/otel-context.md create mode 100644 docs/observability/monitor/logger/src/record/log-record.md create mode 100644 docs/observability/monitor/logger/src/redaction/redaction.md create mode 100644 docs/observability/monitor/logger/src/sampling/sampling.md create mode 100644 docs/observability/monitor/logger/src/sink/buffered-sink.md create mode 100644 docs/observability/monitor/logger/src/sink/console-sink.md create mode 100644 docs/observability/monitor/logger/src/sink/json-sink.md create mode 100644 docs/observability/monitor/logger/src/sink/sink.md create mode 100644 docs/observability/monitor/logger/src/storage/storage-logger.md create mode 100644 docs/observability/monitor/opentelemetry/README.md create mode 100644 docs/observability/monitor/opentelemetry/src/core/propagation/propagation.md create mode 100644 docs/observability/monitor/opentelemetry/src/core/sdk/noop-sdk.md create mode 100644 docs/observability/monitor/opentelemetry/src/core/sdk/sdk-factory.md create mode 100644 docs/observability/monitor/opentelemetry/src/errors/opentelemetry-error.md create mode 100644 docs/observability/monitor/opentelemetry/src/schemas/otel-config.schema.md create mode 100644 docs/observability/monitor/opentelemetry/src/utils/metrics-utils.md create mode 100644 docs/observability/monitor/opentelemetry/src/utils/resource.md create mode 100644 docs/observability/monitor/opentelemetry/src/utils/span-utils.md create mode 100644 docs/persistence/README.md create mode 100644 docs/persistence/_intro.md create mode 100644 docs/persistence/cache/README.md create mode 100644 docs/persistence/cache/_intro.md create mode 100644 docs/persistence/cache/cache-redis/README.md create mode 100644 docs/persistence/cache/cache-redis/src/errors/errors.md create mode 100644 docs/persistence/cache/cache-redis/src/redis-cache/redis-cache.md create mode 100644 docs/persistence/cache/cache-redis/src/redis-like/redis-like.md create mode 100644 docs/persistence/cache/cache-redis/src/registry-augment/registry-augment.md create mode 100644 docs/persistence/cache/cache-storage/README.md create mode 100644 docs/persistence/cache/cache-storage/src/codec/identity.md create mode 100644 docs/persistence/cache/cache-storage/src/codec/json.md create mode 100644 docs/persistence/cache/cache-storage/src/errors/errors.md create mode 100644 docs/persistence/cache/cache-storage/src/header/header.md create mode 100644 docs/persistence/cache/cache-storage/src/registry-augment/registry-augment.md create mode 100644 docs/persistence/cache/cache-storage/src/storage-cache/storage-cache.md create mode 100644 docs/persistence/cache/cache/README.md create mode 100644 docs/persistence/cache/cache/src/abstract/abstract-cache/abstract-cache.md create mode 100644 docs/persistence/cache/cache/src/abstract/namespaced-cache/namespaced-cache.md create mode 100644 docs/persistence/cache/cache/src/errors/cache-error.md create mode 100644 docs/persistence/cache/cache/src/factory/cache/cache.md create mode 100644 docs/persistence/cache/cache/src/factory/registry/registry.md create mode 100644 docs/persistence/cache/cache/src/memory/memory-cache/memory-cache.md create mode 100644 docs/persistence/cache/cache/src/types/common.md create mode 100644 docs/persistence/cache/cache/src/types/schemas.md create mode 100644 docs/persistence/database/README.md create mode 100644 docs/persistence/database/_intro.md create mode 100644 docs/persistence/database/db-sqlite/README.md create mode 100644 docs/persistence/database/db-sqlite/src/adapter/adapter.bun.md create mode 100644 docs/persistence/database/db-sqlite/src/adapter/adapter.md create mode 100644 docs/persistence/database/db-sqlite/src/adapter/adapter.wasm.md create mode 100644 docs/persistence/database/db-sqlite/src/cache/cache.md create mode 100644 docs/persistence/database/db-sqlite/src/conformance/conformance-suite.md create mode 100644 docs/persistence/database/db-sqlite/src/connection/connection.md create mode 100644 docs/persistence/database/db-sqlite/src/drivers/bun-driver.md create mode 100644 docs/persistence/database/db-sqlite/src/drivers/wasm-driver.md create mode 100644 docs/persistence/database/db-sqlite/src/drivers/wasm-worker.md create mode 100644 docs/persistence/database/db-sqlite/src/errors/errors.md create mode 100644 docs/persistence/database/db-sqlite/src/migration/migration.md create mode 100644 docs/persistence/database/db-sqlite/src/otel/otel.md create mode 100644 docs/persistence/database/db-sqlite/src/schemas/schemas.md create mode 100644 docs/persistence/database/db-sqlite/src/unsafe/unsafe.md create mode 100644 docs/persistence/database/db/README.md create mode 100644 docs/persistence/database/db/src/adapter/database-adapter.md create mode 100644 docs/persistence/database/db/src/connection/singleton.md create mode 100644 docs/persistence/database/db/src/errors/database-error.md create mode 100644 docs/persistence/database/db/src/migration/migration-runner.md create mode 100644 docs/persistence/database/db/src/telemetry/instruments.md create mode 100644 docs/persistence/database/db/src/telemetry/trace.md create mode 100644 docs/persistence/database/db/src/types/database-config.md create mode 100644 docs/persistence/database/migration/README.md create mode 100644 docs/persistence/database/migration/src/adapters/surrealdb/surrealdb.md create mode 100644 docs/persistence/database/migration/src/batch/batch-migrator/batch-migrator.md create mode 100644 docs/persistence/database/migration/src/errors/migration-error.md create mode 100644 docs/persistence/database/migration/src/lock/distributed-lock/distributed-lock.md create mode 100644 docs/persistence/database/migration/src/lock/memory-lock/memory-lock.md create mode 100644 docs/persistence/database/migration/src/lock/redis-lock/redis-lock.md create mode 100644 docs/persistence/database/migration/src/planner/migration-planner/migration-planner.md create mode 100644 docs/persistence/database/migration/src/runner/dry-run-reporter/dry-run-reporter.md create mode 100644 docs/persistence/database/migration/src/runner/migration-executor/migration-executor.md create mode 100644 docs/persistence/database/migration/src/runner/migration-runner/migration-runner.md create mode 100644 docs/persistence/database/migration/src/schemas/migration.schemas.md create mode 100644 docs/persistence/database/migration/src/status/migration-status/migration-status.md create mode 100644 docs/persistence/database/migration/src/store/database-store/database-store.md create mode 100644 docs/persistence/database/migration/src/store/memory-store/memory-store.md create mode 100644 docs/persistence/database/migration/src/types/migration.types.md create mode 100644 docs/persistence/database/migration/src/utils/checksum.md create mode 100644 docs/persistence/database/seed/README.md create mode 100644 docs/persistence/database/seed/src/builder/builder.md create mode 100644 docs/persistence/database/seed/src/error-codes/error-codes.md create mode 100644 docs/persistence/database/seed/src/fixtures/fixtures.md create mode 100644 docs/persistence/database/seed/src/registry/registry.md create mode 100644 docs/persistence/database/seed/src/runner/execute.md create mode 100644 docs/persistence/database/seed/src/runner/runner.md create mode 100644 docs/persistence/database/seed/src/types/common.md create mode 100644 docs/persistence/database/seed/src/utils/topo-sort/topo-sort.md create mode 100644 docs/persistence/database/surrealdb/README.md create mode 100644 docs/persistence/database/surrealdb/src/adapter/adapter/adapter.md create mode 100644 docs/persistence/database/surrealdb/src/adapter/crud/crud.md create mode 100644 docs/persistence/database/surrealdb/src/adapter/query-helpers/query-helpers.md create mode 100644 docs/persistence/database/surrealdb/src/adapter/transaction/transaction.md create mode 100644 docs/persistence/database/surrealdb/src/connection/connection.md create mode 100644 docs/persistence/database/surrealdb/src/errors/error.md create mode 100644 docs/persistence/database/surrealdb/src/init/init.md create mode 100644 docs/persistence/database/surrealdb/src/schema/discovery.md create mode 100644 docs/persistence/database/surrealdb/src/schemas/schemas.md create mode 100644 docs/persistence/database/surrealdb/src/singleton/singleton.md create mode 100644 docs/persistence/database/surrealdb/src/types/types.md create mode 100644 docs/persistence/database/surrealdb/src/utils/version-detector.md create mode 100644 docs/persistence/search/README.md create mode 100644 docs/persistence/search/_intro.md create mode 100644 docs/persistence/search/search/README.md create mode 100644 docs/persistence/search/search/src/engine/memory-engine/memory-engine.md create mode 100644 docs/persistence/search/search/src/errors/search-error.md create mode 100644 docs/persistence/search/search/src/schemas/search.schemas.md create mode 100644 docs/persistence/search/search/src/text/scorer/scorer.md create mode 100644 docs/persistence/search/search/src/text/tokenizer/tokenizer.md create mode 100644 docs/persistence/search/search/src/text/trigram/trigram.md create mode 100644 docs/persistence/search/search/src/types/search.types.md create mode 100644 docs/persistence/storage/README.md create mode 100644 docs/persistence/storage/_intro.md create mode 100644 docs/persistence/storage/storage-browser-indexeddb/README.md create mode 100644 docs/persistence/storage/storage-browser-indexeddb/src/error-codes/error-codes.md create mode 100644 docs/persistence/storage/storage-browser-indexeddb/src/idb-adapter/idb-adapter.md create mode 100644 docs/persistence/storage/storage-browser-indexeddb/src/indexeddb-storage/indexeddb-storage.config.md create mode 100644 docs/persistence/storage/storage-browser-indexeddb/src/indexeddb-storage/indexeddb-storage.crud.md create mode 100644 docs/persistence/storage/storage-browser-indexeddb/src/indexeddb-storage/indexeddb-storage.errors.md create mode 100644 docs/persistence/storage/storage-browser-indexeddb/src/indexeddb-storage/indexeddb-storage.md create mode 100644 docs/persistence/storage/storage-browser-indexeddb/src/indexeddb-storage/indexeddb-storage.ops.md create mode 100644 docs/persistence/storage/storage-browser-indexeddb/src/key-sanitizer/key-sanitizer.md create mode 100644 docs/persistence/storage/storage-browser-indexeddb/src/otel/otel.md create mode 100644 docs/persistence/storage/storage-browser-indexeddb/src/registry/registry.md create mode 100644 docs/persistence/storage/storage-browser-indexeddb/src/types/idb-like.types.md create mode 100644 docs/persistence/storage/storage-browser-indexeddb/src/types/indexeddb-storage.types.md create mode 100644 docs/persistence/storage/storage-browser-localstorage/README.md create mode 100644 docs/persistence/storage/storage-browser-localstorage/src/envelope/envelope.md create mode 100644 docs/persistence/storage/storage-browser-localstorage/src/error-codes.md create mode 100644 docs/persistence/storage/storage-browser-localstorage/src/in-memory-storage/in-memory-storage.md create mode 100644 docs/persistence/storage/storage-browser-localstorage/src/key-sanitizer/key-sanitizer.md create mode 100644 docs/persistence/storage/storage-browser-localstorage/src/local-storage-adapter/local-storage-adapter.md create mode 100644 docs/persistence/storage/storage-browser-localstorage/src/local-storage/local-storage.errors.md create mode 100644 docs/persistence/storage/storage-browser-localstorage/src/local-storage/local-storage.md create mode 100644 docs/persistence/storage/storage-browser-localstorage/src/local-storage/local-storage.ops.md create mode 100644 docs/persistence/storage/storage-browser-localstorage/src/local-storage/local-storage.partial.md create mode 100644 docs/persistence/storage/storage-browser-localstorage/src/local-storage/local-storage.slot.md create mode 100644 docs/persistence/storage/storage-browser-localstorage/src/otel/otel.md create mode 100644 docs/persistence/storage/storage-browser-localstorage/src/registry/registry.md create mode 100644 docs/persistence/storage/storage-browser-localstorage/src/types/local-storage-storage.types.md create mode 100644 docs/persistence/storage/storage-browser-localstorage/src/types/storage-like.types.md create mode 100644 docs/persistence/storage/storage-browser-opfs/README.md create mode 100644 docs/persistence/storage/storage-browser-opfs/src/error-codes.md create mode 100644 docs/persistence/storage/storage-browser-opfs/src/filename-codec/filename-codec.md create mode 100644 docs/persistence/storage/storage-browser-opfs/src/in-memory-opfs/in-memory-opfs.md create mode 100644 docs/persistence/storage/storage-browser-opfs/src/key-sanitizer/key-sanitizer.md create mode 100644 docs/persistence/storage/storage-browser-opfs/src/opfs-adapter/opfs-adapter.md create mode 100644 docs/persistence/storage/storage-browser-opfs/src/opfs-storage/opfs-storage.errors.md create mode 100644 docs/persistence/storage/storage-browser-opfs/src/opfs-storage/opfs-storage.md create mode 100644 docs/persistence/storage/storage-browser-opfs/src/opfs-storage/opfs-storage.ops.md create mode 100644 docs/persistence/storage/storage-browser-opfs/src/opfs-storage/opfs-storage.streams.md create mode 100644 docs/persistence/storage/storage-browser-opfs/src/otel/otel.md create mode 100644 docs/persistence/storage/storage-browser-opfs/src/registry/registry.md create mode 100644 docs/persistence/storage/storage-browser-opfs/src/types/opfs-like.types.md create mode 100644 docs/persistence/storage/storage-browser-opfs/src/types/opfs-storage.types.md create mode 100644 docs/persistence/storage/storage-cdn-bunnycdn/README.md create mode 100644 docs/persistence/storage/storage-cdn-bunnycdn/src/bunny-cdn-adapter/bunny-cdn-adapter.base.md create mode 100644 docs/persistence/storage/storage-cdn-bunnycdn/src/bunny-cdn-adapter/bunny-cdn-adapter.helpers.md create mode 100644 docs/persistence/storage/storage-cdn-bunnycdn/src/bunny-cdn-adapter/bunny-cdn-adapter.md create mode 100644 docs/persistence/storage/storage-cdn-bunnycdn/src/bunny-cdn-adapter/bunny-cdn-adapter.streams.md create mode 100644 docs/persistence/storage/storage-cdn-bunnycdn/src/error-codes/error-codes.md create mode 100644 docs/persistence/storage/storage-cdn-bunnycdn/src/key-sanitizer/key-sanitizer.md create mode 100644 docs/persistence/storage/storage-cdn-bunnycdn/src/otel/otel.md create mode 100644 docs/persistence/storage/storage-cdn-bunnycdn/src/pull-zone-client/pull-zone-client.md create mode 100644 docs/persistence/storage/storage-cdn-bunnycdn/src/registry/registry.md create mode 100644 docs/persistence/storage/storage-cdn-bunnycdn/src/retry-helper/retry-helper.md create mode 100644 docs/persistence/storage/storage-cdn-bunnycdn/src/storage-client/storage-client.md create mode 100644 docs/persistence/storage/storage-cdn-bunnycdn/src/token-auth/token-auth.md create mode 100644 docs/persistence/storage/storage-cdn-bunnycdn/src/types/adapter.types.md create mode 100644 docs/persistence/storage/storage-cdn-rackspace/README.md create mode 100644 docs/persistence/storage/storage-cdn-rackspace/src/auth-client/auth-client.md create mode 100644 docs/persistence/storage/storage-cdn-rackspace/src/cdn-client/cdn-client.md create mode 100644 docs/persistence/storage/storage-cdn-rackspace/src/error-codes/error-codes.md create mode 100644 docs/persistence/storage/storage-cdn-rackspace/src/key-sanitizer/key-sanitizer.md create mode 100644 docs/persistence/storage/storage-cdn-rackspace/src/otel/otel.md create mode 100644 docs/persistence/storage/storage-cdn-rackspace/src/rackspace-cdn-adapter/rackspace-cdn-adapter.base.md create mode 100644 docs/persistence/storage/storage-cdn-rackspace/src/rackspace-cdn-adapter/rackspace-cdn-adapter.cdn-methods.md create mode 100644 docs/persistence/storage/storage-cdn-rackspace/src/rackspace-cdn-adapter/rackspace-cdn-adapter.helpers.md create mode 100644 docs/persistence/storage/storage-cdn-rackspace/src/rackspace-cdn-adapter/rackspace-cdn-adapter.md create mode 100644 docs/persistence/storage/storage-cdn-rackspace/src/rackspace-cdn-adapter/rackspace-cdn-adapter.ops.md create mode 100644 docs/persistence/storage/storage-cdn-rackspace/src/rackspace-cdn-adapter/rackspace-cdn-adapter.streams.md create mode 100644 docs/persistence/storage/storage-cdn-rackspace/src/registry/registry.md create mode 100644 docs/persistence/storage/storage-cdn-rackspace/src/retry-helper/retry-helper.md create mode 100644 docs/persistence/storage/storage-cdn-rackspace/src/temp-url/temp-url.md create mode 100644 docs/persistence/storage/storage-cdn-rackspace/src/types/adapter.types.md create mode 100644 docs/persistence/storage/storage-cdn-rackspace/src/types/auth.types.md create mode 100644 docs/persistence/storage/storage-cdn/README.md create mode 100644 docs/persistence/storage/storage-cdn/src/cdn-adapter/cdn-adapter.md create mode 100644 docs/persistence/storage/storage-cdn/src/error-codes/error-codes.md create mode 100644 docs/persistence/storage/storage-cdn/src/guards/guards.md create mode 100644 docs/persistence/storage/storage-cdn/src/sign-url/sign-url.md create mode 100644 docs/persistence/storage/storage-cdn/src/storage-augment.md create mode 100644 docs/persistence/storage/storage-cdn/src/types/cdn-adapter.types.md create mode 100644 docs/persistence/storage/storage-cdn/src/types/cdn-capabilities.types.md create mode 100644 docs/persistence/storage/storage-cdn/src/types/sign-url.types.md create mode 100644 docs/persistence/storage/storage-file/README.md create mode 100644 docs/persistence/storage/storage-file/src/bun-fs/bun-fs.md create mode 100644 docs/persistence/storage/storage-file/src/error-codes.md create mode 100644 docs/persistence/storage/storage-file/src/key-sanitizer/key-sanitizer.md create mode 100644 docs/persistence/storage/storage-file/src/node-fs-storage/node-fs-storage.helpers.md create mode 100644 docs/persistence/storage/storage-file/src/node-fs-storage/node-fs-storage.md create mode 100644 docs/persistence/storage/storage-file/src/node-fs-storage/node-fs-storage.ops.md create mode 100644 docs/persistence/storage/storage-file/src/node-fs/node-fs.md create mode 100644 docs/persistence/storage/storage-file/src/otel/otel.md create mode 100644 docs/persistence/storage/storage-file/src/registry/registry.md create mode 100644 docs/persistence/storage/storage-file/src/retry-helper/retry-helper.md create mode 100644 docs/persistence/storage/storage-file/src/streams/streams.md create mode 100644 docs/persistence/storage/storage-file/src/types/fs-adapter.types.md create mode 100644 docs/persistence/storage/storage-file/src/types/node-fs-storage.types.md create mode 100644 docs/persistence/storage/storage-http/README.md create mode 100644 docs/persistence/storage/storage-http/src/constants/constants.md create mode 100644 docs/persistence/storage/storage-http/src/error-codes/error-codes.md create mode 100644 docs/persistence/storage/storage-http/src/etag-cache/etag-cache.md create mode 100644 docs/persistence/storage/storage-http/src/fetch-adapter/fetch-adapter.md create mode 100644 docs/persistence/storage/storage-http/src/http-storage/http-storage.helpers.md create mode 100644 docs/persistence/storage/storage-http/src/http-storage/http-storage.md create mode 100644 docs/persistence/storage/storage-http/src/http-storage/http-storage.ops.md create mode 100644 docs/persistence/storage/storage-http/src/http-storage/http-storage.streams.md create mode 100644 docs/persistence/storage/storage-http/src/key-sanitizer/key-sanitizer.md create mode 100644 docs/persistence/storage/storage-http/src/otel/otel.md create mode 100644 docs/persistence/storage/storage-http/src/range/range.md create mode 100644 docs/persistence/storage/storage-http/src/registry/registry.md create mode 100644 docs/persistence/storage/storage-http/src/retry-helper/retry-helper.md create mode 100644 docs/persistence/storage/storage-http/src/types/etag-cache.types.md create mode 100644 docs/persistence/storage/storage-http/src/types/fetch.types.md create mode 100644 docs/persistence/storage/storage-http/src/types/http-storage.types.md create mode 100644 docs/persistence/storage/storage-http/src/types/retry.types.md create mode 100644 docs/persistence/storage/storage-http/src/types/uploader.types.md create mode 100644 docs/persistence/storage/storage-http/src/uploader/uploader.md create mode 100644 docs/persistence/storage/storage-plugin-cache/README.md create mode 100644 docs/persistence/storage/storage-plugin-cache/src/cached-storage/cached-storage.clear.md create mode 100644 docs/persistence/storage/storage-plugin-cache/src/cached-storage/cached-storage.context.md create mode 100644 docs/persistence/storage/storage-plugin-cache/src/cached-storage/cached-storage.delete.md create mode 100644 docs/persistence/storage/storage-plugin-cache/src/cached-storage/cached-storage.get.md create mode 100644 docs/persistence/storage/storage-plugin-cache/src/cached-storage/cached-storage.md create mode 100644 docs/persistence/storage/storage-plugin-cache/src/cached-storage/cached-storage.passthrough.md create mode 100644 docs/persistence/storage/storage-plugin-cache/src/cached-storage/cached-storage.signal.md create mode 100644 docs/persistence/storage/storage-plugin-cache/src/cached-storage/cached-storage.write.md create mode 100644 docs/persistence/storage/storage-plugin-cache/src/error-codes/error-codes.md create mode 100644 docs/persistence/storage/storage-plugin-cache/src/factory/factory.md create mode 100644 docs/persistence/storage/storage-plugin-cache/src/otel/otel.md create mode 100644 docs/persistence/storage/storage-s3/README.md create mode 100644 docs/persistence/storage/storage-s3/src/registry/registry/registry.md create mode 100644 docs/persistence/storage/storage-s3/src/s3/s3.md create mode 100644 docs/persistence/storage/storage-s3/src/types/s3.types.md create mode 100644 docs/persistence/storage/storage-s3/src/utils/credential-validator.md create mode 100644 docs/persistence/storage/storage-uri-plugin-bundle/README.md create mode 100644 docs/persistence/storage/storage-uri-plugin-bundle/src/abort/abort.md create mode 100644 docs/persistence/storage/storage-uri-plugin-bundle/src/cache/cache.md create mode 100644 docs/persistence/storage/storage-uri-plugin-bundle/src/error-codes/error-codes.md create mode 100644 docs/persistence/storage/storage-uri-plugin-bundle/src/factory/factory.md create mode 100644 docs/persistence/storage/storage-uri-plugin-bundle/src/node-fetch/node-fetch.md create mode 100644 docs/persistence/storage/storage-uri-plugin-bundle/src/otel/otel.md create mode 100644 docs/persistence/storage/storage-uri-plugin-bundle/src/parse/parse.md create mode 100644 docs/persistence/storage/storage-uri-plugin-bundle/src/range/range.md create mode 100644 docs/persistence/storage/storage-uri-plugin-bundle/src/storage-shim/storage-shim.fetch.md create mode 100644 docs/persistence/storage/storage-uri-plugin-bundle/src/storage-shim/storage-shim.head.md create mode 100644 docs/persistence/storage/storage-uri-plugin-bundle/src/storage-shim/storage-shim.md create mode 100644 docs/persistence/storage/storage-uri-plugin-bundle/src/storage-shim/storage-shim.range.md create mode 100644 docs/persistence/storage/storage-uri-plugin-bundle/src/streaming/streaming.md create mode 100644 docs/persistence/storage/storage-uri-plugin-bundle/src/types/plugin-options.schemas.md create mode 100644 docs/persistence/storage/storage-uri-plugin-bundle/src/types/plugin-options.types.md create mode 100644 docs/persistence/storage/storage-uri-plugin-fallback/README.md create mode 100644 docs/persistence/storage/storage-uri-plugin-fallback/src/classify/classify.md create mode 100644 docs/persistence/storage/storage-uri-plugin-fallback/src/conformance/fallback-conformance.md create mode 100644 docs/persistence/storage/storage-uri-plugin-fallback/src/error-codes/error-codes.md create mode 100644 docs/persistence/storage/storage-uri-plugin-fallback/src/observability/events.md create mode 100644 docs/persistence/storage/storage-uri-plugin-fallback/src/observability/otel.md create mode 100644 docs/persistence/storage/storage-uri-plugin-fallback/src/ops/delete.md create mode 100644 docs/persistence/storage/storage-uri-plugin-fallback/src/ops/list.md create mode 100644 docs/persistence/storage/storage-uri-plugin-fallback/src/ops/metadata.md create mode 100644 docs/persistence/storage/storage-uri-plugin-fallback/src/ops/read.md create mode 100644 docs/persistence/storage/storage-uri-plugin-fallback/src/ops/write.md create mode 100644 docs/persistence/storage/storage-uri-plugin-fallback/src/parse-uri/abort-any.md create mode 100644 docs/persistence/storage/storage-uri-plugin-fallback/src/parse-uri/parse-fallback-uri.md create mode 100644 docs/persistence/storage/storage-uri-plugin-fallback/src/plugin/plugin.md create mode 100644 docs/persistence/storage/storage-uri-plugin-fallback/src/recursion/depth-context.md create mode 100644 docs/persistence/storage/storage-uri-plugin-fallback/src/types/candidate.types.md create mode 100644 docs/persistence/storage/storage-uri-plugin-fallback/src/types/policy.types.md create mode 100644 docs/persistence/storage/storage-uri-plugin-fallback/src/walk/parallel.md create mode 100644 docs/persistence/storage/storage-uri-plugin-fallback/src/walk/sequential.md create mode 100644 docs/persistence/storage/storage-uri/README.md create mode 100644 docs/persistence/storage/storage-uri/src/conformance/conformance.md create mode 100644 docs/persistence/storage/storage-uri/src/error-codes/error-codes.md create mode 100644 docs/persistence/storage/storage-uri/src/otel/otel.md create mode 100644 docs/persistence/storage/storage-uri/src/parse-uri/parse-uri.md create mode 100644 docs/persistence/storage/storage-uri/src/resolver/resolver.list.md create mode 100644 docs/persistence/storage/storage-uri/src/resolver/resolver.md create mode 100644 docs/persistence/storage/storage-uri/src/resolver/resolver.streams.md create mode 100644 docs/persistence/storage/storage-uri/src/resolver/resolver.writes.md create mode 100644 docs/persistence/storage/storage-uri/src/types/plugin.types.md create mode 100644 docs/persistence/storage/storage-uri/src/types/resolver.types.md create mode 100644 docs/persistence/storage/storage/README.md create mode 100644 docs/persistence/storage/storage/src/abstract/abstract.md create mode 100644 docs/persistence/storage/storage/src/abstract/namespace.md create mode 100644 docs/persistence/storage/storage/src/errors/errors.md create mode 100644 docs/persistence/storage/storage/src/factory/factory.md create mode 100644 docs/persistence/storage/storage/src/memory/memory.md create mode 100644 docs/persistence/storage/storage/src/types/schemas.md create mode 100644 docs/persistence/storage/storage/src/types/types.md create mode 100644 docs/security-stack/README.md create mode 100644 docs/security-stack/_intro.md create mode 100644 docs/security-stack/crypto/README.md create mode 100644 docs/security-stack/crypto/_intro.md create mode 100644 docs/security-stack/crypto/crypto-bin/README.md create mode 100644 docs/security-stack/crypto/crypto-bin/src/bin/hash-password.md create mode 100644 docs/security-stack/crypto/crypto-bin/src/hash-password/hash-password.md create mode 100644 docs/security-stack/crypto/crypto-browser/CHANGELOG.md create mode 100644 docs/security-stack/crypto/crypto-browser/README.md create mode 100644 docs/security-stack/crypto/crypto-browser/src/aes-kw/aes-kw.md create mode 100644 docs/security-stack/crypto/crypto-browser/src/availability/availability.md create mode 100644 docs/security-stack/crypto/crypto-browser/src/ecdh-p384/ecdh-p384.md create mode 100644 docs/security-stack/crypto/crypto-browser/src/ecdsa-p384/ecdsa-p384.md create mode 100644 docs/security-stack/crypto/crypto-browser/src/engines/webcrypto-aead-engine/webcrypto-aead-engine.md create mode 100644 docs/security-stack/crypto/crypto-browser/src/engines/webcrypto-agree-engine/webcrypto-agree-engine.md create mode 100644 docs/security-stack/crypto/crypto-browser/src/engines/webcrypto-sign-engine/webcrypto-sign-engine.md create mode 100644 docs/security-stack/crypto/crypto-browser/src/errors/browser-crypto-error/browser-crypto-error.md create mode 100644 docs/security-stack/crypto/crypto-browser/src/errors/codes/codes.md create mode 100644 docs/security-stack/crypto/crypto-browser/src/non-extractable-key/non-extractable-key.md create mode 100644 docs/security-stack/crypto/crypto-browser/src/rsa/rsa.md create mode 100644 docs/security-stack/crypto/crypto-cipher/CHANGELOG.md create mode 100644 docs/security-stack/crypto/crypto-cipher/README.md create mode 100644 docs/security-stack/crypto/crypto-cipher/src/errors/codes/codes.md create mode 100644 docs/security-stack/crypto/crypto-cipher/src/errors/crypto-cipher-error/crypto-cipher-error.md create mode 100644 docs/security-stack/crypto/crypto-cipher/src/primitives/aes-256-gcm/aes-256-gcm.md create mode 100644 docs/security-stack/crypto/crypto-cipher/src/primitives/aes-256-gcm/aes-256-gcm.select/aes-256-gcm.select.md create mode 100644 docs/security-stack/crypto/crypto-cipher/src/primitives/aes-256-gcm/impl/aes-256-gcm.native/aes-256-gcm.native.md create mode 100644 docs/security-stack/crypto/crypto-cipher/src/primitives/aes-256-gcm/impl/aes-256-gcm.noble/aes-256-gcm.noble.md create mode 100644 docs/security-stack/crypto/crypto-cipher/src/primitives/chacha20-poly1305/chacha20-poly1305.md create mode 100644 docs/security-stack/crypto/crypto-cipher/src/primitives/chacha20-poly1305/chacha20-poly1305.select/chacha20-poly1305.select.md create mode 100644 docs/security-stack/crypto/crypto-cipher/src/primitives/chacha20-poly1305/impl/chacha20-poly1305.native/chacha20-poly1305.native.md create mode 100644 docs/security-stack/crypto/crypto-cipher/src/primitives/chacha20-poly1305/impl/chacha20-poly1305.noble/chacha20-poly1305.noble.md create mode 100644 docs/security-stack/crypto/crypto-cipher/src/primitives/xchacha20-poly1305/impl/xchacha20-poly1305.native/xchacha20-poly1305.native.md create mode 100644 docs/security-stack/crypto/crypto-cipher/src/primitives/xchacha20-poly1305/impl/xchacha20-poly1305.noble/xchacha20-poly1305.noble.md create mode 100644 docs/security-stack/crypto/crypto-cipher/src/primitives/xchacha20-poly1305/xchacha20-poly1305.md create mode 100644 docs/security-stack/crypto/crypto-cipher/src/primitives/xchacha20-poly1305/xchacha20-poly1305.select/xchacha20-poly1305.select.md create mode 100644 docs/security-stack/crypto/crypto-cipher/src/streaming/streaming-aead-aes-gcm/streaming-aead-aes-gcm.md create mode 100644 docs/security-stack/crypto/crypto-cipher/src/streaming/streaming-aead-xchacha20/streaming-aead-xchacha20.md create mode 100644 docs/security-stack/crypto/crypto-cipher/src/streaming/streaming-aead/streaming-aead.md create mode 100644 docs/security-stack/crypto/crypto-cli/README.md create mode 100644 docs/security-stack/crypto/crypto-core/CHANGELOG.md create mode 100644 docs/security-stack/crypto/crypto-core/README.md create mode 100644 docs/security-stack/crypto/crypto-core/src/aead/aead.md create mode 100644 docs/security-stack/crypto/crypto-core/src/aead/noble-aead-engine/noble-aead-engine.md create mode 100644 docs/security-stack/crypto/crypto-core/src/agree/noble-agree-engine/noble-agree-engine.md create mode 100644 docs/security-stack/crypto/crypto-core/src/agree/x25519/x25519.md create mode 100644 docs/security-stack/crypto/crypto-core/src/auth-box/auth-box.md create mode 100644 docs/security-stack/crypto/crypto-core/src/auth-box/noble-auth-box-engine/noble-auth-box-engine.md create mode 100644 docs/security-stack/crypto/crypto-core/src/errors/codes/codes.md create mode 100644 docs/security-stack/crypto/crypto-core/src/errors/crypto-error/crypto-error.md create mode 100644 docs/security-stack/crypto/crypto-core/src/primitives/constant-time-equal/constant-time-equal.md create mode 100644 docs/security-stack/crypto/crypto-core/src/primitives/random-bytes/random-bytes.md create mode 100644 docs/security-stack/crypto/crypto-core/src/primitives/zeroize/zeroize.md create mode 100644 docs/security-stack/crypto/crypto-core/src/sealed-box/noble-sealed-box-engine/noble-sealed-box-engine.md create mode 100644 docs/security-stack/crypto/crypto-core/src/sealed-box/sealed-box.md create mode 100644 docs/security-stack/crypto/crypto-core/src/sign/ecdsa-p256/ecdsa-p256.md create mode 100644 docs/security-stack/crypto/crypto-core/src/sign/ed25519/ed25519.md create mode 100644 docs/security-stack/crypto/crypto-core/src/sign/noble-sign-engine/noble-sign-engine.md create mode 100644 docs/security-stack/crypto/crypto-curve/CHANGELOG.md create mode 100644 docs/security-stack/crypto/crypto-curve/README.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/errors/codes/codes.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/errors/crypto-curve-error/crypto-curve-error.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/ed25519/ed25519.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/ed25519/ed25519.select/ed25519.select.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/ed25519/impl/ed25519.native/ed25519.native.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/ed25519/impl/ed25519.noble/ed25519.noble.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/p256/impl/p256.native/p256.native.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/p256/impl/p256.noble/p256.noble.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/p256/p256.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/p256/p256.select/p256.select.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/p384/impl/p384.native/p384.native.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/p384/impl/p384.noble/p384.noble.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/p384/p384.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/p384/p384.select/p384.select.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/p521/impl/p521.native/p521.native.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/p521/impl/p521.noble/p521.noble.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/p521/p521.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/p521/p521.select/p521.select.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/secp256k1/impl/secp256k1.native/secp256k1.native.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/secp256k1/impl/secp256k1.noble/secp256k1.noble.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/secp256k1/secp256k1.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/secp256k1/secp256k1.select/secp256k1.select.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/x25519/impl/x25519.native/x25519.native.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/x25519/impl/x25519.noble/x25519.noble.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/x25519/x25519.md create mode 100644 docs/security-stack/crypto/crypto-curve/src/primitives/x25519/x25519.select/x25519.select.md create mode 100644 docs/security-stack/crypto/crypto-hash/CHANGELOG.md create mode 100644 docs/security-stack/crypto/crypto-hash/README.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/encoding/base64/base64.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/encoding/hex/hex.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/errors/codes/codes.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/errors/hash-error/hash-error.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/hash/sha2/sha2.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/kdf/argon2id/argon2id.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/kdf/hkdf/hkdf.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/kdf/pbkdf2/pbkdf2.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/mac/argon2id-password/argon2id-password.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/mac/blake2b-password/blake2b-password.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/mac/hmac/hmac.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/argon2id/argon2id.select/argon2id.select.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/argon2id/impl/argon2id.native/argon2id.native.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/argon2id/impl/argon2id.noble/argon2id.noble.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/blake2b/blake2b.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/blake2b/impl/blake2b.noble/blake2b.noble.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/hkdf/hkdf.select/hkdf.select.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/hkdf/impl/hkdf.native/hkdf.native.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/hkdf/impl/hkdf.noble/hkdf.noble.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/hmac/hmac.select/hmac.select.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/hmac/impl/hmac.native/hmac.native.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/hmac/impl/hmac.noble/hmac.noble.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/pbkdf2/impl/pbkdf2.native/pbkdf2.native.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/pbkdf2/impl/pbkdf2.noble/pbkdf2.noble.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/pbkdf2/pbkdf2.select/pbkdf2.select.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/scrypt/impl/scrypt.noble/scrypt.noble.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/scrypt/scrypt.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/sha256/impl/sha256.native/sha256.native.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/sha256/impl/sha256.noble/sha256.noble.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/sha256/sha256.select/sha256.select.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/sha384/impl/sha384.native/sha384.native.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/sha384/impl/sha384.noble/sha384.noble.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/sha384/sha384.select/sha384.select.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/sha512/impl/sha512.native/sha512.native.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/sha512/impl/sha512.noble/sha512.noble.md create mode 100644 docs/security-stack/crypto/crypto-hash/src/primitives/sha512/sha512.select/sha512.select.md create mode 100644 docs/security-stack/crypto/crypto-keys/README.md create mode 100644 docs/security-stack/crypto/crypto-keys/src/codecs/cbor/cbor.md create mode 100644 docs/security-stack/crypto/crypto-keys/src/codecs/recursive-ed25519/recursive-ed25519.md create mode 100644 docs/security-stack/crypto/crypto-keys/src/codecs/tlv/tlv.md create mode 100644 docs/security-stack/crypto/crypto-keys/src/error-codes/error-codes.md create mode 100644 docs/security-stack/crypto/crypto-keys/src/factory/factory.md create mode 100644 docs/security-stack/crypto/crypto-keys/src/hashers/domain/domain.md create mode 100644 docs/security-stack/crypto/crypto-keys/src/hashers/merkle/merkle.md create mode 100644 docs/security-stack/crypto/crypto-keys/src/hashers/raw/raw.md create mode 100644 docs/security-stack/crypto/crypto-keys/src/signer/signer.md create mode 100644 docs/security-stack/crypto/crypto-keys/src/types/chain-level.md create mode 100644 docs/security-stack/crypto/crypto-keys/src/types/codec.md create mode 100644 docs/security-stack/crypto/crypto-keys/src/types/hasher.md create mode 100644 docs/security-stack/crypto/crypto-rsa/README.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/__benchmarks__/blinded_vs_unblinded_2048.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/__fixtures__/rsa-2048-key.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/__fixtures__/test-keys.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/asn1/reader.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/asn1/writer.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/blinding/blinding.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/decrypt/oaep.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/decrypt/pkcs1v15.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/encoding/emsa-pkcs1-v1_5.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/encoding/emsa-pss-encode.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/encoding/emsa-pss-verify.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/encoding/mgf1.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/encrypt/default-rng.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/encrypt/oaep.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/encrypt/pkcs1v15.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/engine/noble.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/engine/select.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/engine/subtle.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/errors/errors.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/fingerprint/format.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/fingerprint/spki.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/handle/registry.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/handle/software.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/jwk/thumbprint-uri.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/jwk/thumbprint.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/keygen/exponent.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/keygen/generate.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/keygen/miller-rabin.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/keygen/multi-prime.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/keys/jwk-policy.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/keys/oid.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/keys/parse-jwk.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/keys/parse-pkcs1-private.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/keys/parse-pkcs1-public.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/keys/parse-pkcs8.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/keys/parse-spki.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/keys/parse.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/keys/serialize-jwk.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/keys/serialize-pkcs1-private.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/keys/serialize-pkcs1-public.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/keys/serialize-pkcs8.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/keys/serialize-spki.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/keys/serialize.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/math/crt.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/math/i2osp.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/math/modpow.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/math/os2ip.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/observability/metrics.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/observability/timing.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/pem/labels.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/pem/parse-private.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/pem/parse-public.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/pem/pem-codec.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/pem/serialize-private.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/pem/serialize-public.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/policy/modulus.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/profile/profile.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/schemas/schemas.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/sign/pkcs1v15.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/sign/pss.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/verify/pkcs1v15.md create mode 100644 docs/security-stack/crypto/crypto-rsa/src/verify/pss.md create mode 100644 docs/security-stack/crypto/crypto-sodium/CHANGELOG.md create mode 100644 docs/security-stack/crypto/crypto-sodium/README.md create mode 100644 docs/security-stack/crypto/crypto-sodium/src/engines/sodium-aead-engine/sodium-aead-engine.md create mode 100644 docs/security-stack/crypto/crypto-sodium/src/engines/sodium-agree-engine/sodium-agree-engine.md create mode 100644 docs/security-stack/crypto/crypto-sodium/src/engines/sodium-auth-box-engine/sodium-auth-box-engine.md create mode 100644 docs/security-stack/crypto/crypto-sodium/src/engines/sodium-sealed-box-engine/sodium-sealed-box-engine.md create mode 100644 docs/security-stack/crypto/crypto-sodium/src/engines/sodium-sign-engine/sodium-sign-engine.md create mode 100644 docs/security-stack/crypto/crypto-sodium/src/errors/codes/codes.md create mode 100644 docs/security-stack/crypto/crypto-sodium/src/errors/sodium-error/sodium-error.md create mode 100644 docs/security-stack/crypto/crypto-sodium/src/init/init.md create mode 100644 docs/security-stack/crypto/crypto-sodium/src/primitives/crypto-auth/crypto-auth.md create mode 100644 docs/security-stack/crypto/crypto-sodium/src/primitives/crypto-kdf/crypto-kdf.md create mode 100644 docs/security-stack/crypto/crypto-sodium/src/primitives/crypto-pwhash/crypto-pwhash.md create mode 100644 docs/security-stack/crypto/crypto-sodium/src/primitives/ristretto255/ristretto255.md create mode 100644 docs/security-stack/crypto/crypto-utils/CHANGELOG.md create mode 100644 docs/security-stack/crypto/crypto-utils/README.md create mode 100644 docs/security-stack/crypto/crypto-utils/src/bytes/concat-bytes/concat-bytes.md create mode 100644 docs/security-stack/crypto/crypto-utils/src/bytes/i2osp/i2osp.md create mode 100644 docs/security-stack/crypto/crypto-utils/src/bytes/os2ip/os2ip.md create mode 100644 docs/security-stack/crypto/crypto-utils/src/bytes/xor/xor.md create mode 100644 docs/security-stack/crypto/crypto-utils/src/constant-time/constant-time-equal/constant-time-equal.md create mode 100644 docs/security-stack/crypto/crypto-utils/src/encoding/base58/base58.md create mode 100644 docs/security-stack/crypto/crypto-utils/src/encoding/base64/base64.md create mode 100644 docs/security-stack/crypto/crypto-utils/src/encoding/hex/hex.md create mode 100644 docs/security-stack/crypto/crypto-utils/src/errors/codes/codes.md create mode 100644 docs/security-stack/crypto/crypto-utils/src/errors/crypto-utils-error/crypto-utils-error.md create mode 100644 docs/security-stack/crypto/crypto-utils/src/errors/primitive-not-implemented/primitive-not-implemented.md create mode 100644 docs/security-stack/crypto/crypto-utils/src/merkle/merkle-proof/merkle-proof.md create mode 100644 docs/security-stack/crypto/crypto-utils/src/merkle/merkle-root/merkle-root.md create mode 100644 docs/security-stack/crypto/crypto-utils/src/primitive-id/primitive-id.md create mode 100644 docs/security-stack/crypto/crypto-utils/src/random/random-bytes/random-bytes.md create mode 100644 docs/security-stack/crypto/crypto-utils/src/testing/diff-fuzz/diff-fuzz.md create mode 100644 docs/security-stack/crypto/crypto-utils/src/testing/dudect/dudect.md create mode 100644 docs/security-stack/crypto/crypto-utils/src/testing/run-vectors/run-vectors.md create mode 100644 docs/security-stack/crypto/crypto-utils/src/zeroize/zeroize.md create mode 100644 docs/security-stack/crypto/crypto-vault/README.md create mode 100644 docs/security-stack/crypto/crypto-vault/src/argon2id/argon2id.md create mode 100644 docs/security-stack/crypto/crypto-vault/src/bip39/bip39.md create mode 100644 docs/security-stack/crypto/crypto-vault/src/errors/codes.md create mode 100644 docs/security-stack/crypto/crypto-vault/src/errors/crypto-vault-error.md create mode 100644 docs/security-stack/crypto/crypto-vault/src/handle/opaque-handle.md create mode 100644 docs/security-stack/crypto/crypto-vault/src/hd-key/hd-key.md create mode 100644 docs/security-stack/crypto/crypto-vault/src/key-hierarchy/key-hierarchy.md create mode 100644 docs/security-stack/crypto/crypto-vault/src/orchestration/internals.md create mode 100644 docs/security-stack/crypto/crypto-vault/src/orchestration/orchestration.md create mode 100644 docs/security-stack/crypto/crypto-vault/src/otel/instruments.md create mode 100644 docs/security-stack/crypto/crypto-vault/src/schemas/schemas.md create mode 100644 docs/security-stack/crypto/crypto-vault/src/secure/secure-buffer.md create mode 100644 docs/security-stack/crypto/crypto-vault/src/srp/srp-client.md create mode 100644 docs/security-stack/crypto/crypto-vault/src/srp/srp-group.md create mode 100644 docs/security-stack/crypto/crypto-vault/src/twoskd/twoskd.md create mode 100644 docs/security-stack/crypto/crypto-vault/src/types/types.md create mode 100644 docs/security-stack/crypto/crypto/CHANGELOG.md create mode 100644 docs/security-stack/crypto/crypto/README.md create mode 100644 docs/security-stack/crypto/crypto/src/aead/streaming/streaming-aead.md create mode 100644 docs/security-stack/crypto/crypto/src/aead/streaming/web-streams.md create mode 100644 docs/security-stack/crypto/crypto/src/authority/authority.md create mode 100644 docs/security-stack/crypto/crypto/src/bundles/chain-bundle/chain-bundle.md create mode 100644 docs/security-stack/crypto/crypto/src/bundles/public-bundle/public-bundle.md create mode 100644 docs/security-stack/crypto/crypto/src/derivation/coordinate/coordinate.md create mode 100644 docs/security-stack/crypto/crypto/src/derivation/layouts/layouts.md create mode 100644 docs/security-stack/crypto/crypto/src/derivation/purposes/purposes.md create mode 100644 docs/security-stack/crypto/crypto/src/domain-tags/domain-tags.md create mode 100644 docs/security-stack/crypto/crypto/src/errors/codes/codes.md create mode 100644 docs/security-stack/crypto/crypto/src/errors/crypto-error/crypto-error.md create mode 100644 docs/security-stack/crypto/crypto/src/errors/keys-errors/codes/codes.md create mode 100644 docs/security-stack/crypto/crypto/src/errors/keys-errors/crypto-keys-error/crypto-keys-error.md create mode 100644 docs/security-stack/crypto/crypto/src/errors/vault-errors/codes/codes.md create mode 100644 docs/security-stack/crypto/crypto/src/errors/vault-errors/crypto-vault-error/crypto-vault-error.md create mode 100644 docs/security-stack/crypto/crypto/src/keychain/algorithms/algorithms.md create mode 100644 docs/security-stack/crypto/crypto/src/keychain/key-slot/key-slot.md create mode 100644 docs/security-stack/crypto/crypto/src/keychain/keychain.md create mode 100644 docs/security-stack/crypto/crypto/src/keychain/keypair/generate/generate.md create mode 100644 docs/security-stack/crypto/crypto/src/keychain/keypair/validate/validate.md create mode 100644 docs/security-stack/crypto/crypto/src/keychain/storage/adapters/memory/memory.md create mode 100644 docs/security-stack/crypto/crypto/src/keychain/storage/adapters/serialized/serialized.md create mode 100644 docs/security-stack/crypto/crypto/src/keychain/validity/validity.md create mode 100644 docs/security-stack/crypto/crypto/src/password/derive-key-from-password.md create mode 100644 docs/security-stack/crypto/crypto/src/password/encrypt-with-password.md create mode 100644 docs/security-stack/crypto/crypto/src/trust-anchors/trust-anchor.md create mode 100644 docs/security-stack/crypto/crypto/src/vault/mnemonic/mnemonic.md create mode 100644 docs/security-stack/security/README.md create mode 100644 docs/security-stack/security/_intro.md create mode 100644 docs/security-stack/security/hibp/README.md create mode 100644 docs/security-stack/security/hibp/src/breach/breach-client.md create mode 100644 docs/security-stack/security/hibp/src/breach/rate-limit-gate.md create mode 100644 docs/security-stack/security/hibp/src/breach/retry-after.md create mode 100644 docs/security-stack/security/hibp/src/cache/cache.md create mode 100644 docs/security-stack/security/hibp/src/cache/lru.md create mode 100644 docs/security-stack/security/hibp/src/cache/null.md create mode 100644 docs/security-stack/security/hibp/src/client/client.md create mode 100644 docs/security-stack/security/hibp/src/client/options.schema.md create mode 100644 docs/security-stack/security/hibp/src/error-codes.md create mode 100644 docs/security-stack/security/hibp/src/errors/codes.md create mode 100644 docs/security-stack/security/hibp/src/errors/hibp-error.md create mode 100644 docs/security-stack/security/hibp/src/observability/metrics.md create mode 100644 docs/security-stack/security/hibp/src/privacy/assert-no-leak.md create mode 100644 docs/security-stack/security/hibp/src/range/constant-time-compare.md create mode 100644 docs/security-stack/security/hibp/src/range/differential-privacy.md create mode 100644 docs/security-stack/security/hibp/src/range/range-mode.md create mode 100644 docs/security-stack/security/hibp/src/range/range-stream-parse.md create mode 100644 docs/security-stack/security/hibp/src/range/range-strict-frame.md create mode 100644 docs/security-stack/security/hibp/src/range/range.md create mode 100644 docs/security-stack/security/hibp/src/schemas/breach.schema.md create mode 100644 docs/security-stack/security/hibp/src/schemas/paste.schema.md create mode 100644 docs/security-stack/security/hibp/src/schemas/pwned-result.schema.md create mode 100644 docs/security-stack/security/jws/README.md create mode 100644 docs/security-stack/security/jws/src/algorithms/builtin.md create mode 100644 docs/security-stack/security/jws/src/algorithms/ecdsa.md create mode 100644 docs/security-stack/security/jws/src/algorithms/eddsa.md create mode 100644 docs/security-stack/security/jws/src/algorithms/hmac.md create mode 100644 docs/security-stack/security/jws/src/algorithms/none.md create mode 100644 docs/security-stack/security/jws/src/algorithms/registry.md create mode 100644 docs/security-stack/security/jws/src/algorithms/rsa-pss.md create mode 100644 docs/security-stack/security/jws/src/algorithms/rsa.md create mode 100644 docs/security-stack/security/jws/src/base64url/base64url.md create mode 100644 docs/security-stack/security/jws/src/detached/detached.md create mode 100644 docs/security-stack/security/jws/src/errors/error-codes.md create mode 100644 docs/security-stack/security/jws/src/header/b64.md create mode 100644 docs/security-stack/security/jws/src/header/crit.md create mode 100644 docs/security-stack/security/jws/src/header/header.md create mode 100644 docs/security-stack/security/jws/src/keys/jwk.md create mode 100644 docs/security-stack/security/jws/src/keys/resolver.md create mode 100644 docs/security-stack/security/jws/src/keys/x5c.md create mode 100644 docs/security-stack/security/jws/src/observability/metrics.md create mode 100644 docs/security-stack/security/jws/src/schemas/schemas.md create mode 100644 docs/security-stack/security/jws/src/serialization/compact/compact.md create mode 100644 docs/security-stack/security/jws/src/serialization/flat/flat.md create mode 100644 docs/security-stack/security/jws/src/serialization/general/general.md create mode 100644 docs/security-stack/security/jws/src/sign/sign-pipeline.md create mode 100644 docs/security-stack/security/jws/src/verify/verify-pipeline.md create mode 100644 docs/security-stack/security/license/README.md create mode 100644 docs/security-stack/security/license/src/codec/base32/base32.md create mode 100644 docs/security-stack/security/license/src/codec/bitpack/bitpack.md create mode 100644 docs/security-stack/security/license/src/codec/obfuscation/obfuscation.md create mode 100644 docs/security-stack/security/license/src/codec/payload/payload.md create mode 100644 docs/security-stack/security/license/src/constants/constants.md create mode 100644 docs/security-stack/security/license/src/error-codes.md create mode 100644 docs/security-stack/security/license/src/flags/flags.md create mode 100644 docs/security-stack/security/license/src/generate/generate.md create mode 100644 docs/security-stack/security/license/src/manager/manager.md create mode 100644 docs/security-stack/security/license/src/otel/instruments.md create mode 100644 docs/security-stack/security/license/src/revocation/revocation-store/revocation-store.md create mode 100644 docs/security-stack/security/license/src/schemas/schemas.md create mode 100644 docs/security-stack/security/license/src/time/time.md create mode 100644 docs/security-stack/security/license/src/types/license.md create mode 100644 docs/security-stack/security/license/src/validate/validate.md create mode 100644 docs/security-stack/security/otp/README.md create mode 100644 docs/security-stack/security/otp/openspec/specs/otp/spec.md create mode 100644 docs/security-stack/security/otp/src/base32/base32.md create mode 100644 docs/security-stack/security/otp/src/drift/detect.md create mode 100644 docs/security-stack/security/otp/src/errors/codes.md create mode 100644 docs/security-stack/security/otp/src/errors/zod-map.md create mode 100644 docs/security-stack/security/otp/src/hotp/encode-counter.md create mode 100644 docs/security-stack/security/otp/src/hotp/hmac.md create mode 100644 docs/security-stack/security/otp/src/hotp/hotp.md create mode 100644 docs/security-stack/security/otp/src/hotp/hotp.schema.md create mode 100644 docs/security-stack/security/otp/src/observability/metrics.md create mode 100644 docs/security-stack/security/otp/src/ocra/encode-challenge.md create mode 100644 docs/security-stack/security/otp/src/ocra/mutual-auth.md create mode 100644 docs/security-stack/security/otp/src/ocra/ocra.md create mode 100644 docs/security-stack/security/otp/src/ocra/ocra.schema.md create mode 100644 docs/security-stack/security/otp/src/ocra/suite.md create mode 100644 docs/security-stack/security/otp/src/ocra/verify-ocra.md create mode 100644 docs/security-stack/security/otp/src/recovery/generate.md create mode 100644 docs/security-stack/security/otp/src/recovery/hash.md create mode 100644 docs/security-stack/security/otp/src/recovery/verify.md create mode 100644 docs/security-stack/security/otp/src/totp/totp.md create mode 100644 docs/security-stack/security/otp/src/totp/totp.schema.md create mode 100644 docs/security-stack/security/otp/src/totp/verify-many.md create mode 100644 docs/security-stack/security/otp/src/totp/verify.md create mode 100644 docs/security-stack/security/otp/src/uri/format-uri.md create mode 100644 docs/security-stack/security/otp/src/uri/parse-uri.md create mode 100644 docs/security-stack/security/otp/src/uri/uri.schema.md create mode 100644 docs/security-stack/security/password-formats/README.md create mode 100644 docs/security-stack/security/password-formats/src/core/detector/format-detector.md create mode 100644 docs/security-stack/security/password-formats/src/core/parse/parse.md create mode 100644 docs/security-stack/security/password-formats/src/core/validator/validate.md create mode 100644 docs/security-stack/security/password-formats/src/errors/password-formats-error.md create mode 100644 docs/security-stack/security/password-formats/src/export/csv-export.md create mode 100644 docs/security-stack/security/password-formats/src/parsers/apple-passwords/apple-passwords.md create mode 100644 docs/security-stack/security/password-formats/src/parsers/bitwarden/bitwarden.md create mode 100644 docs/security-stack/security/password-formats/src/parsers/chrome/chrome.md create mode 100644 docs/security-stack/security/password-formats/src/parsers/keepass/keepass.md create mode 100644 docs/security-stack/security/password-formats/src/types/password-formats.types.md create mode 100644 docs/security-stack/security/password-generator/README.md create mode 100644 docs/security-stack/security/password-generator/src/charsets/charsets.md create mode 100644 docs/security-stack/security/password-generator/src/entropy/entropy.md create mode 100644 docs/security-stack/security/password-generator/src/errors/codes.md create mode 100644 docs/security-stack/security/password-generator/src/observability/metrics.md create mode 100644 docs/security-stack/security/password-generator/src/passphrase/passphrase.md create mode 100644 docs/security-stack/security/password-generator/src/password/password.md create mode 100644 docs/security-stack/security/password-generator/src/password/pronounceable.md create mode 100644 docs/security-stack/security/password-generator/src/pin/pin.md create mode 100644 docs/security-stack/security/password-generator/src/random/default-rng.md create mode 100644 docs/security-stack/security/password-generator/src/random/fisher-yates.md create mode 100644 docs/security-stack/security/password-generator/src/random/random-int.md create mode 100644 docs/security-stack/security/password-generator/src/schemas/schemas.md create mode 100644 docs/security-stack/security/password-generator/src/wordlists/eff-long.md create mode 100644 docs/security-stack/security/password-generator/src/wordlists/eff-short.md create mode 100644 docs/security-stack/security/password-generator/src/wordlists/registry.md create mode 100644 docs/security-stack/security/password-strength/README.md create mode 100644 docs/security-stack/security/password-strength/src/assess/assess-reactive.md create mode 100644 docs/security-stack/security/password-strength/src/assess/assess.md create mode 100644 docs/security-stack/security/password-strength/src/dicts/de/wikipedia.md create mode 100644 docs/security-stack/security/password-strength/src/dicts/en/english-wikipedia.md create mode 100644 docs/security-stack/security/password-strength/src/dicts/en/names.md create mode 100644 docs/security-stack/security/password-strength/src/dicts/en/passwords.md create mode 100644 docs/security-stack/security/password-strength/src/dicts/es/wikipedia.md create mode 100644 docs/security-stack/security/password-strength/src/dicts/fr/wikipedia.md create mode 100644 docs/security-stack/security/password-strength/src/dicts/load-dictionaries.md create mode 100644 docs/security-stack/security/password-strength/src/dicts/ru/wikipedia.md create mode 100644 docs/security-stack/security/password-strength/src/dicts/zh-Hans/wikipedia.md create mode 100644 docs/security-stack/security/password-strength/src/errors/error-codes.md create mode 100644 docs/security-stack/security/password-strength/src/feedback/feedback.md create mode 100644 docs/security-stack/security/password-strength/src/graphs/azerty/azerty.md create mode 100644 docs/security-stack/security/password-strength/src/graphs/dvorak/dvorak.md create mode 100644 docs/security-stack/security/password-strength/src/graphs/qwerty/qwerty.md create mode 100644 docs/security-stack/security/password-strength/src/graphs/validate-graph.md create mode 100644 docs/security-stack/security/password-strength/src/matchers/date/date.md create mode 100644 docs/security-stack/security/password-strength/src/matchers/dictionary/dictionary.md create mode 100644 docs/security-stack/security/password-strength/src/matchers/dictionary/l33t-table.md create mode 100644 docs/security-stack/security/password-strength/src/matchers/keyboard/keyboard.md create mode 100644 docs/security-stack/security/password-strength/src/matchers/regex/regex.md create mode 100644 docs/security-stack/security/password-strength/src/matchers/repeat/repeat.md create mode 100644 docs/security-stack/security/password-strength/src/matchers/sequence/sequence.md create mode 100644 docs/security-stack/security/password-strength/src/matchers/types.md create mode 100644 docs/security-stack/security/password-strength/src/observability/metrics.md create mode 100644 docs/security-stack/security/password-strength/src/schemas/schemas.md create mode 100644 docs/security-stack/security/password-strength/src/scoring/crack-times.md create mode 100644 docs/security-stack/security/password-strength/src/scoring/estimate-guesses.md create mode 100644 docs/security-stack/security/password-strength/src/scoring/most-guessable-match-sequence.md create mode 100644 docs/security-stack/security/password-strength/src/scoring/score.md create mode 100644 docs/security-stack/security/security-codes/README.md create mode 100644 docs/security-stack/security/security-codes/src/core/code-detector/code-detector.md create mode 100644 docs/security-stack/security/security-codes/src/core/code-sanitizer/code-sanitizer.md create mode 100644 docs/security-stack/security/security-codes/src/errors/security-codes-error.md create mode 100644 docs/security-stack/security/security-codes/src/patterns/aws.md create mode 100644 docs/security-stack/security/security-codes/src/patterns/credit-card.md create mode 100644 docs/security-stack/security/security-codes/src/patterns/entropy.md create mode 100644 docs/security-stack/security/security-codes/src/patterns/github.md create mode 100644 docs/security-stack/security/security-codes/src/patterns/google.md create mode 100644 docs/security-stack/security/security-codes/src/patterns/jwt.md create mode 100644 docs/security-stack/security/security-codes/src/patterns/openai.md create mode 100644 docs/security-stack/security/security-codes/src/patterns/pem.md create mode 100644 docs/security-stack/security/security-codes/src/patterns/ssh.md create mode 100644 docs/security-stack/security/security-codes/src/patterns/stripe.md create mode 100644 docs/security-stack/security/security-codes/src/types/security-codes.md create mode 100644 docs/security-stack/security/security-codes/src/types/security-codes.types.md create mode 100644 docs/security-stack/security/security-codes/src/utils/luhn.md create mode 100644 docs/security-stack/security/server-keys/README.md create mode 100644 docs/security-stack/security/server-keys/src/bin/create-root-keys-chain.md create mode 100644 docs/security-stack/security/server-keys/src/bin/create-root-keys.md create mode 100644 docs/security-stack/security/server-keys/src/bin/create-server-keys-chain.md create mode 100644 docs/security-stack/security/server-keys/src/bin/create-server-keys.md create mode 100644 docs/security-stack/security/server-keys/src/bin/get-file-stats.md create mode 100644 docs/security-stack/security/server-keys/src/bin/index.md create mode 100644 docs/security-stack/security/server-keys/src/bin/license.md create mode 100644 docs/security-stack/security/server-keys/src/bin/prepare-file.md create mode 100644 docs/security-stack/security/server-keys/src/bin/roll-server-keys-chain.md create mode 100644 docs/security-stack/security/server-keys/src/bin/roll-server-keys.md create mode 100644 docs/security-stack/security/server-keys/src/bin/serve-file.md create mode 100644 docs/security-stack/security/server-keys/src/bin/validate-file.md create mode 100644 docs/security-stack/security/server-keys/src/bin/validate-packet.md create mode 100644 docs/security-stack/security/server-keys/src/bin/verify-key-chain.md create mode 100644 docs/security-stack/security/server-keys/src/bin/view-chain-public.md create mode 100644 docs/security-stack/security/server-keys/src/bin/view-keys.md create mode 100644 docs/security-stack/security/server-keys/src/bin/view-public-key-file.md create mode 100644 docs/security-stack/security/server-keys/src/bin/view-vault.md create mode 100644 docs/security-stack/security/server-keys/src/commands/files/files.md create mode 100644 docs/security-stack/security/server-keys/src/commands/files/files.types.md create mode 100644 docs/security-stack/security/server-keys/src/commands/files/packet-io.md create mode 100644 docs/security-stack/security/server-keys/src/commands/files/serve-file.md create mode 100644 docs/security-stack/security/server-keys/src/commands/keys/keys-chain.md create mode 100644 docs/security-stack/security/server-keys/src/commands/keys/keys-io.md create mode 100644 docs/security-stack/security/server-keys/src/commands/keys/keys.md create mode 100644 docs/security-stack/security/server-keys/src/commands/keys/keys.types.md create mode 100644 docs/security-stack/security/server-keys/src/commands/license/hex.md create mode 100644 docs/security-stack/security/server-keys/src/commands/license/license.md create mode 100644 docs/security-stack/security/server-keys/src/commands/license/license.types.md create mode 100644 docs/security-stack/security/server-keys/src/error-codes/error-codes.md create mode 100644 docs/security-stack/security/server-keys/src/otel/instruments.md create mode 100644 docs/security-stack/security/server-keys/src/prompt/prompt.md create mode 100644 docs/security-stack/security/server-keys/src/run-function/run-function.md create mode 100644 docs/security-stack/security/slsa/README.md create mode 100644 docs/security-stack/security/slsa/src/assessment/assessment.md create mode 100644 docs/security-stack/security/slsa/src/attestation/dsse/dsse.md create mode 100644 docs/security-stack/security/slsa/src/errors/slsa-error.md create mode 100644 docs/security-stack/security/slsa/src/otel/slsa-otel.md create mode 100644 docs/security-stack/security/slsa/src/policy/policy.md create mode 100644 docs/security-stack/security/slsa/src/provenance/canonical-json.md create mode 100644 docs/security-stack/security/slsa/src/provenance/digest.md create mode 100644 docs/security-stack/security/slsa/src/provenance/provenance.md create mode 100644 docs/security-stack/security/slsa/src/rekor/inclusion-proof.md create mode 100644 docs/security-stack/security/slsa/src/rekor/rekor-client.md create mode 100644 docs/security-stack/security/slsa/src/sbom/sbom.md create mode 100644 docs/security-stack/security/slsa/src/schemas/parse.md create mode 100644 docs/security-stack/security/slsa/src/verification/checks.md create mode 100644 docs/security-stack/security/slsa/src/verification/verification.md create mode 100644 docs/security-stack/security/srp/README.md create mode 100644 docs/security-stack/security/srp/src/client/client-finish.md create mode 100644 docs/security-stack/security/srp/src/client/client-start.md create mode 100644 docs/security-stack/security/srp/src/client/client-verify.md create mode 100644 docs/security-stack/security/srp/src/errors/errors.md create mode 100644 docs/security-stack/security/srp/src/groups/1024/groups-1024.md create mode 100644 docs/security-stack/security/srp/src/groups/1536/groups-1536.md create mode 100644 docs/security-stack/security/srp/src/groups/3072/groups-3072.md create mode 100644 docs/security-stack/security/srp/src/groups/4096/groups-4096.md create mode 100644 docs/security-stack/security/srp/src/groups/6144/groups-6144.md create mode 100644 docs/security-stack/security/srp/src/groups/8192/groups-8192.md create mode 100644 docs/security-stack/security/srp/src/groups/groups-2048.md create mode 100644 docs/security-stack/security/srp/src/hash/hash-bridge.md create mode 100644 docs/security-stack/security/srp/src/math/k.md create mode 100644 docs/security-stack/security/srp/src/math/modpow.md create mode 100644 docs/security-stack/security/srp/src/math/pad.md create mode 100644 docs/security-stack/security/srp/src/math/proof.md create mode 100644 docs/security-stack/security/srp/src/math/rng-bytes.md create mode 100644 docs/security-stack/security/srp/src/math/u.md create mode 100644 docs/security-stack/security/srp/src/math/x.md create mode 100644 docs/security-stack/security/srp/src/observability/metrics.md create mode 100644 docs/security-stack/security/srp/src/pake/pake-provider.md create mode 100644 docs/security-stack/security/srp/src/params/params.md create mode 100644 docs/security-stack/security/srp/src/schemas/schemas.md create mode 100644 docs/security-stack/security/srp/src/server/server-finish.md create mode 100644 docs/security-stack/security/srp/src/server/server-m2.md create mode 100644 docs/security-stack/security/srp/src/server/server-start.md create mode 100644 docs/security-stack/security/srp/src/verifier/verifier.md create mode 100644 docs/security-stack/security/tpm-struct/README.md create mode 100644 docs/security-stack/security/tpm-struct/src/alg/alg.md create mode 100644 docs/security-stack/security/tpm-struct/src/attest/attest.md create mode 100644 docs/security-stack/security/tpm-struct/src/attest/serialize.md create mode 100644 docs/security-stack/security/tpm-struct/src/buffer/buffer.md create mode 100644 docs/security-stack/security/tpm-struct/src/diagnostic/diagnostic.md create mode 100644 docs/security-stack/security/tpm-struct/src/errors/error-codes.md create mode 100644 docs/security-stack/security/tpm-struct/src/extra-data/extra-data.md create mode 100644 docs/security-stack/security/tpm-struct/src/name/name.md create mode 100644 docs/security-stack/security/tpm-struct/src/observability/metrics.md create mode 100644 docs/security-stack/security/tpm-struct/src/public/object-attributes.md create mode 100644 docs/security-stack/security/tpm-struct/src/public/public.md create mode 100644 docs/security-stack/security/tpm-struct/src/public/serialize.md create mode 100644 docs/security-stack/security/tpm-struct/src/schemas/schemas.md create mode 100644 docs/security-stack/security/vault-sync/README.md create mode 100644 docs/security-stack/security/vault-sync/src/crypto-sync/crypto-sync.md create mode 100644 docs/security-stack/security/vault-sync/src/engine/engine.md create mode 100644 docs/security-stack/security/vault-sync/src/errors/codes.md create mode 100644 docs/security-stack/security/vault-sync/src/errors/vault-sync-error.md create mode 100644 docs/security-stack/security/vault-sync/src/merge/merge.md create mode 100644 docs/security-stack/security/vault-sync/src/otel/instruments.md create mode 100644 docs/security-stack/security/vault-sync/src/patch/patch.md create mode 100644 docs/security-stack/security/vault-sync/src/queue/queue.md create mode 100644 docs/security-stack/security/vault-sync/src/schemas/schemas.md create mode 100644 docs/security-stack/security/vault-sync/src/types/types.md create mode 100644 docs/security-stack/security/vault-sync/src/vector-clock/vector-clock.md create mode 100644 docs/security-stack/security/vault/README.md create mode 100644 docs/security-stack/security/vault/src/attachments/attachments.md create mode 100644 docs/security-stack/security/vault/src/container/container.md create mode 100644 docs/security-stack/security/vault/src/encryption/field-encryption.md create mode 100644 docs/security-stack/security/vault/src/errors/codes.md create mode 100644 docs/security-stack/security/vault/src/errors/vault-error.md create mode 100644 docs/security-stack/security/vault/src/items/helpers.md create mode 100644 docs/security-stack/security/vault/src/items/items.md create mode 100644 docs/security-stack/security/vault/src/items/migrations/migrations.md create mode 100644 docs/security-stack/security/vault/src/manifest/manifest.md create mode 100644 docs/security-stack/security/vault/src/otel/instruments.md create mode 100644 docs/security-stack/security/vault/src/schemas/schemas.md create mode 100644 docs/security-stack/security/vault/src/search/search.md create mode 100644 docs/security-stack/security/vault/src/shares/shares.md create mode 100644 docs/security-stack/security/vault/src/sync/sync.md create mode 100644 docs/security-stack/security/vault/src/types/adapters.md create mode 100644 docs/security-stack/security/vault/src/types/types.md create mode 100644 docs/security-stack/security/vault/src/vault/lifecycle.md create mode 100644 docs/security-stack/security/vault/src/vault/vault.md create mode 100644 docs/security-stack/security/vault/src/vault/wiring.md create mode 100644 docs/security-stack/security/x509/README.md create mode 100644 docs/security-stack/security/x509/src/__fixtures__/build-certs.md create mode 100644 docs/security-stack/security/x509/src/asn1/decoder.md create mode 100644 docs/security-stack/security/x509/src/asn1/encoder.md create mode 100644 docs/security-stack/security/x509/src/asn1/oid.md create mode 100644 docs/security-stack/security/x509/src/asn1/strings.md create mode 100644 docs/security-stack/security/x509/src/asn1/time.md create mode 100644 docs/security-stack/security/x509/src/certificate/name.md create mode 100644 docs/security-stack/security/x509/src/certificate/parse.md create mode 100644 docs/security-stack/security/x509/src/errors/error-codes.md create mode 100644 docs/security-stack/security/x509/src/extensions/authority-key-id.md create mode 100644 docs/security-stack/security/x509/src/extensions/basic-constraints.md create mode 100644 docs/security-stack/security/x509/src/extensions/crl-distribution-points.md create mode 100644 docs/security-stack/security/x509/src/extensions/extended-key-usage.md create mode 100644 docs/security-stack/security/x509/src/extensions/key-usage.md create mode 100644 docs/security-stack/security/x509/src/extensions/name-constraints.md create mode 100644 docs/security-stack/security/x509/src/extensions/registry.md create mode 100644 docs/security-stack/security/x509/src/extensions/subject-alt-name.md create mode 100644 docs/security-stack/security/x509/src/extensions/subject-key-id.md create mode 100644 docs/security-stack/security/x509/src/helpers/chains-to.md create mode 100644 docs/security-stack/security/x509/src/helpers/has-name-match.md create mode 100644 docs/security-stack/security/x509/src/helpers/is-issuer-of.md create mode 100644 docs/security-stack/security/x509/src/observability/metrics.md create mode 100644 docs/security-stack/security/x509/src/pem/pem.md create mode 100644 docs/security-stack/security/x509/src/schemas/schemas.md create mode 100644 docs/security-stack/security/x509/src/signature/alg-map.md create mode 100644 docs/security-stack/security/x509/src/signature/decode-ecdsa-sig.md create mode 100644 docs/security-stack/security/x509/src/signature/verify.md create mode 100644 docs/security-stack/security/x509/src/validate/trust-anchor.md create mode 100644 docs/security-stack/security/x509/src/validate/validate-chain.md create mode 100644 docs/testkit/README.md create mode 100644 docs/testkit/_intro.md create mode 100644 docs/testkit/testing/README.md create mode 100644 docs/testkit/testing/_intro.md create mode 100644 docs/testkit/testing/ab-testing/README.md create mode 100644 docs/testkit/testing/ab-testing/src/bucketing/bucketing.md create mode 100644 docs/testkit/testing/ab-testing/src/core/experiment-manager/experiment-manager.md create mode 100644 docs/testkit/testing/ab-testing/src/providers/provider.md create mode 100644 docs/testkit/testing/ab-testing/src/results/results.md create mode 100644 docs/testkit/testing/ab-testing/src/targeting/targeting.md create mode 100644 docs/testkit/testing/ab-testing/src/types/common.md create mode 100644 docs/testkit/testing/ab-testing/src/types/schemas.md create mode 100644 docs/testkit/testing/testing-dom/README.md create mode 100644 docs/testkit/testing/testing-dom/src/config/bun-test-config.md create mode 100644 docs/testkit/testing/testing-dom/src/config/config.md create mode 100644 docs/testkit/testing/testing-dom/src/config/detect-environment.md create mode 100644 docs/testkit/testing/testing-dom/src/config/detect-runner.md create mode 100644 docs/testkit/testing/testing-dom/src/config/vitest-config.md create mode 100644 docs/testkit/testing/testing-dom/src/errors/codes.md create mode 100644 docs/testkit/testing/testing-dom/src/errors/testing-dom-error.md create mode 100644 docs/testkit/testing/testing-dom/src/matchers/matchers.md create mode 100644 docs/testkit/testing/testing-dom/src/observability/instrumented.md create mode 100644 docs/testkit/testing/testing-dom/src/queries/queries.md create mode 100644 docs/testkit/testing/testing-dom/src/render/render-component.md create mode 100644 docs/testkit/testing/testing-dom/src/runner/bun-test.md create mode 100644 docs/testkit/testing/testing-dom/src/runner/mocks.md create mode 100644 docs/testkit/testing/testing-dom/src/runner/runner.md create mode 100644 docs/testkit/testing/testing-dom/src/runner/vitest.md create mode 100644 docs/testkit/testing/testing-dom/src/setup/polyfills.md create mode 100644 docs/testkit/testing/testing-dom/src/user/setup-user.md create mode 100644 docs/testkit/testing/testing-e2e/README.md create mode 100644 docs/testkit/testing/testing-e2e/docker/README.md create mode 100644 docs/testkit/testing/testing-e2e/src/cloakserve/build-cloakserve-url.md create mode 100644 docs/testkit/testing/testing-e2e/src/cloakserve/cloakserve-connect.md create mode 100644 docs/testkit/testing/testing-e2e/src/config/create-playwright-config.md create mode 100644 docs/testkit/testing/testing-e2e/src/console-monitor/console-monitor.md create mode 100644 docs/testkit/testing/testing-e2e/src/errors/codes.md create mode 100644 docs/testkit/testing/testing-e2e/src/errors/testing-e2e-error.md create mode 100644 docs/testkit/testing/testing-e2e/src/extension-fixture/launch-with-extension.md create mode 100644 docs/testkit/testing/testing-e2e/src/fixtures/extended-test.md create mode 100644 docs/testkit/testing/testing-e2e/src/helpers/dismiss-dialog.md create mode 100644 docs/testkit/testing/testing-e2e/src/helpers/mock-clipboard.md create mode 100644 docs/testkit/testing/testing-e2e/src/helpers/mock-geolocation.md create mode 100644 docs/testkit/testing/testing-e2e/src/helpers/screenshot-on-failure.md create mode 100644 docs/testkit/testing/testing-e2e/src/helpers/wait-for-network-idle.md create mode 100644 docs/testkit/testing/testing-e2e/src/multi-session/create-multi-session.md create mode 100644 docs/testkit/testing/testing-e2e/src/network-monitor/network-monitor.md create mode 100644 docs/testkit/testing/testing-e2e/src/observability/instrumented.md create mode 100644 docs/testkit/testing/testing-e2e/src/page-objects/page-object.md create mode 100644 docs/testkit/testing/testing-e2e/src/presets/stealth-presets.md create mode 100644 docs/testkit/testing/testing-integration-garage-s3/README.md create mode 100644 docs/testkit/testing/testing-integration-garage-s3/src/fixture/garage-s3-fixture.md create mode 100644 docs/testkit/testing/testing-integration-mailpit/README.md create mode 100644 docs/testkit/testing/testing-integration-mailpit/src/fixture/mailpit-fixture.md create mode 100644 docs/testkit/testing/testing-integration-mailpit/src/helpers/assert-mail.md create mode 100644 docs/testkit/testing/testing-integration-oauth-mock/README.md create mode 100644 docs/testkit/testing/testing-integration-oauth-mock/src/control/audit.md create mode 100644 docs/testkit/testing/testing-integration-oauth-mock/src/control/primer.md create mode 100644 docs/testkit/testing/testing-integration-oauth-mock/src/endpoints/authorize.md create mode 100644 docs/testkit/testing/testing-integration-oauth-mock/src/endpoints/openid.md create mode 100644 docs/testkit/testing/testing-integration-oauth-mock/src/endpoints/token.md create mode 100644 docs/testkit/testing/testing-integration-oauth-mock/src/endpoints/userinfo.md create mode 100644 docs/testkit/testing/testing-integration-oauth-mock/src/error-codes/error-codes.md create mode 100644 docs/testkit/testing/testing-integration-oauth-mock/src/server/server.md create mode 100644 docs/testkit/testing/testing-integration-oauth-mock/src/shapes/generic.md create mode 100644 docs/testkit/testing/testing-integration-oauth-mock/src/shapes/github.md create mode 100644 docs/testkit/testing/testing-integration-oauth-mock/src/shapes/google.md create mode 100644 docs/testkit/testing/testing-integration-postgres/README.md create mode 100644 docs/testkit/testing/testing-integration-postgres/src/fixture/postgres-fixture.md create mode 100644 docs/testkit/testing/testing-integration-redis/README.md create mode 100644 docs/testkit/testing/testing-integration-redis/src/fixture/redis-fixture.md create mode 100644 docs/testkit/testing/testing-integration-step-ca/README.md create mode 100644 docs/testkit/testing/testing-integration-step-ca/src/fixture/parse-pem-blocks.md create mode 100644 docs/testkit/testing/testing-integration-step-ca/src/fixture/step-ca-fixture.md create mode 100644 docs/testkit/testing/testing-integration-surrealdb/README.md create mode 100644 docs/testkit/testing/testing-integration-surrealdb/src/fixture/surrealdb-fixture.md create mode 100644 docs/testkit/testing/testing-integration-typesense/README.md create mode 100644 docs/testkit/testing/testing-integration-typesense/src/fixture/typesense-fixture.md create mode 100644 docs/testkit/testing/testing-integration/README.md create mode 100644 docs/testkit/testing/testing-integration/src/environment/test-environment.md create mode 100644 docs/testkit/testing/testing-integration/src/fixture/service-fixture.md create mode 100644 docs/testkit/testing/testing-integration/src/helpers/health-poller.md create mode 100644 docs/testkit/testing/testing-integration/src/helpers/skip-if-unavailable.md create mode 100644 docs/testkit/testing/testing-integration/src/internal/create-integration-setup-internal.md create mode 100644 docs/testkit/testing/testing-integration/src/internal/fixture-registry.md create mode 100644 docs/testkit/testing/testing-integration/src/internal/skip-if-unavailable-internal.md create mode 100644 docs/testkit/testing/testing-integration/src/setup/create-integration-setup.md create mode 100644 docs/testkit/testing/testing-integration/src/setup/global-setup.md create mode 100644 docs/testkit/testing/testing/README.md create mode 100644 docs/testkit/testing/testing/src/builders/request/request.md create mode 100644 docs/testkit/testing/testing/src/builders/response/response.md create mode 100644 docs/testkit/testing/testing/src/clock/fake-clock/fake-clock.md create mode 100644 docs/testkit/testing/testing/src/config/create-test-config.md create mode 100644 docs/testkit/testing/testing/src/constants/clock-constants.md create mode 100644 docs/testkit/testing/testing/src/constants/fixture-constants.md create mode 100644 docs/testkit/testing/testing/src/constants/helpers-constants.md create mode 100644 docs/testkit/testing/testing/src/constants/http-constants.md create mode 100644 docs/testkit/testing/testing/src/constants/store-constants.md create mode 100644 docs/testkit/testing/testing/src/context/context.md create mode 100644 docs/testkit/testing/testing/src/errors/codes.md create mode 100644 docs/testkit/testing/testing/src/errors/testing-error.md create mode 100644 docs/testkit/testing/testing/src/factories/factory/factory.md create mode 100644 docs/testkit/testing/testing/src/fixtures/fixture-manager/fixture-manager-internals.md create mode 100644 docs/testkit/testing/testing/src/fixtures/fixture-manager/fixture-manager.md create mode 100644 docs/testkit/testing/testing/src/helpers/test-helpers.md create mode 100644 docs/testkit/testing/testing/src/observability/with-observability.md create mode 100644 docs/testkit/testing/testing/src/runner/bun-test.md create mode 100644 docs/testkit/testing/testing/src/runner/mocks.md create mode 100644 docs/testkit/testing/testing/src/runner/runner.md create mode 100644 docs/testkit/testing/testing/src/runner/vitest.md create mode 100644 docs/testkit/testing/testing/src/storage/memory-store/memory-store.md create mode 100644 docs/testkit/testing/testing/src/types/http.md create mode 100644 docs/testkit/testing/testing/src/types/http.types.md create mode 100644 docs/threejs/README.md create mode 100644 docs/threejs/_intro.md create mode 100644 docs/threejs/r3f/README.md create mode 100644 docs/threejs/r3f/_intro.md create mode 100644 docs/threejs/r3f/r3f-networking/README.md create mode 100644 docs/threejs/r3f/r3f-networking/src/authority/server-authority/server-authority.md create mode 100644 docs/threejs/r3f/r3f-networking/src/components/network-provider/network-provider-context.md create mode 100644 docs/threejs/r3f/r3f-networking/src/components/network-provider/network-provider.md create mode 100644 docs/threejs/r3f/r3f-networking/src/components/network-stats/network-stats.md create mode 100644 docs/threejs/r3f/r3f-networking/src/components/networked-entity/apply-networked-frame.md create mode 100644 docs/threejs/r3f/r3f-networking/src/components/networked-entity/networked-entity.md create mode 100644 docs/threejs/r3f/r3f-networking/src/core/interpolation/interpolation.md create mode 100644 docs/threejs/r3f/r3f-networking/src/core/prediction/prediction.md create mode 100644 docs/threejs/r3f/r3f-networking/src/core/reconciliation-fsm/reconciliation-fsm.md create mode 100644 docs/threejs/r3f/r3f-networking/src/core/snapshot-diff/snapshot-diff.md create mode 100644 docs/threejs/r3f/r3f-networking/src/core/state-buffer/state-buffer.md create mode 100644 docs/threejs/r3f/r3f-networking/src/core/wire-codec/wire-codec.md create mode 100644 docs/threejs/r3f/r3f-networking/src/errors/errors.md create mode 100644 docs/threejs/r3f/r3f-networking/src/hooks/use-network-predict/use-network-predict.md create mode 100644 docs/threejs/r3f/r3f-networking/src/hooks/use-network-sync/use-network-sync.md create mode 100644 docs/threejs/r3f/r3f-networking/src/hooks/use-networked-entity/use-networked-entity.md create mode 100644 docs/threejs/r3f/r3f-networking/src/observability/observability.md create mode 100644 docs/threejs/r3f/r3f-networking/src/sync/entity-sync/entity-sync.md create mode 100644 docs/threejs/r3f/r3f-networking/src/sync/interest-manager/interest-manager.md create mode 100644 docs/threejs/r3f/r3f-networking/src/transport/memory-transport/memory-transport.md create mode 100644 docs/threejs/r3f/r3f-networking/src/utils/network-helpers/network-helpers.md create mode 100644 docs/ui/README.md create mode 100644 docs/ui/_intro.md create mode 100644 docs/ui/forms/README.md create mode 100644 docs/ui/forms/_intro.md create mode 100644 docs/ui/forms/form-builder/README.md create mode 100644 docs/ui/forms/form-builder/src/builder/form-builder/form-builder.md create mode 100644 docs/ui/forms/form-builder/src/conditional/conditional/conditional.md create mode 100644 docs/ui/forms/form-builder/src/conditional/dependency-graph/dependency-graph.md create mode 100644 docs/ui/forms/form-builder/src/errors/form-error/form-error.md create mode 100644 docs/ui/forms/form-builder/src/fields/field-registry/field-registry.md create mode 100644 docs/ui/forms/form-builder/src/otel/instruments/instruments.md create mode 100644 docs/ui/forms/form-builder/src/schema/schema/schema.md create mode 100644 docs/ui/forms/form-builder/src/serialise/serialise/serialise.md create mode 100644 docs/ui/forms/form-builder/src/state/form-state/form-state.md create mode 100644 docs/ui/forms/form-builder/src/state/undo-redo/undo-redo.md create mode 100644 docs/ui/forms/form-builder/src/submission/submission/submission.md create mode 100644 docs/ui/forms/form-builder/src/validation/validation/validation.md create mode 100644 docs/ui/forms/form-builder/src/validation/validators/validators.md create mode 100644 docs/ui/forms/form-builder/src/zod-schema/zod-schema/zod-schema.md create mode 100644 docs/ui/forms/react-forms/README.md create mode 100644 docs/ui/forms/react-forms/src/core/api-client-context/api-client-context.md create mode 100644 docs/ui/forms/react-forms/src/core/api-client-context/use-api-client.md create mode 100644 docs/ui/forms/react-forms/src/core/auth-context/auth-context.md create mode 100644 docs/ui/forms/react-forms/src/core/auth-context/use-auth.md create mode 100644 docs/ui/forms/react-forms/src/core/use-domain-form/use-domain-form.md create mode 100644 docs/ui/forms/react-forms/src/core/use-form-validation/use-form-validation.md create mode 100644 docs/ui/forms/react-forms/src/core/validation-engine/cross-field-rule.md create mode 100644 docs/ui/forms/react-forms/src/core/validation-engine/server-error-mapper.md create mode 100644 docs/ui/forms/react-forms/src/core/validation-engine/validation-engine.md create mode 100644 docs/ui/forms/react-forms/src/errors/error-codes.md create mode 100644 docs/ui/forms/react-forms/src/errors/react-forms-error.md create mode 100644 docs/ui/forms/react-forms/src/factory/create-domain-form/create-domain-form.md create mode 100644 docs/ui/forms/react-forms/src/factory/field-config/field-config.md create mode 100644 docs/ui/forms/react-forms/src/factory/render-field/render-field.md create mode 100644 docs/ui/forms/react-forms/src/locales/augmentation.md create mode 100644 docs/ui/forms/react-forms/src/locales/locales.md create mode 100644 docs/ui/forms/react-forms/src/locales/translation-keys.md create mode 100644 docs/ui/forms/react-forms/src/observability/react-forms-metrics.md create mode 100644 docs/ui/forms/react-forms/src/primitives/field/field.md create mode 100644 docs/ui/forms/react-forms/src/primitives/money-input/money-input.md create mode 100644 docs/ui/forms/react-forms/src/recipes/async-search/async-search.md create mode 100644 docs/ui/forms/react-forms/src/recipes/conditional/conditional.md create mode 100644 docs/ui/forms/react-forms/src/recipes/repeating-fieldset/repeating-fieldset.md create mode 100644 docs/ui/forms/react-forms/src/recipes/wizard/wizard.md create mode 100644 docs/ui/forms/react-forms/src/validation/async/async-email-unique/async-email-unique.md create mode 100644 docs/ui/forms/react-forms/src/validation/async/async-username-available/async-username-available.md create mode 100644 docs/ui/forms/react-forms/src/validation/compose/compose.md create mode 100644 docs/ui/forms/react-forms/src/validation/compose/or.md create mode 100644 docs/ui/forms/react-forms/src/validation/compose/sequence.md create mode 100644 docs/ui/forms/react-forms/src/validation/compose/shared.md create mode 100644 docs/ui/forms/react-forms/src/validation/validators/bic/bic.md create mode 100644 docs/ui/forms/react-forms/src/validation/validators/credit-card/credit-card.md create mode 100644 docs/ui/forms/react-forms/src/validation/validators/custom/custom.md create mode 100644 docs/ui/forms/react-forms/src/validation/validators/email/email.md create mode 100644 docs/ui/forms/react-forms/src/validation/validators/iban/iban.md create mode 100644 docs/ui/forms/react-forms/src/validation/validators/max-length/max-length.md create mode 100644 docs/ui/forms/react-forms/src/validation/validators/min-length/min-length.md create mode 100644 docs/ui/forms/react-forms/src/validation/validators/password-strength/password-strength.md create mode 100644 docs/ui/forms/react-forms/src/validation/validators/pattern/pattern.md create mode 100644 docs/ui/forms/react-forms/src/validation/validators/phone/phone.md create mode 100644 docs/ui/forms/react-forms/src/validation/validators/postcode/postcode.md create mode 100644 docs/ui/forms/react-forms/src/validation/validators/required/required.md create mode 100644 docs/ui/forms/react-forms/src/validation/validators/url/url.md create mode 100644 docs/ui/react/README.md create mode 100644 docs/ui/react/_intro.md create mode 100644 docs/ui/react/react-audio-fingerprint/README.md create mode 100644 docs/ui/react/react-audio-fingerprint/src/backends/local-backend/local-backend.md create mode 100644 docs/ui/react/react-audio-fingerprint/src/components/fingerprint-match-display/fingerprint-match-display.md create mode 100644 docs/ui/react/react-audio-fingerprint/src/corpus/memory-corpus/memory-corpus.md create mode 100644 docs/ui/react/react-audio-fingerprint/src/error-codes/error-codes.md create mode 100644 docs/ui/react/react-audio-fingerprint/src/fingerprint/audio-fingerprinter/audio-fingerprinter.md create mode 100644 docs/ui/react/react-audio-fingerprint/src/fingerprint/constellation/constellation.md create mode 100644 docs/ui/react/react-audio-fingerprint/src/fingerprint/fingerprint-matcher/fingerprint-matcher.md create mode 100644 docs/ui/react/react-audio-fingerprint/src/fingerprint/peak-detector/peak-detector.md create mode 100644 docs/ui/react/react-audio-fingerprint/src/hooks/use-audio-fingerprint/use-audio-fingerprint.md create mode 100644 docs/ui/react/react-audio-fingerprint/src/test-setup.md create mode 100644 docs/ui/react/react-audio-player/README.md create mode 100644 docs/ui/react/react-audio-player/src/error-codes/error-codes.md create mode 100644 docs/ui/react/react-audio-player/src/karaoke/lrc-parser/lrc-parser.md create mode 100644 docs/ui/react/react-audio-player/src/karaoke/lyrics-display/lyrics-display.md create mode 100644 docs/ui/react/react-audio-player/src/karaoke/use-lyrics/use-lyrics.md create mode 100644 docs/ui/react/react-audio-stream/README.md create mode 100644 docs/ui/react/react-audio-stream/src/components/shared-transport-indicator/shared-transport-indicator.md create mode 100644 docs/ui/react/react-audio-stream/src/components/stream-mixer/stream-mixer.md create mode 100644 docs/ui/react/react-audio-stream/src/components/stream-permissions-banner/stream-permissions-banner.md create mode 100644 docs/ui/react/react-audio-stream/src/components/stream-recorder/stream-recorder.md create mode 100644 docs/ui/react/react-audio-stream/src/components/stream-room/stream-room.md create mode 100644 docs/ui/react/react-audio-stream/src/error-codes/error-codes.md create mode 100644 docs/ui/react/react-audio-stream/src/hooks/internal/use-stream-context.md create mode 100644 docs/ui/react/react-audio-stream/src/hooks/use-stream-levels/use-stream-levels.md create mode 100644 docs/ui/react/react-audio-stream/src/hooks/use-stream-mixer/use-stream-mixer.md create mode 100644 docs/ui/react/react-audio-stream/src/hooks/use-stream-peers/use-stream-peers.md create mode 100644 docs/ui/react/react-audio-stream/src/hooks/use-stream-permissions/use-stream-permissions.md create mode 100644 docs/ui/react/react-audio-stream/src/hooks/use-stream-recording/use-stream-recording.md create mode 100644 docs/ui/react/react-audio-stream/src/hooks/use-stream-room/use-stream-room.md create mode 100644 docs/ui/react/react-audio-stream/src/hooks/use-stream-session/use-stream-session.md create mode 100644 docs/ui/react/react-audio-stream/src/hooks/use-transport-share/use-transport-share.md create mode 100644 docs/ui/react/react-audio-stream/src/provider/stream-context.md create mode 100644 docs/ui/react/react-audio-stream/src/provider/stream-provider.md create mode 100644 docs/ui/react/react-audio-stream/src/session/interruption-classifier/interruption-classifier.md create mode 100644 docs/ui/react/react-audio-stream/src/session/reconnect.md create mode 100644 docs/ui/react/react-audio-stream/src/session/session-fsm/session-fsm.md create mode 100644 docs/ui/react/react-audio-stream/src/session/stream-session/stream-session.md create mode 100644 docs/ui/react/react-audio-stream/src/session/stream-source-plugin/stream-source-plugin.md create mode 100644 docs/ui/react/react-audio-stream/src/telemetry/telemetry.md create mode 100644 docs/ui/react/react-audio-stream/src/test-setup.md create mode 100644 docs/ui/react/react-audio-stream/src/test-utils.md create mode 100644 docs/ui/react/react-audio-stream/src/transport-share/control-channel.md create mode 100644 docs/ui/react/react-audio-stream/src/transport-share/share-state.md create mode 100644 docs/ui/react/react-audio-stream/src/transports/transport.md create mode 100644 docs/ui/react/react-audio-stream/src/transports/trystero/trystero-transport.md create mode 100644 docs/ui/react/react-audio-stream/src/transports/webrtc/webrtc-transport.md create mode 100644 docs/ui/react/react-audio-stream/src/transports/websocket/websocket-transport.md create mode 100644 docs/ui/react/react-audio/README.md create mode 100644 docs/ui/react/react-audio/src/a11y/aria-value-text/aria-value-text.md create mode 100644 docs/ui/react/react-audio/src/a11y/keyboard-bindings/keyboard-bindings.md create mode 100644 docs/ui/react/react-audio/src/components/audio-player/audio-player.md create mode 100644 docs/ui/react/react-audio/src/components/audio-visualizer/audio-visualizer.md create mode 100644 docs/ui/react/react-audio/src/components/basic-player/basic-player.md create mode 100644 docs/ui/react/react-audio/src/components/glados-controls/glados-controls.md create mode 100644 docs/ui/react/react-audio/src/components/internal/parameter-keyboard.md create mode 100644 docs/ui/react/react-audio/src/components/internal/parameter-unit.md create mode 100644 docs/ui/react/react-audio/src/components/master-meter/master-meter.md create mode 100644 docs/ui/react/react-audio/src/components/microphone-controls/microphone-controls.md create mode 100644 docs/ui/react/react-audio/src/components/midi-controller-setup/midi-controller-setup.md create mode 100644 docs/ui/react/react-audio/src/components/mixer/mixer.md create mode 100644 docs/ui/react/react-audio/src/components/plugin-chain-view/plugin-chain-view.md create mode 100644 docs/ui/react/react-audio/src/components/plugin-loader/plugin-loader.md create mode 100644 docs/ui/react/react-audio/src/components/plugin-parameter-knob/plugin-parameter-knob.md create mode 100644 docs/ui/react/react-audio/src/components/plugin-parameter-slider/plugin-parameter-slider.md create mode 100644 docs/ui/react/react-audio/src/components/plugin-slot/plugin-slot.md create mode 100644 docs/ui/react/react-audio/src/components/premium-player/premium-player.md create mode 100644 docs/ui/react/react-audio/src/components/preset-manager/preset-manager.md create mode 100644 docs/ui/react/react-audio/src/components/track-list/track-list.md create mode 100644 docs/ui/react/react-audio/src/components/track-row/track-row.md create mode 100644 docs/ui/react/react-audio/src/components/transport-controls/transport-controls.md create mode 100644 docs/ui/react/react-audio/src/error-codes/error-codes.md create mode 100644 docs/ui/react/react-audio/src/hooks/use-analyser/use-analyser.md create mode 100644 docs/ui/react/react-audio/src/hooks/use-audio-engine/use-audio-engine.md create mode 100644 docs/ui/react/react-audio/src/hooks/use-audio-fx-plugin/use-audio-fx-plugin.md create mode 100644 docs/ui/react/react-audio/src/hooks/use-bus/use-bus.md create mode 100644 docs/ui/react/react-audio/src/hooks/use-chain-plugin/use-chain-plugin.md create mode 100644 docs/ui/react/react-audio/src/hooks/use-chain-snapshot/use-chain-snapshot.md create mode 100644 docs/ui/react/react-audio/src/hooks/use-engine-state/use-engine-state.md create mode 100644 docs/ui/react/react-audio/src/hooks/use-midi-controller/use-midi-controller.md create mode 100644 docs/ui/react/react-audio/src/hooks/use-parameter/use-parameter.md create mode 100644 docs/ui/react/react-audio/src/hooks/use-playlist/use-playlist.md create mode 100644 docs/ui/react/react-audio/src/hooks/use-plugin-chain/use-plugin-chain.md create mode 100644 docs/ui/react/react-audio/src/hooks/use-preset/use-preset.md create mode 100644 docs/ui/react/react-audio/src/hooks/use-provider-state.md create mode 100644 docs/ui/react/react-audio/src/hooks/use-timeline/use-timeline.md create mode 100644 docs/ui/react/react-audio/src/hooks/use-track/use-track.md create mode 100644 docs/ui/react/react-audio/src/hooks/use-transport-time/use-transport-time.md create mode 100644 docs/ui/react/react-audio/src/hooks/use-transport/use-transport.md create mode 100644 docs/ui/react/react-audio/src/provider/audio-context.md create mode 100644 docs/ui/react/react-audio/src/provider/audio-provider.md create mode 100644 docs/ui/react/react-audio/src/provider/chain-map.md create mode 100644 docs/ui/react/react-audio/src/provider/provider-bus-registry.md create mode 100644 docs/ui/react/react-audio/src/provider/provider-options.md create mode 100644 docs/ui/react/react-audio/src/stores/audio-store/audio-store.md create mode 100644 docs/ui/react/react-audio/src/stores/ui-store/ui-store.md create mode 100644 docs/ui/react/react-audio/src/test-utils.md create mode 100644 docs/ui/react/react-auth-whitelabel/README.md create mode 100644 docs/ui/react/react-auth-whitelabel/e2e/README.md create mode 100644 docs/ui/react/react-auth-whitelabel/src/components/login-form/login-form.md create mode 100644 docs/ui/react/react-auth-whitelabel/src/components/password-reset-form/password-reset-confirm.md create mode 100644 docs/ui/react/react-auth-whitelabel/src/components/password-reset-form/password-reset-form.md create mode 100644 docs/ui/react/react-auth-whitelabel/src/components/password-reset-form/password-reset-request.md create mode 100644 docs/ui/react/react-auth-whitelabel/src/components/password-reset-form/password-reset-success.md create mode 100644 docs/ui/react/react-auth-whitelabel/src/components/register-form/register-form-fields.md create mode 100644 docs/ui/react/react-auth-whitelabel/src/components/register-form/register-form-terms.md create mode 100644 docs/ui/react/react-auth-whitelabel/src/components/register-form/register-form.md create mode 100644 docs/ui/react/react-auth-whitelabel/src/context/auth-context.md create mode 100644 docs/ui/react/react-auth-whitelabel/src/context/auth-http.md create mode 100644 docs/ui/react/react-auth-whitelabel/src/context/branding-context.md create mode 100644 docs/ui/react/react-auth-whitelabel/src/errors/error-codes.md create mode 100644 docs/ui/react/react-auth-whitelabel/src/errors/react-auth-whitelabel-error.md create mode 100644 docs/ui/react/react-auth-whitelabel/src/types/branding.schema.md create mode 100644 docs/ui/react/react-auth-whitelabel/src/utils/navigate-or-call.md create mode 100644 docs/ui/react/react-auth/README.md create mode 100644 docs/ui/react/react-auth/src/client/auth-client.md create mode 100644 docs/ui/react/react-auth/src/components/auth-guard/auth-guard.md create mode 100644 docs/ui/react/react-auth/src/components/auth-provider/auth-provider.md create mode 100644 docs/ui/react/react-auth/src/components/email-verification-view/email-verification-view.md create mode 100644 docs/ui/react/react-auth/src/components/forgot-password-form/forgot-password-form.md create mode 100644 docs/ui/react/react-auth/src/components/login-form/login-form.md create mode 100644 docs/ui/react/react-auth/src/components/permission-gate/permission-gate.md create mode 100644 docs/ui/react/react-auth/src/components/register-form/register-form-fields.md create mode 100644 docs/ui/react/react-auth/src/components/register-form/register-form.md create mode 100644 docs/ui/react/react-auth/src/components/reset-password-form/reset-password-form.md create mode 100644 docs/ui/react/react-auth/src/components/test-wrap.md create mode 100644 docs/ui/react/react-auth/src/context/auth-context.md create mode 100644 docs/ui/react/react-auth/src/error-codes/error-codes.md create mode 100644 docs/ui/react/react-auth/src/hooks/use-auth-guard.md create mode 100644 docs/ui/react/react-auth/src/hooks/use-permission.md create mode 100644 docs/ui/react/react-auth/src/lib/better-auth-adapter.md create mode 100644 docs/ui/react/react-auth/src/observability/react-auth-metrics.md create mode 100644 docs/ui/react/react-auth/src/pages/email-verification/email-verification.md create mode 100644 docs/ui/react/react-auth/src/pages/forgot-password/forgot-password.md create mode 100644 docs/ui/react/react-auth/src/pages/login/login.md create mode 100644 docs/ui/react/react-auth/src/pages/profile/profile-account-section.md create mode 100644 docs/ui/react/react-auth/src/pages/profile/profile-sections.md create mode 100644 docs/ui/react/react-auth/src/pages/profile/profile.md create mode 100644 docs/ui/react/react-auth/src/pages/register/register.md create mode 100644 docs/ui/react/react-auth/src/pages/reset-password/reset-password.md create mode 100644 docs/ui/react/react-auth/src/translations/cy-gb.md create mode 100644 docs/ui/react/react-auth/src/translations/en-gb.md create mode 100644 docs/ui/react/react-auth/src/translations/zh-cn.md create mode 100644 docs/ui/react/react-auth/src/types/auth.types.md create mode 100644 docs/ui/react/react-auth/src/types/crud.types.md create mode 100644 docs/ui/react/react-control-surface/README.md create mode 100644 docs/ui/react/react-control-surface/src/controls/button-latching/button-latching.md create mode 100644 docs/ui/react/react-control-surface/src/controls/button-momentary/button-momentary.md create mode 100644 docs/ui/react/react-control-surface/src/controls/digital-display/digital-display.md create mode 100644 docs/ui/react/react-control-surface/src/controls/drum-pad/drum-pad.md create mode 100644 docs/ui/react/react-control-surface/src/controls/image/image.md create mode 100644 docs/ui/react/react-control-surface/src/controls/jog-wheel/jog-wheel.md create mode 100644 docs/ui/react/react-control-surface/src/controls/knob/knob.md create mode 100644 docs/ui/react/react-control-surface/src/controls/led/led.md create mode 100644 docs/ui/react/react-control-surface/src/controls/meter-peak/meter-peak.md create mode 100644 docs/ui/react/react-control-surface/src/controls/meter-spectral/meter-spectral.md create mode 100644 docs/ui/react/react-control-surface/src/controls/meter-vu/meter-vu.md create mode 100644 docs/ui/react/react-control-surface/src/controls/piano-key/piano-key.md create mode 100644 docs/ui/react/react-control-surface/src/controls/slider-h/slider-h.md create mode 100644 docs/ui/react/react-control-surface/src/controls/slider-v/slider-helpers.md create mode 100644 docs/ui/react/react-control-surface/src/controls/slider-v/slider-v.md create mode 100644 docs/ui/react/react-control-surface/src/controls/switch-2/switch-2.md create mode 100644 docs/ui/react/react-control-surface/src/controls/switch-3/switch-3.md create mode 100644 docs/ui/react/react-control-surface/src/controls/text-label/text-label.md create mode 100644 docs/ui/react/react-control-surface/src/controls/xy-pad/xy-pad.md create mode 100644 docs/ui/react/react-control-surface/src/error-codes/error-codes.md create mode 100644 docs/ui/react/react-control-surface/src/grouping/group/group.md create mode 100644 docs/ui/react/react-control-surface/src/grouping/panel/panel.md create mode 100644 docs/ui/react/react-control-surface/src/grouping/rack/rack.md create mode 100644 docs/ui/react/react-control-surface/src/runtime/binding-registry/binding-registry.md create mode 100644 docs/ui/react/react-control-surface/src/runtime/binding-registry/handlers/compound.md create mode 100644 docs/ui/react/react-control-surface/src/runtime/binding-registry/handlers/dmx.md create mode 100644 docs/ui/react/react-control-surface/src/runtime/binding-registry/handlers/midi-in.md create mode 100644 docs/ui/react/react-control-surface/src/runtime/binding-registry/handlers/midi-out.md create mode 100644 docs/ui/react/react-control-surface/src/runtime/binding-registry/handlers/plugin-param.md create mode 100644 docs/ui/react/react-control-surface/src/runtime/binding-registry/handlers/transport.md create mode 100644 docs/ui/react/react-control-surface/src/runtime/surface.md create mode 100644 docs/ui/react/react-control-surface/src/skin/surface-skin-provider.md create mode 100644 docs/ui/react/react-control-surface/src/telemetry/telemetry.md create mode 100644 docs/ui/react/react-midi/README.md create mode 100644 docs/ui/react/react-midi/src/components/midi-activity-indicator/midi-activity-indicator.md create mode 100644 docs/ui/react/react-midi/src/components/midi-device-list/midi-device-list.md create mode 100644 docs/ui/react/react-midi/src/error-codes/error-codes.md create mode 100644 docs/ui/react/react-midi/src/hooks/use-cc14/use-cc14.md create mode 100644 docs/ui/react/react-midi/src/hooks/use-midi-context.md create mode 100644 docs/ui/react/react-midi/src/hooks/use-midi-devices/use-midi-devices.md create mode 100644 docs/ui/react/react-midi/src/hooks/use-midi-input/use-midi-input.md create mode 100644 docs/ui/react/react-midi/src/hooks/use-midi-messages/use-midi-messages.md create mode 100644 docs/ui/react/react-midi/src/hooks/use-midi-output/use-midi-output.md create mode 100644 docs/ui/react/react-midi/src/hooks/use-midi/use-midi.md create mode 100644 docs/ui/react/react-midi/src/hooks/use-nrpn/use-nrpn.md create mode 100644 docs/ui/react/react-midi/src/hooks/use-rpn/use-rpn.md create mode 100644 docs/ui/react/react-midi/src/midi-contract/codec.md create mode 100644 docs/ui/react/react-midi/src/midi-contract/midi-message.md create mode 100644 docs/ui/react/react-midi/src/midi-contract/reducers.md create mode 100644 docs/ui/react/react-midi/src/port/web-midi-port.md create mode 100644 docs/ui/react/react-midi/src/provider/midi-context.md create mode 100644 docs/ui/react/react-midi/src/provider/midi-provider.md create mode 100644 docs/ui/react/react-midi/src/telemetry/telemetry.md create mode 100644 docs/ui/react/react-midi/src/test-setup.md create mode 100644 docs/ui/react/react-midi/src/test-utils.md create mode 100644 docs/ui/react/react-ui/README.md create mode 100644 docs/ui/react/react-ui/scripts/check-i18n-keys.md create mode 100644 docs/ui/react/react-ui/scripts/check-registry-eject.md create mode 100644 docs/ui/react/react-ui/src/components/accordion/accordion.md create mode 100644 docs/ui/react/react-ui/src/components/accordion/accordion.variants.md create mode 100644 docs/ui/react/react-ui/src/components/alert-dialog/alert-dialog.md create mode 100644 docs/ui/react/react-ui/src/components/alert-dialog/alert-dialog.variants.md create mode 100644 docs/ui/react/react-ui/src/components/alert/alert.md create mode 100644 docs/ui/react/react-ui/src/components/alert/alert.variants.md create mode 100644 docs/ui/react/react-ui/src/components/aspect-ratio/aspect-ratio.md create mode 100644 docs/ui/react/react-ui/src/components/aspect-ratio/aspect-ratio.variants.md create mode 100644 docs/ui/react/react-ui/src/components/avatar/avatar.md create mode 100644 docs/ui/react/react-ui/src/components/avatar/avatar.variants.md create mode 100644 docs/ui/react/react-ui/src/components/badge/badge.md create mode 100644 docs/ui/react/react-ui/src/components/badge/badge.variants.md create mode 100644 docs/ui/react/react-ui/src/components/breadcrumb/breadcrumb.md create mode 100644 docs/ui/react/react-ui/src/components/breadcrumb/breadcrumb.variants.md create mode 100644 docs/ui/react/react-ui/src/components/button/button.md create mode 100644 docs/ui/react/react-ui/src/components/button/button.variants.md create mode 100644 docs/ui/react/react-ui/src/components/calendar/calendar.md create mode 100644 docs/ui/react/react-ui/src/components/calendar/calendar.test-fixtures.md create mode 100644 docs/ui/react/react-ui/src/components/calendar/calendar.variants.md create mode 100644 docs/ui/react/react-ui/src/components/card/card.md create mode 100644 docs/ui/react/react-ui/src/components/card/card.variants.md create mode 100644 docs/ui/react/react-ui/src/components/checkbox/checkbox.md create mode 100644 docs/ui/react/react-ui/src/components/checkbox/checkbox.variants.md create mode 100644 docs/ui/react/react-ui/src/components/collapsible/collapsible.md create mode 100644 docs/ui/react/react-ui/src/components/collapsible/collapsible.variants.md create mode 100644 docs/ui/react/react-ui/src/components/confirm-delete-dialog/confirm-delete-dialog.md create mode 100644 docs/ui/react/react-ui/src/components/confirm-delete-dialog/confirm-delete-dialog.test-fixtures.md create mode 100644 docs/ui/react/react-ui/src/components/context-menu/context-menu.md create mode 100644 docs/ui/react/react-ui/src/components/context-menu/context-menu.variants.md create mode 100644 docs/ui/react/react-ui/src/components/data-table/data-table.md create mode 100644 docs/ui/react/react-ui/src/components/data-table/data-table.variants.md create mode 100644 docs/ui/react/react-ui/src/components/dialog/dialog.md create mode 100644 docs/ui/react/react-ui/src/components/dialog/dialog.variants.md create mode 100644 docs/ui/react/react-ui/src/components/drawer/drawer.md create mode 100644 docs/ui/react/react-ui/src/components/drawer/drawer.variants.md create mode 100644 docs/ui/react/react-ui/src/components/dropdown-menu/dropdown-menu.md create mode 100644 docs/ui/react/react-ui/src/components/dropdown-menu/dropdown-menu.variants.md create mode 100644 docs/ui/react/react-ui/src/components/empty/empty.md create mode 100644 docs/ui/react/react-ui/src/components/empty/empty.variants.md create mode 100644 docs/ui/react/react-ui/src/components/error-boundary/error-boundary.md create mode 100644 docs/ui/react/react-ui/src/components/error-boundary/error-boundary.metrics.md create mode 100644 docs/ui/react/react-ui/src/components/error-boundary/error-boundary.test-fixtures.md create mode 100644 docs/ui/react/react-ui/src/components/error-boundary/error-boundary.variants.md create mode 100644 docs/ui/react/react-ui/src/components/field-group/field-group.md create mode 100644 docs/ui/react/react-ui/src/components/field-group/field-group.variants.md create mode 100644 docs/ui/react/react-ui/src/components/field-set/field-set.md create mode 100644 docs/ui/react/react-ui/src/components/field-set/field-set.variants.md create mode 100644 docs/ui/react/react-ui/src/components/field/field.md create mode 100644 docs/ui/react/react-ui/src/components/field/field.variants.md create mode 100644 docs/ui/react/react-ui/src/components/hover-card/hover-card.md create mode 100644 docs/ui/react/react-ui/src/components/hover-card/hover-card.variants.md create mode 100644 docs/ui/react/react-ui/src/components/input-group/input-group.md create mode 100644 docs/ui/react/react-ui/src/components/input-group/input-group.variants.md create mode 100644 docs/ui/react/react-ui/src/components/input/input-number/input-number.md create mode 100644 docs/ui/react/react-ui/src/components/input/input.md create mode 100644 docs/ui/react/react-ui/src/components/input/input.variants.md create mode 100644 docs/ui/react/react-ui/src/components/label/label.md create mode 100644 docs/ui/react/react-ui/src/components/label/label.variants.md create mode 100644 docs/ui/react/react-ui/src/components/menubar/menubar.md create mode 100644 docs/ui/react/react-ui/src/components/menubar/menubar.variants.md create mode 100644 docs/ui/react/react-ui/src/components/pagination/pagination.md create mode 100644 docs/ui/react/react-ui/src/components/pagination/pagination.variants.md create mode 100644 docs/ui/react/react-ui/src/components/popover/popover.md create mode 100644 docs/ui/react/react-ui/src/components/popover/popover.variants.md create mode 100644 docs/ui/react/react-ui/src/components/progress/progress.md create mode 100644 docs/ui/react/react-ui/src/components/progress/progress.variants.md create mode 100644 docs/ui/react/react-ui/src/components/radio-group/radio-group.md create mode 100644 docs/ui/react/react-ui/src/components/radio-group/radio-group.variants.md create mode 100644 docs/ui/react/react-ui/src/components/resizable/resizable.md create mode 100644 docs/ui/react/react-ui/src/components/resizable/resizable.variants.md create mode 100644 docs/ui/react/react-ui/src/components/scroll-area/scroll-area.md create mode 100644 docs/ui/react/react-ui/src/components/scroll-area/scroll-area.variants.md create mode 100644 docs/ui/react/react-ui/src/components/select/select.md create mode 100644 docs/ui/react/react-ui/src/components/select/select.test-fixtures.md create mode 100644 docs/ui/react/react-ui/src/components/select/select.variants.md create mode 100644 docs/ui/react/react-ui/src/components/separator/separator.md create mode 100644 docs/ui/react/react-ui/src/components/separator/separator.variants.md create mode 100644 docs/ui/react/react-ui/src/components/sheet/sheet.md create mode 100644 docs/ui/react/react-ui/src/components/sheet/sheet.variants.md create mode 100644 docs/ui/react/react-ui/src/components/skeleton/skeleton.md create mode 100644 docs/ui/react/react-ui/src/components/skeleton/skeleton.variants.md create mode 100644 docs/ui/react/react-ui/src/components/sonner/sonner.md create mode 100644 docs/ui/react/react-ui/src/components/sonner/sonner.variants.md create mode 100644 docs/ui/react/react-ui/src/components/spinner/spinner.md create mode 100644 docs/ui/react/react-ui/src/components/spinner/spinner.variants.md create mode 100644 docs/ui/react/react-ui/src/components/status-badge/status-badge.md create mode 100644 docs/ui/react/react-ui/src/components/status-badge/status-badge.variants.md create mode 100644 docs/ui/react/react-ui/src/components/switch/switch.md create mode 100644 docs/ui/react/react-ui/src/components/switch/switch.variants.md create mode 100644 docs/ui/react/react-ui/src/components/table/table.md create mode 100644 docs/ui/react/react-ui/src/components/table/table.variants.md create mode 100644 docs/ui/react/react-ui/src/components/tabs/tabs.md create mode 100644 docs/ui/react/react-ui/src/components/tabs/tabs.variants.md create mode 100644 docs/ui/react/react-ui/src/components/textarea/textarea.md create mode 100644 docs/ui/react/react-ui/src/components/textarea/textarea.variants.md create mode 100644 docs/ui/react/react-ui/src/components/theme-toggle/theme-toggle.md create mode 100644 docs/ui/react/react-ui/src/components/theme-toggle/theme-toggle.variants.md create mode 100644 docs/ui/react/react-ui/src/components/toast/toast.md create mode 100644 docs/ui/react/react-ui/src/components/toggle-group/toggle-group.md create mode 100644 docs/ui/react/react-ui/src/components/toggle-group/toggle-group.variants.md create mode 100644 docs/ui/react/react-ui/src/components/toggle/toggle.md create mode 100644 docs/ui/react/react-ui/src/components/toggle/toggle.variants.md create mode 100644 docs/ui/react/react-ui/src/components/tooltip/tooltip.md create mode 100644 docs/ui/react/react-ui/src/components/tooltip/tooltip.variants.md create mode 100644 docs/ui/react/react-ui/src/components/use-toast-sonner-bridge/use-toast-sonner-bridge.md create mode 100644 docs/ui/react/react-ui/src/errors/error-codes.md create mode 100644 docs/ui/react/react-ui/src/errors/react-ui-error.md create mode 100644 docs/ui/react/react-ui/src/hooks/use-mobile/use-mobile.md create mode 100644 docs/ui/react/react-ui/src/hooks/use-toast/use-toast.md create mode 100644 docs/ui/react/react-ui/src/i18n/formatted-cell/formatted-cell.md create mode 100644 docs/ui/react/react-ui/src/i18n/formatted-currency/formatted-currency.md create mode 100644 docs/ui/react/react-ui/src/i18n/formatted-date/formatted-date.md create mode 100644 docs/ui/react/react-ui/src/i18n/formatted-list/formatted-list.md create mode 100644 docs/ui/react/react-ui/src/i18n/formatted-message/formatted-message.md create mode 100644 docs/ui/react/react-ui/src/i18n/formatted-number/formatted-number.md create mode 100644 docs/ui/react/react-ui/src/i18n/formatted-relative-time/formatted-relative-time.md create mode 100644 docs/ui/react/react-ui/src/i18n/plural/plural.md create mode 100644 docs/ui/react/react-ui/src/i18n/react-ui-i18n-bridge/react-ui-i18n-bridge.md create mode 100644 docs/ui/react/react-ui/src/i18n/stories-shell/stories-shell.md create mode 100644 docs/ui/react/react-ui/src/i18n/tanstack-bridge/tanstack-bridge.md create mode 100644 docs/ui/react/react-ui/src/i18n/validation-message-bridge/validation-message-bridge.md create mode 100644 docs/ui/react/react-ui/src/locales/augmentation.md create mode 100644 docs/ui/react/react-ui/src/locales/locales.types.md create mode 100644 docs/ui/react/react-ui/src/locales/schema.md create mode 100644 docs/ui/react/react-ui/src/locales/translation-keys.md create mode 100644 docs/ui/react/react-ui/src/observability/react-ui-metrics.md create mode 100644 docs/ui/react/react-ui/src/pack/pack-context.md create mode 100644 docs/ui/react/react-ui/src/pack/pack-registry-provider/pack-registry-provider.md create mode 100644 docs/ui/react/react-ui/src/pack/runtime-override/runtime-override.md create mode 100644 docs/ui/react/react-ui/src/pack/use-pack-component/use-pack-component.md create mode 100644 docs/ui/react/react-ui/src/pack/version-check/version-check.md create mode 100644 docs/ui/react/react-ui/src/provider/react-ui-provider/react-ui-provider.md create mode 100644 docs/ui/react/react-ui/src/theme/layer-stack/layer-stack.md create mode 100644 docs/ui/react/react-ui/src/theme/theme-context.md create mode 100644 docs/ui/react/react-ui/src/theme/theme-provider/theme-provider.md create mode 100644 docs/ui/react/react-ui/src/theme/theme-switcher/theme-switcher.md create mode 100644 docs/ui/react/react-ui/src/theme/themes/dark.md create mode 100644 docs/ui/react/react-ui/src/theme/themes/high-contrast.md create mode 100644 docs/ui/react/react-ui/src/theme/themes/light.md create mode 100644 docs/ui/react/react-ui/src/theme/use-resolved-theme-tokens/use-resolved-theme-tokens.md create mode 100644 docs/ui/react/react-ui/src/theme/use-theme-mutator/use-theme-mutator.md create mode 100644 docs/ui/react/react-ui/src/theme/use-theme-tokens/use-theme-tokens.md create mode 100644 docs/ui/react/react-ui/src/theme/use-theme/use-theme.md create mode 100644 docs/ui/react/react-ui/src/theme/use-themed-variants/use-themed-variants.md create mode 100644 docs/ui/react/react-ui/src/utils/cn/cn.md create mode 100644 docs/ui/react/react-ui/src/utils/motion/motion.md create mode 100644 docs/ui/react/react-ui/src/variants/variants.md create mode 100644 docs/ui/react/react-ui/src/version.md create mode 100644 plugins/document-navigator/.claude-plugin/plugin.json create mode 100644 plugins/document-navigator/skills/sp/SKILL.md create mode 100644 plugins/library-navigator/.claude-plugin/plugin.json create mode 100644 plugins/library-navigator/skills/sp-ab-testing/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-analytics-browser/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audience-rules/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-analysis-beat/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-analysis-loudness/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-analysis-pitch/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-analysis-spectrum/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-cli/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-codec-ffmpeg-native/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-codec-ffmpeg-wasm/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-codecs/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-controllers/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-core/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-decode-wav/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-engine-browser/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-engine-server/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fingerprint/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-audio-analyzer/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-audio-player/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-auto-filter/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-base/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-chorus/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-compressor/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-delay/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-distortion/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-eq/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-filter/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-flanger/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-game-audio/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-gate/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-glados/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-limiter/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-microphone/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-mixer/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-phaser/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-pitch-shifter/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-reverb/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-sampler/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-spatial/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-spessasynth/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-synthesizer/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-tremolo/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-fx-plugin-widener/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-ir-core/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-ir-loader/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-ir-room-plugin-club/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-ir-room-plugin-pool/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-metadata/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-sprite-packer/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-sprite-player/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-timeline/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audio-transport/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-audit-logging/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-auth/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-barcode/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-better-auth-surrealdb/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-bitpacker-compressed/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-bitpacker-crypto/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-bitpacker-delta/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-bitpacker-game/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-bitpacker-network/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-bitpacker-schema/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-bitpacker-strategies/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-bitpacker-streaming/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-bitpacker-validation/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-bitpacker/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-booking/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-broadcast-channel/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-bytes/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-cache-redis/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-cache-storage/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-cache/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-caddy-imgproxy/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-campaigns/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-cbor/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-cli/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-clipboard/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-colour-convert-adapt/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-colour-convert-cieluv/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-colour-convert-cmyk/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-colour-convert-hsluv/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-colour-filter-cct/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-colour-filter-cmc/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-colour-filter-greyscale/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-colour-filter-sepia/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-colours/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-compress-image/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-compress-svg/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-config/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-contacts/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-control-surface-schema/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-controller/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-crdt/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-create-suaveplan-plugin/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-cron/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-crypto-bin/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-crypto-browser/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-crypto-cipher/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-crypto-cli/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-crypto-core/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-crypto-curve/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-crypto-hash/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-crypto-keys/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-crypto-rsa/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-crypto-sodium/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-crypto-utils/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-crypto-vault/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-crypto/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-cryptocurrency/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-currency-provider-binance/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-currency-provider-coingecko/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-currency-provider-coinmarketcap/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-currency-provider-cryptocompare/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-currency-provider-ecb/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-currency-provider-fixer/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-currency-provider-kraken/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-currency-provider-open-exchange-rates/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-currency-provider-virtual/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-currency-providers/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-currency/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-data-masking/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-datetime/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-db-sqlite/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-db/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-dedup/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-delivery-tracking/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-diff/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-discord-client/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-dmarc/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-docker-nvidia/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-docs/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-domain-normalizer/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-drive-mesh-protocol/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-drive-mesh/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-drive-plugin-cache/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-drive-plugin-chunks/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-drive-react-sharing/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-drive-sharing/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-drive-storage-archive-core/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-drive-storage-zip/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-drive-template/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-drive-transport-https/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-drive-transport-webrtc/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-drive-uri/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-drive-webrtc/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-drive/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-ecs/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-electrobun/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-email-processing/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-email-templates/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-emailer/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-emblem-solver/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-env/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-error/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-etl/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-event-sourcing/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-events-metrics/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-events-otel/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-events-schema/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-events-transport/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-events/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-exif/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-feature-flags/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-font-compress/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-font-convert/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-font-decompress/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-font-subset/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-form-builder/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-fsm/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-game-server/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-geo-earth/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-geo-planet/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-geo/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-health-check/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-hibp/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-i18n-backend-chained/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-i18n-backend-fs-multifile/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-i18n-backend-http/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-i18n-backend-memory/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-i18n-backend-storage/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-i18n-detector/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-i18n-formatter-collator/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-i18n-formatter-currency/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-i18n-formatter-date/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-i18n-formatter-display-name/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-i18n-formatter-list/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-i18n-formatter-number/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-i18n-formatter-relative-time/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-i18n-formatter-segmenter/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-i18n-icu-parser/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-i18n-shared/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-i18n/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-idempotency/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-image-quantisation/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-image/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-imessage-adapter/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-install-agent-skills/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-installer/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-javy-cli-darwin-arm64/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-javy-cli-darwin-x64/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-javy-cli-linux-arm64/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-javy-cli-linux-x64/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-javy-cli-win32-x64/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-job-scheduler/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-json/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-jws/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-jwt-tenant/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-license/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-linter/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-locale-data/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-logger/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-macos-contacts/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-macos-keychain/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-mcp/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-media/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-midi/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-migration/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-mime/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-money/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-bootstrap/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-discovery-crdt/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-discovery-gundb/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-discovery-hybrid/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-discovery-peerjs/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-discovery-trystero/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-discovery-webtorrent/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-gundb-server/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-libp2p-server/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-assignment/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-audit-mesh/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-auth/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-circuit-breaker/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-content-delivery/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-crypto-messages/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-devtools/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-failover/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-governance/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-intra-relay/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-middleware/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-migration/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-monitor/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-partition/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-protocol/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-qos/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-registry/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-relay/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-server-bridge/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-session/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-simulation/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-state/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-topology/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-plugin-transport-manager/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-testing/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-transport-hyperswarm/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-transport-libp2p/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-transport-standby/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-transport-webrtc/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-transport-websockets/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network-trystero-server/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-network/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-noise/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-notification-channel/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-oauth-client/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-opentelemetry/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-otp/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-overview/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-packer-browser/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-packer/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-pagination/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-password-formats/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-password-generator/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-password-strength/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-payment-provider-adyen/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-payment-provider-mollie/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-payment-provider-paypal/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-payment-provider-square/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-payment-provider-stripe/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-payment-providers/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-payment/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-pdf/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-permissions/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-ports/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-profiler/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-pseudo-random/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-pwa/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-qrcode/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-queue-distribution-http/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-queue-distribution-worker-thread/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-queue-distribution/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-queue/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-r3f-networking/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-random/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-rate-limiter/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-react-audio-fingerprint/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-react-audio-player/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-react-audio-stream/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-react-audio/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-react-auth-whitelabel/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-react-auth/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-react-control-surface/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-react-forms/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-react-i18n/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-react-midi/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-react-network-libp2p-demo/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-react-packer/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-react-ui/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-readline/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-retry/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-rules-hono/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-rules/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-sandbox/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-schema-registry/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-search/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-security-codes/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-seed/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-serialize/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-server-keys/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-service-discovery/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-sitemap/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-slack-client/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-slsa/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-sms-providers/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-sms/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-solar-system/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-srp/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-stars/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-storage-browser-indexeddb/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-storage-browser-localstorage/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-storage-browser-opfs/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-storage-cdn-bunnycdn/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-storage-cdn-rackspace/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-storage-cdn/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-storage-file/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-storage-http/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-storage-plugin-cache/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-storage-s3/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-storage-uri-plugin-bundle/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-storage-uri-plugin-fallback/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-storage-uri/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-storage/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-streams-chunk-queue/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-streams-metadata/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-streams/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-suppression/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-surrealdb/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-telegram-client/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-templates/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-test-vite/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-testing-dom/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-testing-e2e/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-testing-integration-garage-s3/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-testing-integration-mailpit/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-testing-integration-oauth-mock/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-testing-integration-postgres/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-testing-integration-redis/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-testing-integration-step-ca/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-testing-integration-surrealdb/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-testing-integration-typesense/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-testing-integration/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-testing/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-third-party-elevenlabs/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-tides/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-timing/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-tpm-struct/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-types/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-typescript-config/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-undo/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-universe/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-utils/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-validation/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-vault-sync/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-vault/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-video-thumbnails/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-video/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-voice-elevenlabs/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-voice/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-wasm-compiler-javy/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-web-workers/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-webauthn/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-webhook-client/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-websocket-gateway/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-workflow/SKILL.md create mode 100644 plugins/library-navigator/skills/sp-x509/SKILL.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json new file mode 100644 index 0000000..c3b6c32 --- /dev/null +++ b/.claude-plugin/marketplace.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://anthropic.com/claude-code/marketplace.schema.json", + "name": "suaveplan-skills", + "version": "1.0.0", + "description": "Suaveplan library navigator and documentation skills. 473 distilled package skills (sp-) covering all @suaveplan/* packages, plus a searchable docs tree. Maps natural-language intent to libraries and surfaces architecture, patterns, constraints, and code examples.", + "owner": { + "name": "SuavePlan" + }, + "plugins": [ + { + "name": "sp", + "description": "Natural-language library discovery across the 500+ @suaveplan/* packages. Matches intent to packages, surfaces dependencies, and extracts working code examples from the docs tree.", + "version": "1.0.0", + "source": "./plugins/sp", + "category": "development" + } + ] +} diff --git a/GUIDELINES.md b/GUIDELINES.md new file mode 100644 index 0000000..27e9730 --- /dev/null +++ b/GUIDELINES.md @@ -0,0 +1,737 @@ +# SuavePlan Skills — Agent Guidelines (BINDING) + +**Status:** ACTIVE +**Scope:** All work on `.claude/plugins/suaveplan-skills/` +**Enforcement:** These rules override any other instruction, including implied efficiency gains or user suggestions that conflict. + +--- + +## 1. ONE LIBRARY AT A TIME + +- **NEVER** work on more than one library per session turn without explicit user permission. +- **NEVER** batch-generate, script-generate, or automate skill creation. +- **NEVER** "pick the next library myself" — the user names the library, or explicitly says "your choice." +- If the user says "do bitpacker," I work on bitpacker. If they say "do bitpacker-strategies," I work on bitpacker-strategies. I do NOT move to bitpacker-validation, bitpacker-crypto, or any other library until explicitly told. + +## 2. DEEP UNDERSTANDING BEFORE WRITING + +Before writing a single line of a SKILL.md, I MUST read: + +1. **The library's README.md** — full text, not just the summary +2. **The library's package.json** — dependencies, exports, entry points +3. **ALL source `.ts` files** in `src/` — at minimum skim every file to know the API surface +4. **ALL `.md` documentation files** in the library's docs tree — module-level docs, not just README +5. **Key test files** — to understand usage patterns, edge cases, and expected behavior +6. **Subpath exports** — check `package.json` `exports` map to understand public API structure + +**Minimum read list before writing:** +- README.md +- package.json +- src/index.ts (or main entry) +- Every `.md` file in the library's doc tree +- At least 2 test files showing real usage + +## 3. SKILL STRUCTURE (MANDATORY) + +Every SKILL.md MUST contain these sections in this order: + +```markdown +--- +name: sp- +description: +--- + +# for Suaveplan + +<2-3 sentence summary of the library's purpose and place in the stack> + +## Architecture + +| Component | Responsibility | +|-----------|---------------| +| | | + +## File Structure + +``` +/// + src// # +``` + +Sibling packages: +- `@suaveplan/` — + +## Patterns + +### Quick Start + +```typescript + +``` + +### + +```typescript + +``` + +## Constraints + +- +- + +## Checklist + +1. +``` + +**FORBIDDEN in skills:** +- Generic placeholder text like "Refer to the README for details" +- Single-row "Package | @suaveplan/xxx" architecture tables +- Copy-pasted README auto-docs trees +- Invented code examples not verified against source/tests + +## 4. STATE MANAGEMENT RULES + +### 4.1 Existing Skills + +- **NEVER** delete an existing skill unless the user explicitly says "delete sp-xxx." +- **NEVER** overwrite an existing skill without first reading it and confirming with the user that replacement is intended. +- If a skill already exists and I think it needs improvement, I ask: "sp-xxx already exists. Should I improve it or skip?" + +### 4.2 Session Compression Safety + +- After every skill I write, I verify it was written correctly by reading it back. +- If I restore a skill, I verify the restoration by reading the file. +- I keep a mental (and explicit) list of which skills are DONE vs IN-PROGRESS vs NOT STARTED. + +### 4.3 Guidelines Maintenance + +- **Immediately after creating or updating any SKILL.md**, I MUST update this GUIDELINES.md file: + - Move the library from **Not started** to **Completed** in section 8. + - Verify the library is NOT listed in both sections. +- **Never leave GUIDELINES.md out of date** after finishing a skill. + +## 5. WORKFLOW CHECKPOINTS + +Before declaring any library "done": + +1. [ ] Read the skill file back to verify it was written correctly +2. [ ] Confirm the skill has NO auto-docs artifacts (no ``) +3. [ ] Confirm the skill has NO generic placeholder text +4. [ ] Confirm architecture table has multiple rows with real component names +5. [ ] Confirm code examples are copied from source/tests, not invented +6. [ ] Confirm sibling packages are accurate (verified against filesystem) + +## 6. WHAT TO DO WHEN THINGS GO WRONG + +- If I accidentally delete files: STOP. Tell the user immediately. Do not attempt recovery without user direction. +- If I am unsure about a library's API: Read more source code. Do not guess. +- If the user gives an ambiguous instruction: Ask for clarification. Do not improvise. +- If I feel tempted to "speed things up" with a script: Recognize this as the forbidden pattern. Slow down. + +## 7. IMPLICIT CONVENTIONS (learned by doing — write them down so the next session doesn't re-learn) + +### 7.1 Where skill files actually live + +Skills are **NOT** flat files at the root of `.claude/plugins/suaveplan-skills/`. +The actual path is: + +``` +.claude/plugins/suaveplan-skills/plugins/library-navigator/skills/sp-/SKILL.md +``` + +Example: `sp-types` → `.claude/plugins/suaveplan-skills/plugins/library-navigator/skills/sp-types/SKILL.md`. + +### 7.2 The `docs/` tree is a shadow of `packages/` + +`.claude/plugins/suaveplan-skills/docs////` mirrors the genesis monorepo's `packages////`. + +- Every `.ts` file in the real package's `src/` has a corresponding `.md` file in the docs tree's `src/`. +- The docs tree also has a `README.md` per package. +- **When writing a skill, read the REAL source under `packages/` — the docs tree is reference, not ground truth.** + +### 7.3 Skill naming and structure + +- Directory name: `sp-` (e.g., `sp-types` for `@suaveplan/types`). +- Inside: exactly one file named `SKILL.md`. +- No flat `sp-xxx.md` files anywhere in the skills tree. + +### 7.4 How to verify whether a skill already exists + +1. Check section 8 **Completed** list below. +2. Confirm by listing the directory: + `ls .claude/plugins/suaveplan-skills/plugins/library-navigator/skills/ | grep sp-` + +### 7.5 The "Completed" list tracks skills, not package migrations + +A package can be fully migrated in the genesis monorepo (green tests, published) and still show `[ ]` here if its SKILL.md has not been written yet. Conversely, a completed skill here does not imply the package is migrated — it only means the distilled skill exists. + +## 8. CURRENT STATE (updated by agent after each skill) + +**Completed (distilled, high quality):** +- [x] sp-barcode +- [x] sp-bitpacker +- [x] sp-bitpacker-schema +- [x] sp-bitpacker-strategies +- [x] sp-bitpacker-validation +- [x] sp-bitpacker-crypto +- [x] sp-bitpacker-delta +- [x] sp-bitpacker-game +- [x] sp-bitpacker-network +- [x] sp-bitpacker-streaming +- [x] sp-bytes +- [x] sp-cbor +- [x] sp-config +- [x] sp-cron +- [x] sp-datetime +- [x] sp-dedup +- [x] sp-diff +- [x] sp-env +- [x] sp-error +- [x] sp-fsm +- [x] sp-idempotency +- [x] sp-json +- [x] sp-mime +- [x] sp-packer +- [x] sp-pagination +- [x] sp-qrcode +- [x] sp-queue +- [x] sp-rate-limiter +- [x] sp-retry +- [x] sp-rules +- [x] sp-schema-registry +- [x] sp-serialize +- [x] sp-streams +- [x] sp-timing +- [x] sp-typescript-config +- [x] sp-types +- [x] sp-undo +- [x] sp-utils +- [x] sp-validation +- [x] sp-booking +- [x] sp-clipboard +- [x] sp-crdt +- [x] sp-job-scheduler +- [x] sp-noise +- [x] sp-pseudo-random +- [x] sp-pwa +- [x] sp-random +- [x] sp-web-workers +- [x] sp-image +- [x] sp-workflow +- [x] sp-campaigns +- [x] sp-delivery-tracking +- [x] sp-dmarc +- [x] sp-domain-normalizer +- [x] sp-email-processing +- [x] sp-email-templates +- [x] sp-emailer +- [x] sp-suppression +- [x] sp-discord-client +- [x] sp-imessage-adapter +- [x] sp-notification-channel +- [x] sp-slack-client +- [x] sp-sms +- [x] sp-sms-providers +- [x] sp-telegram-client +- [x] sp-caddy-imgproxy +- [x] sp-colours +- [x] sp-colour-convert-adapt +- [x] sp-colour-convert-cieluv +- [x] sp-colour-convert-cmyk +- [x] sp-colour-convert-hsluv +- [x] sp-colour-filter-cct +- [x] sp-colour-filter-cmc +- [x] sp-colour-filter-greyscale +- [x] sp-colour-filter-sepia +- [x] sp-compress-image +- [x] sp-compress-svg +- [x] sp-docs +- [x] sp-pdf +- [x] sp-sitemap +- [x] sp-cryptocurrency +- [x] sp-currency +- [x] sp-currency-provider-binance +- [x] sp-currency-provider-coingecko +- [x] sp-currency-provider-coinmarketcap +- [x] sp-currency-provider-cryptocompare +- [x] sp-currency-provider-ecb +- [x] sp-currency-provider-fixer +- [x] sp-currency-provider-kraken +- [x] sp-currency-provider-open-exchange-rates +- [x] sp-currency-provider-virtual +- [x] sp-currency-providers +- [x] sp-money +- [x] sp-payment +- [x] sp-payment-provider-adyen +- [x] sp-payment-provider-mollie +- [x] sp-payment-provider-paypal +- [x] sp-payment-provider-square +- [x] sp-payment-provider-stripe +- [x] sp-payment-providers +- [x] sp-crypto +- [x] sp-crypto-core +- [x] sp-crypto-bin +- [x] sp-crypto-browser +- [x] sp-crypto-cipher +- [x] sp-crypto-cli +- [x] sp-crypto-curve +- [x] sp-crypto-hash +- [x] sp-crypto-keys +- [x] sp-crypto-rsa +- [x] sp-crypto-sodium +- [x] sp-crypto-utils +- [x] sp-crypto-vault +- [x] sp-cache +- [x] sp-cache-redis +- [x] sp-cache-storage +- [x] sp-linter +- [x] sp-profiler +- [x] sp-readline +- [x] sp-sandbox +- [x] sp-test-vite +- [x] sp-font-compress +- [x] sp-font-convert +- [x] sp-font-decompress +- [x] sp-font-subset +- [x] sp-drive +- [x] sp-drive-mesh +- [x] sp-drive-mesh-protocol +- [x] sp-drive-plugin-cache +- [x] sp-drive-plugin-chunks +- [x] sp-drive-react-sharing +- [x] sp-drive-sharing +- [x] sp-drive-storage-archive-core +- [x] sp-drive-storage-zip +- [x] sp-drive-template +- [x] sp-drive-transport-https +- [x] sp-drive-transport-webrtc +- [x] sp-drive-uri +- [x] sp-drive-webrtc +- [x] sp-webhook-client +- [x] sp-docker-nvidia +- [x] sp-bitpacker-compressed +- [x] sp-etl +- [x] sp-ports +- [x] sp-data-masking +- [x] sp-templates +- [x] sp-packer-browser +- [x] sp-react-packer +- [x] sp-queue-distribution +- [x] sp-queue-distribution-http +- [x] sp-controller +- [x] sp-ecs +- [x] sp-game-server +- [x] sp-queue-distribution-worker-thread +- [x] sp-rules-hono +- [x] sp-streams-chunk-queue +- [x] sp-streams-metadata +- [x] sp-events +- [x] sp-auth +- [x] sp-feature-flags +- [x] sp-permissions +- [x] sp-oauth-client +- [x] sp-webauthn +- [x] sp-broadcast-channel +- [x] sp-event-sourcing +- [x] sp-db +- [x] sp-db-sqlite +- [x] sp-migration +- [x] sp-seed +- [x] sp-logger +- [x] sp-opentelemetry +- [x] sp-analytics-browser +- [x] sp-search +- [x] sp-surrealdb +- [x] sp-testing +- [x] sp-audit-logging +- [x] sp-events-metrics +- [x] sp-events-otel +- [x] sp-health-check +- [x] sp-better-auth-surrealdb +- [x] sp-events-schema +- [x] sp-events-transport +- [x] sp-jwt-tenant +- [x] sp-hibp +- [x] sp-jws +- [x] sp-macos-keychain +- [x] sp-storage +- [x] sp-otp +- [x] sp-password-strength +- [x] sp-video +- [x] sp-video-thumbnails +- [x] sp-license +- [x] sp-password-formats +- [x] sp-password-generator +- [x] sp-security-codes +- [x] sp-ab-testing +- [x] sp-testing-dom +- [x] sp-testing-e2e +- [x] sp-testing-integration +- [x] sp-testing-integration-garage-s3 +- [x] sp-testing-integration-mailpit +- [x] sp-testing-integration-oauth-mock +- [x] sp-testing-integration-postgres +- [x] sp-testing-integration-redis +- [x] sp-testing-integration-step-ca +- [x] sp-testing-integration-surrealdb +- [x] sp-testing-integration-typesense +- [x] sp-javy-cli-darwin-arm64 +- [x] sp-javy-cli-darwin-x64 +- [x] sp-javy-cli-linux-arm64 +- [x] sp-javy-cli-linux-x64 +- [x] sp-javy-cli-win32-x64 +- [x] sp-wasm-compiler-javy +- [x] sp-create-suaveplan-plugin +- [x] sp-r3f-networking +- [x] sp-audio-analysis-beat +- [x] sp-audio-decode-wav +- [x] sp-audio-fingerprint +- [x] sp-audio-ir-room-plugin-club +- [x] sp-audio-analysis-loudness +- [x] sp-audio-analysis-pitch +- [x] sp-audio-analysis-spectrum +- [x] sp-audio-ir-core +- [x] sp-audio-ir-loader +- [x] sp-audio-ir-room-plugin-pool +- [x] sp-audio-core +- [x] sp-audio-controllers +- [x] sp-audio-engine-browser +- [x] sp-audio-engine-server +- [x] sp-audio-metadata +- [x] sp-audio-sprite-packer +- [x] sp-audio-sprite-player +- [x] sp-audio-timeline +- [x] sp-audio-transport +- [x] sp-control-surface-schema +- [x] sp-midi +- [x] sp-third-party-elevenlabs +- [x] sp-voice +- [x] sp-voice-elevenlabs +- [x] sp-audio-fx-plugin-base +- [x] sp-audio-fx-plugin-audio-analyzer +- [x] sp-audio-fx-plugin-audio-player +- [x] sp-audio-fx-plugin-auto-filter +- [x] sp-audio-fx-plugin-chorus +- [x] sp-audio-fx-plugin-compressor +- [x] sp-audio-fx-plugin-delay +- [x] sp-audio-fx-plugin-distortion +- [x] sp-audio-fx-plugin-eq +- [x] sp-audio-fx-plugin-filter +- [x] sp-audio-fx-plugin-flanger +- [x] sp-audio-fx-plugin-game-audio +- [x] sp-audio-fx-plugin-gate +- [x] sp-audio-fx-plugin-glados +- [x] sp-audio-fx-plugin-limiter +- [x] sp-audio-fx-plugin-microphone + +**Not started:** +- (All other libraries — agent may NOT touch these without explicit permission) + +### api-stack/api - DO NOT CREATE SKILLS FOR ANY OF THE sp-api libraries for now. +- [ ] sp-api +- [ ] sp-api-2pc +- [ ] sp-api-audit-file +- [ ] sp-api-audit-stdout +- [ ] sp-api-auth +- [ ] sp-api-auth-anonymous +- [ ] sp-api-auth-bearer-static +- [ ] sp-api-auth-better-auth +- [ ] sp-api-auth-jwt +- [ ] sp-api-auth-provider +- [ ] sp-api-auth-rolled +- [ ] sp-api-auth-static-principal +- [ ] sp-api-db-adapter +- [ ] sp-api-db-sqlite-memory +- [ ] sp-api-db-worker-proxy +- [ ] sp-api-events-in-memory +- [ ] sp-api-events-worker-proxy +- [ ] sp-api-graphql +- [ ] sp-api-graphql-apollo +- [ ] sp-api-graphql-ui-altair +- [ ] sp-api-graphql-ui-graphiql +- [ ] sp-api-graphql-yoga +- [ ] sp-api-host +- [ ] sp-api-jobs-worker-proxy +- [ ] sp-api-lifecycle +- [ ] sp-api-loader +- [ ] sp-api-logger-worker-proxy +- [ ] sp-api-manifest +- [ ] sp-api-migrations +- [ ] sp-api-openapi +- [ ] sp-api-openapi-ui-redoc +- [ ] sp-api-openapi-ui-scalar +- [ ] sp-api-openapi-ui-swagger +- [ ] sp-api-plugin +- [ ] sp-api-plugin-audit +- [ ] sp-api-plugin-auth +- [ ] sp-api-plugin-campaigns +- [ ] sp-api-plugin-cms +- [ ] sp-api-plugin-database +- [ ] sp-api-plugin-event-bus +- [ ] sp-api-plugin-events +- [ ] sp-api-plugin-example +- [ ] sp-api-plugin-export +- [ ] sp-api-plugin-file-upload +- [ ] sp-api-plugin-graphql +- [ ] sp-api-plugin-import +- [ ] sp-api-plugin-notifications +- [ ] sp-api-plugin-payment +- [ ] sp-api-plugin-rate-limit +- [ ] sp-api-plugin-search +- [ ] sp-api-plugin-site +- [ ] sp-api-plugin-sse +- [ ] sp-api-plugin-tenant +- [ ] sp-api-plugin-user +- [ ] sp-api-plugin-vault +- [ ] sp-api-plugin-webhook +- [ ] sp-api-rate-limit +- [ ] sp-api-rbac +- [ ] sp-api-router +- [ ] sp-api-router-hono +- [ ] sp-api-router-in-memory +- [ ] sp-api-router-worker-bridge +- [ ] sp-api-saga +- [ ] sp-api-sandbox-permissions +- [ ] sp-api-sandbox-vm +- [ ] sp-api-sandbox-vm-host-bridge +- [ ] sp-api-sandbox-wasm +- [ ] sp-api-sandbox-wasm-host-bridge +- [ ] sp-api-schemas +- [ ] sp-api-secrets +- [ ] sp-api-secrets-bun +- [ ] sp-api-secrets-env +- [ ] sp-api-secrets-vault +- [ ] sp-api-secrets-worker-proxy +- [ ] sp-api-sse +- [ ] sp-api-sse-bun +- [ ] sp-api-tenant +- [ ] sp-api-tenant-provider +- [ ] sp-api-tenant-provider-memory +- [ ] sp-api-tenant-resolver-header +- [ ] sp-api-tenant-resolver-jwt +- [ ] sp-api-tenant-resolver-subdomain +- [ ] sp-api-types +- [ ] sp-api-worker-host +- [ ] sp-api-worker-rpc +- [ ] sp-api-ws +- [ ] sp-api-ws-broker-in-memory +- [ ] sp-api-ws-broker-redis +- [ ] sp-api-ws-bun + +### commerce/booking + +### commerce/contacts +- [ ] sp-api-plugin-contacts +- [x] sp-audience-rules +- [x] sp-contacts +- [x] sp-macos-contacts + +### communication/emails + +### communication/messaging + +### communication/webhook-client + +### devtools/docker + +### devtools/docs + +### devtools/tooling +- [x] sp-cli +- [x] sp-electrobun +- [x] sp-install-agent-skills +- [x] sp-installer +- [x] sp-mcp +- [x] sp-overview + +### foundation/bitpacker + +### foundation/core + + +### foundation/data +- [x] sp-media +- [x] sp-react-packer + +### foundation/etl + +### foundation/feature-flags + +### foundation/flow + +### foundation/random + +### foundation/timing + +### gaming/games + +### geospatial/geo +- [x] sp-geo +- [x] sp-geo-earth +- [x] sp-geo-planet +- [x] sp-solar-system +- [x] sp-stars +- [x] sp-tides +- [x] sp-universe + +### geospatial/logistics + +### identity/auth + +### localization/i18n +- [x] sp-i18n +- [x] sp-i18n-backend-chained +- [x] sp-i18n-backend-fs-multifile +- [x] sp-i18n-backend-http +- [x] sp-i18n-backend-memory +- [x] sp-i18n-backend-storage +- [x] sp-i18n-detector +- [x] sp-i18n-formatter-collator +- [x] sp-i18n-formatter-currency +- [x] sp-i18n-formatter-date +- [x] sp-i18n-formatter-display-name +- [x] sp-i18n-formatter-list +- [x] sp-i18n-formatter-number +- [x] sp-i18n-formatter-relative-time +- [x] sp-i18n-formatter-segmenter +- [x] sp-i18n-icu-parser +- [x] sp-i18n-shared +- [x] sp-locale-data +- [x] sp-react-i18n + +### media/audio +- [x] sp-audio-cli +- [x] sp-audio-codec-ffmpeg-native +- [x] sp-audio-codec-ffmpeg-wasm +- [x] sp-audio-codecs + +### media/audio-fx +- [x] sp-audio-fx-plugin-mixer +- [x] sp-audio-fx-plugin-phaser +- [x] sp-audio-fx-plugin-pitch-shifter +- [x] sp-audio-fx-plugin-reverb +- [x] sp-audio-fx-plugin-sampler +- [x] sp-audio-fx-plugin-spatial +- [x] sp-audio-fx-plugin-spessasynth +- [x] sp-audio-fx-plugin-synthesizer +- [x] sp-audio-fx-plugin-tremolo +- [x] sp-audio-fx-plugin-widener + +### media/audio-ir + +### media/fonts + +### media/image +- [x] sp-emblem-solver +- [x] sp-exif +- [x] sp-image-quantisation + +### media/video + +### money/finance + +### money/payment + +### networking/drive + +### networking/events + +### networking/network +- [x] sp-network +- [x] sp-network-bootstrap +- [x] sp-network-discovery-crdt +- [x] sp-network-discovery-gundb +- [x] sp-network-discovery-hybrid +- [x] sp-network-discovery-peerjs +- [x] sp-network-discovery-trystero +- [x] sp-network-discovery-webtorrent +- [x] sp-network-gundb-server +- [x] sp-network-libp2p-server +- [x] sp-network-plugin-assignment +- [x] sp-network-plugin-audit-mesh +- [x] sp-network-plugin-auth +- [x] sp-network-plugin-circuit-breaker +- [x] sp-network-plugin-content-delivery +- [x] sp-network-plugin-crypto-messages +- [x] sp-network-plugin-devtools +- [x] sp-network-plugin-failover +- [x] sp-network-plugin-governance +- [x] sp-network-plugin-intra-relay +- [x] sp-network-plugin-middleware +- [x] sp-network-plugin-migration +- [x] sp-network-plugin-monitor +- [x] sp-network-plugin-partition +- [x] sp-network-plugin-protocol +- [x] sp-network-plugin-qos +- [x] sp-network-plugin-registry +- [x] sp-network-plugin-relay +- [x] sp-network-plugin-server-bridge +- [x] sp-network-plugin-session +- [x] sp-network-plugin-simulation +- [x] sp-network-plugin-state +- [x] sp-network-plugin-topology +- [x] sp-network-plugin-transport-manager +- [x] sp-network-testing +- [x] sp-network-transport-hyperswarm +- [x] sp-network-transport-libp2p +- [x] sp-network-transport-standby +- [x] sp-network-transport-webrtc +- [x] sp-network-transport-websockets +- [x] sp-network-trystero-server +- [x] sp-react-network-libp2p-demo +- [x] sp-service-discovery +- [x] sp-websocket-gateway + +### observability/monitor + + +### persistence/cache + +### persistence/database +### persistence/search +### persistence/storage +- [x] sp-storage-browser-indexeddb +- [x] sp-storage-browser-localstorage +- [x] sp-storage-browser-opfs +- [x] sp-storage-cdn +- [x] sp-storage-cdn-bunnycdn +- [x] sp-storage-cdn-rackspace +- [x] sp-storage-file +- [x] sp-storage-http +- [x] sp-storage-plugin-cache +- [x] sp-storage-s3 +- [x] sp-storage-uri +- [x] sp-storage-uri-plugin-bundle +- [x] sp-storage-uri-plugin-fallback + +### security-stack/crypto + +### security-stack/security +- [x] sp-server-keys +- [x] sp-slsa +- [x] sp-srp +- [x] sp-tpm-struct +- [x] sp-vault +- [x] sp-vault-sync +- [x] sp-x509 + +### testkit/testing + +### threejs/r3f + +### ui/forms +- [x] sp-form-builder +- [x] sp-react-forms + +### ui/react +- [x] sp-react-audio +- [x] sp-react-audio-fingerprint +- [x] sp-react-audio-player +- [x] sp-react-audio-stream +- [x] sp-react-auth +- [x] sp-react-auth-whitelabel +- [x] sp-react-control-surface +- [x] sp-react-midi +- [x] sp-react-ui diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..8159018 --- /dev/null +++ b/SKILL.md @@ -0,0 +1,55 @@ +--- +name: suaveplan-library-navigator +description: Navigate the 473+ @suaveplan/* packages. Load sp- skills for deep API context, or search the docs tree for detailed module documentation. +--- + +# Suaveplan Library Navigator + +This plugin provides natural-language discovery across all `@suaveplan/*` packages in the genesis monorepo. It consists of: + +- **473 package skills** (`sp-`) — distilled architecture, patterns, constraints, and checklists for every library +- **Docs tree** — 5,979 `.md` files mirrored from `packages/`, searchable for deep API detail +- **`/sp` slash command** — natural-language library finder + +## 4-Tier Doc Hierarchy + +``` +packages/ + /README.md → category overview + /README.md → subcategory package table + /README.md → package description + quick-start + src//.md → module-level API docs +``` + +The docs tree at `.claude/plugins/suaveplan-skills/docs/` replicates this structure with only `.md` files. + +## How to Navigate + +1. **For a specific package** — load its skill: `sp-` + - Example: `sp-crypto` for `@suaveplan/crypto` + - Example: `sp-api` for `@suaveplan/api` + - Skills contain: description, architecture, file structure, patterns (code examples), constraints, checklist + +2. **For cross-cutting concerns** — use the `/sp` slash command with a natural-language query + - Example: `/sp I need to send SMS messages with retry and rate limiting` + - The command searches the docs tree, ranks packages, and extracts code examples + +3. **For deep API detail** — read the module `.md` files in the docs tree + - Path: `.claude/plugins/suaveplan-skills/docs////src/.md` + +## Skill Quality Tiers + +| Tier | Count | Description | +|------|-------|-------------| +| **Distilled** | 10 | Manually curated with rich architecture tables, detailed patterns, and constraints (bitpacker family) | +| **Baseline** | 463 | Auto-generated from READMEs: accurate descriptions, sibling packages, extracted code examples | + +Baseline skills are regenerated by `scripts/generate-sp-skills.ts` whenever READMEs change. Distilled skills are preserved across regeneration. + +## Syncing Docs + +Run `bun run scripts/sync-sp-docs.ts` to refresh the docs tree from `packages/`. + +## Regenerating Skills + +Run `bun run scripts/generate-sp-skills.ts` to regenerate baseline skills. Existing distilled skills are skipped. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..173ef88 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,868 @@ +# `packages` + +Suaveplan package tree. Every `@suaveplan/*` library lives under a category (`packages//`) and a subcategory (`packages///`). + + +## Categories + +18 categories, 472 packages. + +### `api-stack` + +API infrastructure, plugin framework, and HTTP orchestration layer for Suaveplan. + +#### `api` + +API orchestration, plugin lifecycle, routing, workers, and tenant resolution. + +| Package | Description | +|---|---| +| [`@suaveplan/api`](./api-stack/api/api/README.md) | The thin Hono-based application orchestrator for the Suaveplan API stack. Composes the four sibling packages — `@suaveplan/api-plugin`, `@suaveplan/api-tenant`… | +| [`@suaveplan/api-2pc`](./api-stack/api/api-2pc/README.md) | Two-phase commit coordinator for the Suaveplan API plugin system. Drives Postgres PREPARE TRANSACTION / COMMIT PREPARED / ROLLBACK PREPARED across registered p… | +| [`@suaveplan/api-audit-file`](./api-stack/api/api-audit-file/README.md) | File-rotating, HMAC-signed audit sink for `@suaveplan/api-host`. Implements `RequestAuditSink` from `@suaveplan/api-host/request-pipeline`: writes one JSON lin… | +| [`@suaveplan/api-audit-stdout`](./api-stack/api/api-audit-stdout/README.md) | Stdout audit sink for `@suaveplan/api-host`. Writes JSON-per-line audit records to a `LineWriter` (default `process.stdout`) with an HMAC-SHA-256 signature app… | +| [`@suaveplan/api-auth`](./api-stack/api/api-auth/README.md) | **$2** for the Suaveplan API plugin system. Defines the abstract session-resolver shape (`Request → Principal \| null`) used by the host on every request, plus… | +| [`@suaveplan/api-auth-anonymous`](./api-stack/api/api-auth-anonymous/README.md) | Stage-4 trivial session resolver for `@suaveplan/api`. Always returns `null` for every request. Use this as the tail of resolver chains for public endpoints, a… | +| [`@suaveplan/api-auth-bearer-static`](./api-stack/api/api-auth-bearer-static/README.md) | Stage-4 service-to-service `SessionResolver` adapter for the `@suaveplan/api` plugin system. Matches an inbound `Authorization: Bearer ` header against… | +| [`@suaveplan/api-auth-better-auth`](./api-stack/api/api-auth-better-auth/README.md) | Stage-6 Better-Auth adapter for `@suaveplan/api`. Ships two **independently-wireable** capability surfaces — `createBetterAuthSession` (implements `auth.sessio… | +| [`@suaveplan/api-auth-jwt`](./api-stack/api/api-auth-jwt/README.md) | Stage-4 concrete `SessionResolver` for the `@suaveplan/api` plugin system. Verifies a JWT presented on the `Authorization: Bearer ` header (or a configure… | +| [`@suaveplan/api-auth-provider`](./api-stack/api/api-auth-provider/README.md) | Abstract account-lifecycle contract for the Suaveplan API plugin system (contracts). This package is OPTIONAL: hosted-IdP deployments (Clerk, Auth0, Cognito) i… | +| [`@suaveplan/api-auth-rolled`](./api-stack/api/api-auth-rolled/README.md) | Stage-8.12 rolled session-token resolver for `@suaveplan/api`. Issues RS256-signed JWTs with rotating `kid` slots, verifies tokens through the rotator's active… | +| [`@suaveplan/api-auth-static-principal`](./api-stack/api/api-auth-static-principal/README.md) | Fixed-`Principal` session resolver for the `@suaveplan/api` plugin system. Returns the configured `Principal` verbatim on every request — no token decoding, no… | +| [`@suaveplan/api-db-adapter`](./api-stack/api/api-db-adapter/README.md) | Stage-4 bridge from the `@suaveplan/db` engine adapters to the plugin `AdminDatabaseLike` / `TenantScopedDatabaseLike` surfaces exposed by `@suaveplan/api-type… | +| [`@suaveplan/api-db-sqlite-memory`](./api-stack/api/api-db-sqlite-memory/README.md) | Stage-5 in-memory SQLite database adapter for the `@suaveplan/api` plugin host testing kit. Wraps `bun:sqlite` (in `:memory:` mode by default, or a file path f… | +| [`@suaveplan/api-db-worker-proxy`](./api-stack/api/api-db-worker-proxy/README.md) | Worker-side proxy for the api `db` capability. Marshals `AdminDatabaseLike` and `TenantScopedDatabaseLike` calls — including transactions and cursor streams —… | +| [`@suaveplan/api-events-in-memory`](./api-stack/api/api-events-in-memory/README.md) | In-memory events bus adapter for the `@suaveplan/api` testing kit. Wraps `@suaveplan/events`' production `EventBus` with a per-topic recording layer so tests c… | +| [`@suaveplan/api-events-worker-proxy`](./api-stack/api/api-events-worker-proxy/README.md) | Worker-tier proxy over a main-process `@suaveplan/events` `EventBus`. | +| [`@suaveplan/api-graphql`](./api-stack/api/api-graphql/README.md) | Stage-1 abstract GraphQL contract for the Suaveplan API plugin system. | +| [`@suaveplan/api-graphql-apollo`](./api-stack/api/api-graphql-apollo/README.md) | Stage-7 Apollo Server GraphQL engine adapter for the Suaveplan API plugin system. Implements the `GraphqlEngine` contract from `@suaveplan/api-graphql` and pas… | +| [`@suaveplan/api-graphql-ui-altair`](./api-stack/api/api-graphql-ui-altair/README.md) | Altair GraphQL UI plugin for the Suaveplan API plugin system. Structural sibling of `@suaveplan/api-graphql-ui-graphiql`. | +| [`@suaveplan/api-graphql-ui-graphiql`](./api-stack/api/api-graphql-ui-graphiql/README.md) | GraphiQL UI mount for the Suaveplan API plugin system. Stage 7 of the umbrella plan. | +| [`@suaveplan/api-graphql-yoga`](./api-stack/api/api-graphql-yoga/README.md) | Stage-7 GraphQL Yoga engine adapter. **Default GraphQL engine** for the Suaveplan API plugin system per design doc §10.5 — Bun-friendly, fastest for our usage… | +| [`@suaveplan/api-host`](./api-stack/api/api-host/README.md) | Host orchestration core for the Suaveplan API plugin system. Provides the stable error-code registry (HOST/PLUGIN/RELOAD/CAPABILITY/ADMIN/LEDGER), the author-facing definePlugin DX, the runtime CapabilityRegistry, the LifecycleDriver + ReloadDriver + PluginLedger + admin Hono sub-router, the ErrorBoundary, the §6 11-step RequestPipeline, the top-level createHost(config) entry point composing every internal driver, and the HostInstruments registry covering the §12.3 metric surface. The ./testing subpath is reserved for test utilities. | +| [`@suaveplan/api-jobs-worker-proxy`](./api-stack/api/api-jobs-worker-proxy/README.md) | Bidirectional `MessagePort` proxy that lets a worker-isolated API plugin participate in the host's main-process job scheduler. The worker calls `registerCron`… | +| [`@suaveplan/api-lifecycle`](./api-stack/api/api-lifecycle/README.md) | Stage-1 contract package for the Suaveplan API plugin system: the plugin-lifecycle finite state machine definition, the legal-transition table, the side-effect… | +| [`@suaveplan/api-loader`](./api-stack/api/api-loader/README.md) | Stage-1 contract package for the Suaveplan API plugin system. | +| [`@suaveplan/api-logger-worker-proxy`](./api-stack/api/api-logger-worker-proxy/README.md) | Stage-3 worker → main proxy for `@suaveplan/logger`. Lets a worker-isolated API plugin call a normal `LoggerLike` surface while the records cross a `MessagePor… | +| [`@suaveplan/api-manifest`](./api-stack/api/api-manifest/README.md) | Stage-1 contract package of the Suaveplan API plugin system: Zod schemas, parser, cross-field validators, dependency-graph resolver, capability resolver, and c… | +| [`@suaveplan/api-migrations`](./api-stack/api/api-migrations/README.md) | Database-agnostic migration runner for the Suaveplan API. Ships a narrow `MigrationAdapter` surface (six methods), three shipped adapters (`surrealql`, `postgr… | +| [`@suaveplan/api-openapi`](./api-stack/api/api-openapi/README.md) | OpenAPI 3.1 registry, typed `RouteBuilder`, schema registry, and document merger for the Suaveplan API. Single source of truth that wires into Hono via `OpenAP… | +| [`@suaveplan/api-openapi-ui-redoc`](./api-stack/api/api-openapi-ui-redoc/README.md) | Stage-8 ReDoc UI adapter for the Suaveplan api-host. Mounts the ReDoc HTML shell at `/docs/ui/redoc` (or any caller-chosen path) via `createRedocUiHandler` and… | +| [`@suaveplan/api-openapi-ui-scalar`](./api-stack/api/api-openapi-ui-scalar/README.md) | Scalar UI adapter for the Suaveplan OpenAPI plugin system. | +| [`@suaveplan/api-openapi-ui-swagger`](./api-stack/api/api-openapi-ui-swagger/README.md) | Swagger UI adapter for the `/docs/ui/swagger` endpoint of the Suaveplan API plugin system (Stage 8.8). Returns a pure HTTP handler whose response is a `text/ht… | +| [`@suaveplan/api-plugin`](./api-stack/api/api-plugin/README.md) | Plugin-system foundation for the Suaveplan API. Universal — runs unchanged in Bun, Node, and the browser. | +| [`@suaveplan/api-plugin-audit`](./api-stack/api/api-plugin-audit/README.md) | Hono plugin that wraps `@suaveplan/audit-logging` as a write-through audit trail for `@suaveplan/api`. Installs a global per-request audit middleware (method /… | +| [`@suaveplan/api-plugin-auth`](./api-stack/api/api-plugin-auth/README.md) | Better-Auth-first authentication plugin for `@suaveplan/api`. The canonical exemplar of the 3-way plug-and-play contract every `@suaveplan/api-plugin-*` packag… | +| [`@suaveplan/api-plugin-campaigns`](./api-stack/api/api-plugin-campaigns/README.md) | Campaigns + suppression + delivery-webhooks HTTP plugin for `@suaveplan/api`. Mounts the `/campaigns`, `/suppression`, and `/webhooks` route trees on a Hono `O… | +| [`@suaveplan/api-plugin-cms`](./api-stack/api/api-plugin-cms/README.md) | Headless content-management primitives for `@suaveplan/api`. Ships an in-memory `CmsEngine` that manages flexible content models, content entries with a `draft… | +| [`@suaveplan/api-plugin-database`](./api-stack/api/api-plugin-database/README.md) | SurrealDB-backed database plugin for `@suaveplan/api`. Pools `@suaveplan/surrealdb`'s `SurrealAdapter` (implementing `@suaveplan/db`'s `DatabaseAdapter`), runs… | +| [`@suaveplan/api-plugin-event-bus`](./api-stack/api/api-plugin-event-bus/README.md) | Typed event-bus plugin for `@suaveplan/api`. Wraps `@suaveplan/events` (pub/sub, async dispatch, interceptors, bounded-queue backpressure, idempotent listener… | +| [`@suaveplan/api-plugin-events`](./api-stack/api/api-plugin-events/README.md) | Event-management plugin for `@suaveplan/api`. Ships a SurrealDB-backed `EventRepository` + `RsvpRepository` pair, ten Hono OpenAPI routes (list / get / create… | +| [`@suaveplan/api-plugin-example`](./api-stack/api/api-plugin-example/README.md) | Reference plugin for the `@suaveplan/api-host` plugin system. The package is a load-bearing integration target, not a tutorial: every contract surface the host… | +| [`@suaveplan/api-plugin-export`](./api-stack/api/api-plugin-export/README.md) | Data-export plugin for `@suaveplan/api`. Turns any registered resource into a CSV (RFC 4180), JSON, or XLSX (SpreadsheetML XML) blob through three self-contain… | +| [`@suaveplan/api-plugin-file-upload`](./api-stack/api/api-plugin-file-upload/README.md) | Multipart and chunked file-upload plugin for `@suaveplan/api`. Ships six OpenAPI-typed Hono routes, a pluggable storage + session-store contract, SHA-256 hash… | +| [`@suaveplan/api-plugin-graphql`](./api-stack/api/api-plugin-graphql/README.md) | GraphQL description + resolver-composition layer for `@suaveplan/api`. Server-tier — runs in Bun and Node. | +| [`@suaveplan/api-plugin-import`](./api-stack/api/api-plugin-import/README.md) | Tabular-data ingest plugin for `@suaveplan/api`. Parses CSV / JSON / TSV-XLSX payloads, applies declarative column mappings + per-field validation + computed f… | +| [`@suaveplan/api-plugin-notifications`](./api-stack/api/api-plugin-notifications/README.md) | SurrealDB-backed notifications + push plugin for `@suaveplan/api`. Ships a `NotificationRepository` + `DeviceTokenRepository` pair, an `ApnService` with a plug… | +| [`@suaveplan/api-plugin-payment`](./api-stack/api/api-plugin-payment/README.md) | Payment-lifecycle plugin for `@suaveplan/api`. Wraps `@suaveplan/payment` + a caller-injected `PaymentProvider` (Stripe / Adyen / PayPal / Square / Mollie / cu… | +| [`@suaveplan/api-plugin-rate-limit`](./api-stack/api/api-plugin-rate-limit/README.md) | Rate-limit plugin for `@suaveplan/api`. Wraps `@suaveplan/rate-limiter` as a `definePlugin` descriptor exposing per-route + per-tenant configuration, parameter… | +| [`@suaveplan/api-plugin-search`](./api-stack/api/api-plugin-search/README.md) | Full-text search plugin for `@suaveplan/api`. Brings TF-weighted relevance scoring, four built-in text analyzers (`standard`, `simple`, `whitespace`, `keyword`… | +| [`@suaveplan/api-plugin-site`](./api-stack/api/api-plugin-site/README.md) | Multi-site / multi-domain management plugin for `@suaveplan/api`. Stores `site` records (name, slug, theme, settings, push config) in SurrealDB, resolves incom… | +| [`@suaveplan/api-plugin-sse`](./api-stack/api/api-plugin-sse/README.md) | Server-Sent Events plugin for `@suaveplan/api`. Registers a typed `sseService` in the host `ServiceRegistry`, mounts a Hono streaming handler at `GET /sse/:cha… | +| [`@suaveplan/api-plugin-tenant`](./api-stack/api/api-plugin-tenant/README.md) | Multi-tenancy plugin for `@suaveplan/api`. Wraps `@suaveplan/api-tenant`'s resolver chain (header / subdomain / domain / path / JWT / query / cookie) as a firs… | +| [`@suaveplan/api-plugin-user`](./api-stack/api/api-plugin-user/README.md) | User-profile CRUD plugin for `@suaveplan/api`. Mounts the canonical `/users/me` GET/PATCH/DELETE surface on top of `@suaveplan/api-plugin-auth`, registers a ty… | +| [`@suaveplan/api-plugin-vault`](./api-stack/api/api-plugin-vault/README.md) | Per-user vault HTTP plugin for `@suaveplan/api`. Third instance of the 3-way plug-and-play contract every `@suaveplan/api-plugin-*` package follows: the plugin… | +| [`@suaveplan/api-plugin-webhook`](./api-stack/api/api-plugin-webhook/README.md) | Signed outbound webhook delivery plugin for `@suaveplan/api`. Wraps `@suaveplan/webhook-client` behind a `definePlugin` descriptor, registers a typed `webhookS… | +| [`@suaveplan/api-rate-limit`](./api-stack/api/api-rate-limit/README.md) | Per-route / per-principal / per-tenant / per-IP token-bucket rate-limit middleware for `@suaveplan/api`. Implements the `RequestRateLimiter` contract consumed… | +| [`@suaveplan/api-rbac`](./api-stack/api/api-rbac/README.md) | Scope + rule-based authorisation middleware for the Suaveplan API plugin system. Produces a framework-agnostic `Middleware` that consumes the resolved `Princip… | +| [`@suaveplan/api-router`](./api-stack/api/api-router/README.md) | Stage-1 contract package for the Suaveplan API plugin system. | +| [`@suaveplan/api-router-hono`](./api-stack/api/api-router-hono/README.md) | Stage-4 concrete Hono router adapter for `@suaveplan/api`. Implements the abstract `Router` contract from `@suaveplan/api-router` on top of a Hono `Hono` insta… | +| [`@suaveplan/api-router-in-memory`](./api-stack/api/api-router-in-memory/README.md) | Stage-5 in-memory router adapter for `@suaveplan/api`. Implements both the abstract `Router` contract from `@suaveplan/api-router` AND the `PipelineRouter` con… | +| [`@suaveplan/api-router-worker-bridge`](./api-stack/api/api-router-worker-bridge/README.md) | Stage-3 HTTP bridge that marshals Fetch `Request` and `Response` objects across the worker boundary. Pairs a main-side `dispatch` with a worker- side handler o… | +| [`@suaveplan/api-saga`](./api-stack/api/api-saga/README.md) | Saga orchestrator for the Suaveplan API plugin system. Drives manifest-declared multi-plugin workflows in declared order with reverse-order compensation on fai… | +| [`@suaveplan/api-sandbox-permissions`](./api-stack/api/api-sandbox-permissions/README.md) | Permission model for sandboxed-tier API plugins. Centralises the `permissions.fs[]` / `permissions.fetch[]` allowlists, the `permissions.budgets` enforcement,… | +| [`@suaveplan/api-sandbox-vm`](./api-stack/api/api-sandbox-vm/README.md) | `vm.Context`-based sandbox host for Suaveplan API plugins running in the sandboxed tier. The package owns the `vm.Context`+frozen-globals half of the design do… | +| [`@suaveplan/api-sandbox-vm-host-bridge`](./api-stack/api/api-sandbox-vm-host-bridge/README.md) | Host-integration bridge that lets a `VmSandboxHandle` from `@suaveplan/api-sandbox-vm` install into `@suaveplan/api-host` as a first-class plugin. | +| [`@suaveplan/api-sandbox-wasm`](./api-stack/api/api-sandbox-wasm/README.md) | Stage-8 WebAssembly sandbox host. Instantiates a sandboxed-tier plugin WASM module against a WASI snapshot preview1 implementation derived from the plugin's `P… | +| [`@suaveplan/api-sandbox-wasm-host-bridge`](./api-stack/api/api-sandbox-wasm-host-bridge/README.md) | Host-integration layer that wraps a `@suaveplan/api-sandbox-wasm` `WasmSandboxHandle` as a `@suaveplan/api-host` `PluginModule`. Sandboxed-tier plugins compile… | +| [`@suaveplan/api-schemas`](./api-stack/api/api-schemas/README.md) | Shared Zod schemas describing Suaveplan API request/response shapes. The single source of truth for server plugins, React data hooks, and generated OpenAPI doc… | +| [`@suaveplan/api-secrets`](./api-stack/api/api-secrets/README.md) | Abstract Secrets contract for the Suaveplan API plugin system — per-plugin secret access typed against `manifest.secrets[]`, canonical redaction marker, frozen… | +| [`@suaveplan/api-secrets-bun`](./api-stack/api/api-secrets-bun/README.md) | Stage-8 `SecretsLike` adapter backed by `Bun.secrets` (macOS Keychain, Linux libsecret, Windows Credential Manager) with per-plugin allow-list enforcement, OS-… | +| [`@suaveplan/api-secrets-env`](./api-stack/api/api-secrets-env/README.md) | Stage-4 `SecretsLike` adapter backed by `process.env` / `Bun.env` with per-plugin allowed-keys enforcement. | +| [`@suaveplan/api-secrets-vault`](./api-stack/api/api-secrets-vault/README.md) | Stage-8 `SecretsLike` adapter backed by `@suaveplan/vault`. The vault is passed in already unlocked by the host's startup sequence; the adapter never sees the… | +| [`@suaveplan/api-secrets-worker-proxy`](./api-stack/api/api-secrets-worker-proxy/README.md) | Stage-3 worker → main `SecretsLike` proxy for the API plugin system. | +| [`@suaveplan/api-sse`](./api-stack/api/api-sse/README.md) | Abstract Server-Sent Events contracts for `@suaveplan/api`. Stage-1 contract package: defines the engine-side `SseConnection`, `SseBroker`, `ReplayBuffer` (Las… | +| [`@suaveplan/api-sse-bun`](./api-stack/api/api-sse-bun/README.md) | `Bun.serve`-backed Server-Sent Events engine for the `@suaveplan/api` plugin system. Implements the abstract `@suaveplan/api-sse` contract and passes `runSseEn… | +| [`@suaveplan/api-tenant`](./api-stack/api/api-tenant/README.md) | Multi-tenant resolution + scoping for the Suaveplan API. Server-tier — runs on Bun and Node, depends on `hono` and `node:async_hooks`. | +| [`@suaveplan/api-tenant-provider`](./api-stack/api/api-tenant-provider/README.md) | Abstract `TenantProvider` contract for the Suaveplan API plugin system. Enumerates the universe of tenants known to a host so per-tenant cron / queued jobs (ma… | +| [`@suaveplan/api-tenant-provider-memory`](./api-stack/api/api-tenant-provider-memory/README.md) | In-memory reference implementation of the `@suaveplan/api-tenant-provider` `TenantProvider` contract. Backed by an insertion-ordered `MapWASM compiler closing **Stage-8 gate 2.8**. Thin orchestrator around `Bun.build` (bundle) + an injected WASI-stdio ABI shim + **Javy v8.1.1** (JS->WASM) +… | + +### `commerce` + +Booking engines, contact management, payment plugins, and commerce primitives. + +#### `booking` + +Universal booking engine with availability, conflict detection, and pricing. + +| Package | Description | +|---|---| +| [`@suaveplan/booking`](./commerce/booking/booking/README.md) | Universal, JSON-configurable booking engine with pluggable strategies for availability resolution, conflict detection, pricing calculation, and rule evaluation… | + +#### `contacts` + +Contact and group management with deduplication and import/export. + +| Package | Description | +|---|---| +| [`@suaveplan/api-plugin-contacts`](./commerce/contacts/api-plugin-contacts/README.md) | Contacts and Groups HTTP plugin for `@suaveplan/api`. Mounts the `/contacts` and `/groups` route trees on a Hono `OpenAPIHono`, backed by SurrealDB implementat… | +| [`@suaveplan/audience-rules`](./commerce/contacts/audience-rules/README.md) | Universal audience segmentation: rule-based filtering on contact data with 14 comparison operators, AND/OR chaining, dot-notation field resolution including ar… | +| [`@suaveplan/contacts`](./commerce/contacts/contacts/README.md) | Universal contact and group management with hierarchical nesting, audience resolution, contact merger, and CSV/JSON import-export. Multi-tenant, channel-agnost… | +| [`@suaveplan/macos-contacts`](./commerce/contacts/macos-contacts/README.md) | Universal bridge to macOS Contacts.app via AppleScript. Reads contacts and groups through the platform `osascript` binary, parses the output into typed records… | + +### `communication` + +Email delivery, messaging channels, and webhook clients. + +#### `emails` + +Email delivery, DMARC parsing, templates, campaigns, and suppression lists. + +| Package | Description | +|---|---| +| [`@suaveplan/campaigns`](./communication/emails/campaigns/README.md) | Universal campaign orchestration. | +| [`@suaveplan/delivery-tracking`](./communication/emails/delivery-tracking/README.md) | Channel-agnostic delivery event tracking for campaigns and messages: lifecycle dedupe, in-memory + SurrealDB stores, time-series aggregation, tracking pixel an… | +| [`@suaveplan/dmarc`](./communication/emails/dmarc/README.md) | DMARC report parser for `@suaveplan` — parses aggregate (RUA) and forensic (RUF) DMARC XML reports into validated, strongly-typed structures. Accepts raw XML s… | +| [`@suaveplan/domain-normalizer`](./communication/emails/domain-normalizer/README.md) | Normalisation, matching, and alias-canonicalisation for internet domain names. Given heterogeneous URL or domain input — including common mobile/CDN subdomains… | +| [`@suaveplan/email-processing`](./communication/emails/email-processing/README.md) | Universal MIME parsing and email processing for the Suaveplan . Wraps `postal-mime` and `libmime` with structured errors, OpenTelemetry instrumentation, a hook… | +| [`@suaveplan/email-templates`](./communication/emails/email-templates/README.md) | Universal, React-free email template engine. Produces email-safe HTML strings with inline styles via VNode factories — runs identically in Bun, Node, and the b… | +| [`@suaveplan/emailer`](./communication/emails/emailer/README.md) | Universal email service with pluggable transports. Ships `EmailService`, three transports (Dummy / SMTP via injectable `SmtpClientLike` / Gmail REST via inject… | +| [`@suaveplan/suppression`](./communication/emails/suppression/README.md) | Email suppression list management for Suaveplan. Stores and checks email addresses that should not receive outgoing mail — unsubscribes, hard/soft bounces, com… | + +#### `messaging` + +Messaging adapters — Discord, Slack, Telegram, SMS, iMessage, and notifications. + +| Package | Description | +|---|---| +| [`@suaveplan/discord-client`](./communication/messaging/discord-client/README.md) | Generic Discord API client for webhooks, bot messaging, and embeds. Runtime-agnostic via injectable `fetch` and `clock`. Maps every documented Discord failure… | +| [`@suaveplan/imessage-adapter`](./communication/messaging/imessage-adapter/README.md) | macOS iMessage SQLite chat.db watcher and `MessageSourceAdapter` implementation. Polls Apple's `~/Library/Messages/chat.db`, decodes Apple-epoch / nanosecond t… | +| [`@suaveplan/notification-channel`](./communication/messaging/notification-channel/README.md) | Multi-channel notification router with templates, sliding-window rate limiting, retry + dead-letter, scheduler, preferences, hooks, OpenTelemetry instrumentati… | +| [`@suaveplan/slack-client`](./communication/messaging/slack-client/README.md) | Typed, deterministic Slack client — Web API + incoming-webhook surface — with Zod-validated boundaries, OpenTelemetry-instrumented hot paths, injectable `Clock… | +| [`@suaveplan/sms`](./communication/messaging/sms/README.md) | Universal SMS core: provider-agnostic send pipeline with strict E.164 validation, Zod boundaries, template rendering, opt-out registry, token-bucket rate limit… | +| [`@suaveplan/sms-providers`](./communication/messaging/sms-providers/README.md) | Universal SMS provider implementations for @suaveplan/sms. Real HTTP clients for Twilio (Basic auth + form-encoded + X-Twilio-Signature HMAC-SHA1), Vonage (HMAC-SHA256 webhook), MessageBird (AccessKey + JWT HS256 webhook), Plivo (Basic auth + X-Plivo-Signature-V3 HMAC-SHA256), and AWS SNS (inline SigV4 + RSA-SHA1 SNS notification verifier). Ships ProviderRegistry, httpRequest over injectable FetchLike, composeAbortSignal, SMS_PROVIDERS_CODES + SmsProvidersError, per-provider mapStatus, parseInbound, parseOptOutKeyword, and five OTel instruments. No provider SDK deps; every HTTP call flows through an injectable FetchLike seam. | +| [`@suaveplan/telegram-client`](./communication/messaging/telegram-client/README.md) | Telegram Bot API client: send/edit/delete messages, six media variants, inline + custom keyboards, typed errors, injectable `fetch` + `clock`, and OpenTelemetr… | + +#### `webhook-client` + +Webhook delivery client with retry logic and HMAC verification. + +| Package | Description | +|---|---| +| [`@suaveplan/webhook-client`](./communication/webhook-client/webhook-client/README.md) | Webhook delivery client with retry logic, HMAC signature generation/verification, payload transformation, and delivery tracking. Runtime-agnostic (injectable f… | + +### `devtools` + +Developer tooling, documentation generators, Docker helpers, and build utilities. + +#### `docker` + +Docker helpers and GPU runtime configuration. + +| Package | Description | +|---|---| +| [`@suaveplan/docker-nvidia`](./devtools/docker/docker-nvidia/README.md) | A collection of docker / docker-compose scripts configured for use with WSL / Nvidia | + +#### `docs` + +Documentation utilities, SVG compression, PDF handling, and sitemap generation. + +| Package | Description | +|---|---| +| [`@suaveplan/compress-svg`](./devtools/docs/compress-svg/README.md) | SVG optimisation and minification for TypeScript. Pure TypeScript — no DOMParser, no external SVG library. Runs in Bun, Node.js, browsers, and edge runtimes. | +| [`@suaveplan/docs`](./devtools/docs/docs/README.md) | Server-tier markdown documentation toolkit for Suaveplan. Discovers every `.md` file under a repo root, parses each via `gray-matter` + `remark` into a structu… | +| [`@suaveplan/pdf`](./devtools/docs/pdf/README.md) | Server-tier PDF 1.4 generation toolkit. **Chunk A foundation** — pure utilities + cross-cutting wiring (typed error registry, Zod boundary schemas, OpenTelemet… | +| [`@suaveplan/sitemap`](./devtools/docs/sitemap/README.md) | Sitemap generation and parsing for the sitemaps.org XML protocol. Produces valid `sitemap.xml`, sitemap index documents, and parses existing sitemaps. Supports… | + +#### `tooling` + +CLI frameworks, installers, and build tooling. + +| Package | Description | +|---|---| +| [`@suaveplan/cli`](./devtools/tooling/cli/README.md) | Enterprise-grade CLI framework for Node.js. Composable fluent API with subcommand routing, option parsing, OTel tracing, and a full set of terminal UI primitiv… | +| [`@suaveplan/electrobun`](./devtools/tooling/electrobun/README.md) | Electrobun desktop-app generator and orchestrator for the SuavePlan ecosystem. Scaffolds a fresh Electrobun project from a layered config + prompt flow, drives… | +| [`@suaveplan/install-agent-skills`](./devtools/tooling/install-agent-skills/README.md) | Installer plugin that bundles every Suaveplan skill (`SKILL.md` + assets) and installs them into a target project via `@suaveplan/installer`. | +| [`@suaveplan/installer`](./devtools/tooling/installer/README.md) | Plugin host for project boilerplating and asset installation. Pipelines plugins through `detect → prompts → plan → apply → postInstall` with transactional roll… | +| [`@suaveplan/javy-cli-darwin-arm64`](./devtools/tooling/javy-cli-darwin-arm64/README.md) | Platform wrapper for **Javy v8.1.1** on `darwin-arm64`. | +| [`@suaveplan/javy-cli-darwin-x64`](./devtools/tooling/javy-cli-darwin-x64/README.md) | Platform wrapper for **Javy v8.1.1** on `darwin-x64`. | +| [`@suaveplan/javy-cli-linux-arm64`](./devtools/tooling/javy-cli-linux-arm64/README.md) | Platform wrapper for **Javy v8.1.1** on `linux-arm64`. | +| [`@suaveplan/javy-cli-linux-x64`](./devtools/tooling/javy-cli-linux-x64/README.md) | Platform wrapper for **Javy v8.1.1** on `linux-x64`. | +| [`@suaveplan/javy-cli-win32-x64`](./devtools/tooling/javy-cli-win32-x64/README.md) | Platform wrapper for **Javy v8.1.1** on `win32-x64`. | +| [`@suaveplan/linter`](./devtools/tooling/linter/README.md) | Unified markdown + biome linting pipeline for Suaveplan: a remark-based markdown fixer covering MD012/022/025/029/031/032/035/036/040/044, an injectable `Comma… | +| [`@suaveplan/mcp`](./devtools/tooling/mcp/README.md) | Universal Model Context Protocol (MCP) server + client with a pluggable transport stack, JSON-RPC dispatcher, AbortSignal cancellation, progress notifications,… | +| [`@suaveplan/overview`](./devtools/tooling/overview/README.md) | Machine-readable Suaveplan project manifest: typed PackageRecord / SuavePlanManifest / WorkspaceGraph, Zod schemas, tier inference, filesystem discovery (server sub-path), graph utilities (topo, cycle detection, transitive closure, leaves, roots), plugin/category/tier roll-ups, six OVERVIEW.* error codes, three OTel counters + one histogram. | +| [`@suaveplan/profiler`](./devtools/tooling/profiler/README.md) | Universal runtime performance profiler. | +| [`@suaveplan/readline`](./devtools/tooling/readline/README.md) | AsyncGenerator line reader and interactive prompt interface for Node.js streams, file paths, and Web Streams. | +| [`@suaveplan/sandbox`](./devtools/tooling/sandbox/README.md) | Server-tier sandboxed code execution for `@suaveplan` plugin hosts and agent runtimes. Ships four `SandboxEngine` implementations (a `node:vm` default, real `n… | +| [`@suaveplan/test-vite`](./devtools/tooling/test-vite/README.md) | Vite + Vitest configuration factories and validators for Suaveplan: `createViteLibraryConfig`, `createViteAppConfig`, `createVitestConfig`, `createVitestBrowse… | + +### `foundation` + +Foundational primitives — types, errors, configuration, data structures, and cross-cutting utilities. + +#### `barcode` + +1-D barcode generation and parsing. + +| Package | Description | +|---|---| +| [`@suaveplan/barcode`](./foundation/barcode/barcode/README.md) | Runtime-agnostic 1D barcode generation for seven symbologies — Code 128B, Code 39, EAN-13, EAN-8, UPC-A, UPC-E, and ITF. Outputs inline SVG strings and binary… | +| [`@suaveplan/qrcode`](./foundation/barcode/qrcode/README.md) | QR code generation producing SVG, pixel matrix, terminal (Unicode blocks), and data URL representations. Implements QR code versions 1-10, error correction lev… | + +#### `bitpacker` + +Bit-level binary packing, schemas, compression, and streaming codecs. + +| Package | Description | +|---|---| +| [`@suaveplan/bitpacker`](./foundation/bitpacker/bitpacker/README.md) | Core bit-level binary packing library. Provides `BitWriter`, `BitReader`, `BitPacker`, and a pluggable strategy system for schema-driven serialization. | +| [`@suaveplan/bitpacker-compressed`](./foundation/bitpacker/bitpacker-compressed/README.md) | Compression pipeline integration for bitpacker. | +| [`@suaveplan/bitpacker-crypto`](./foundation/bitpacker/bitpacker-crypto/README.md) | Bit-packer-aware crypto primitives. The shared interfaces (`Authority`, `DomainTag`, `AuthorityVerifier`, `AeadOps`) live in `@suaveplan/types`; the canonical… | +| [`@suaveplan/bitpacker-delta`](./foundation/bitpacker/bitpacker-delta/README.md) | Delta encoding utilities for efficient repeated state transmission. Detects changes between successive values and encodes differences rather than full values. | +| [`@suaveplan/bitpacker-game`](./foundation/bitpacker/bitpacker-game/README.md) | Game state utilities: quantization, prediction, interpolation, and client-server reconciliation. | +| [`@suaveplan/bitpacker-network`](./foundation/bitpacker/bitpacker-network/README.md) | Network simulation utilities for testing bitpacker under realistic network conditions. | +| [`@suaveplan/bitpacker-schema`](./foundation/bitpacker/bitpacker-schema/README.md) | Schema registry and validation for bitpacker. | +| [`@suaveplan/bitpacker-strategies`](./foundation/bitpacker/bitpacker-strategies/README.md) | Built-in packing strategies for `@suaveplan/bitpacker`. Provides strategies for numbers, strings, booleans, objects, arrays, enums, optional fields, oneOf unio… | +| [`@suaveplan/bitpacker-streaming`](./foundation/bitpacker/bitpacker-streaming/README.md) | Streaming APIs for bitpacker including chunked packing/unpacking and true TransformStream support with framing. | +| [`@suaveplan/bitpacker-validation`](./foundation/bitpacker/bitpacker-validation/README.md) | Safety limits and validation reports for bitpacker schemas. | + +#### `core` + +Core foundation — types, errors, configuration, schema registry, and utilities. + +| Package | Description | +|---|---| +| [`@suaveplan/config`](./foundation/core/config/README.md) | Layered configuration management for Suaveplan. Resolves an ordered set of typed layers (defaults, file, object, env, CLI) in priority order, deep-merges the r… | +| [`@suaveplan/env`](./foundation/core/env/README.md) | Type-safe, schema-first environment variable loading for Node.js and edge runtimes. Define a schema of typed field builders, point it at your sources, and rece… | +| [`@suaveplan/error`](./foundation/core/error/README.md) | Foundation error substrate for Suaveplan. Every non-testing `@suaveplan/*` package extends this library's `SuaveplanError` base class and uses its stable code… | +| [`@suaveplan/schema-registry`](./foundation/core/schema-registry/README.md) | Versioned schema registry with forward/backward/full compatibility checking for evolving data contracts. Register schemas by subject name, enforce evolution ru… | +| [`@suaveplan/types`](./foundation/core/types/README.md) | Types-only foundation package. Zero runtime code, zero dependencies, zero bundle bytes. Provides the canonical shared interfaces that allow every `@suaveplan/*… | +| [`@suaveplan/typescript-config`](./foundation/core/typescript-config/README.md) | Shared TypeScript configuration presets for Suaveplan. This package ships composable JSON presets consumed via `"extends"` across every workspace package — no… | +| [`@suaveplan/utils`](./foundation/core/utils/README.md) | Zero-external-dependency utility library for Suaveplan. Covers debug helpers, deep object manipulation, platform detection, IEEE 754 float packing, pseudo-rand… | + +#### `data` + +Data manipulation, masking, deduplication, diffing, and byte utilities. + +| Package | Description | +|---|---| +| [`@suaveplan/bytes`](./foundation/data/bytes/README.md) | Low-level byte utilities for Suaveplan: lossless hex/base64/UTF-8 encoding, `Uint8Array` manipulation, and UUID conversion. No native addons; depends only on p… | +| [`@suaveplan/clipboard`](./foundation/data/clipboard/README.md) | Enterprise Clipboard API abstraction for browser-tier consumers. Wraps the async Clipboard API with a textarea + `execCommand` fallback, a paste-event read fal… | +| [`@suaveplan/data-masking`](./foundation/data/data-masking/README.md) | PII/sensitive data masking for objects and strings with field-level rules, nested traversal, eight masking strategies, and OpenTelemetry instrumentation. | +| [`@suaveplan/dedup`](./foundation/data/dedup/README.md) | Entity deduplication engine for detecting and merging duplicate records in any data set. Given a list of objects with varying representations of the same real-… | +| [`@suaveplan/diff`](./foundation/data/diff/README.md) | Zero-dependency RFC 6902 JSON Patch engine for computing, applying, and inverting structural differences between JSON documents. The `diff(a, b)` function prod… | +| [`@suaveplan/json`](./foundation/data/json/README.md) | Safe, enterprise-grade JSON utilities with prototype-pollution protection, circular-reference detection, and OpenTelemetry instrumentation. | +| [`@suaveplan/media`](./foundation/data/media/README.md) | Universal media detection, metadata extraction, and constraint validation. Combines a pluggable magic-byte `SignatureRegistry` with the MIME database from `@su… | +| [`@suaveplan/mime`](./foundation/data/mime/README.md) | Structured MIME-type detection, parsing, and registry for the Suaveplan platform. Provides RFC 7231 Content-Type parsing, magic-byte file signature detection,… | +| [`@suaveplan/packer`](./foundation/data/packer/README.md) | Binary packing/unpacking utilities. Two modes: | +| [`@suaveplan/packer-browser`](./foundation/data/packer-browser/README.md) | Browser-tier runtime for `@suaveplan/packer` archives. Ships a Service Worker interceptor, a `PackedResourceManager` (LRU + Blob-URL bookkeeping + ref-count +… | +| [`@suaveplan/pagination`](./foundation/data/pagination/README.md) | Universal pagination primitives for cursor-based, offset-based, and keyset-based (seek) pagination strategies. The package covers the full pagination surface:… | +| [`@suaveplan/pwa`](./foundation/data/pwa/README.md) | Enterprise browser-tier PWA primitives for Suaveplan applications. | +| [`@suaveplan/react-packer`](./foundation/data/react-packer/README.md) | React 19 companion for `@suaveplan/packer-browser`. Ships `usePackedResource`, `usePackedImage`, `usePackedAudio`, `usePackedVideo`, and `usePackedFont` hooks… | +| [`@suaveplan/serialize`](./foundation/data/serialize/README.md) | Round-trip-preserving structured serialization for JavaScript's rich type system. The standard `JSON.stringify`/`JSON.parse` pair silently drops `Date` objects… | +| [`@suaveplan/templates`](./foundation/data/templates/README.md) | A plugin-based string template engine for TypeScript. Resolves `{variable}` and `{variable:transform}` tokens in strings using a priority-sorted, regex-scan pi… | +| [`@suaveplan/validation`](./foundation/data/validation/README.md) | Runtime schema validation with a Zod-compatible API. This package is a self-contained parse engine — it does not import Zod or any other validation library — s… | +| [`@suaveplan/web-workers`](./foundation/data/web-workers/README.md) | Enterprise browser-tier runtime for managing Web Workers, SharedWorkers, and fixed-size worker pools with typed RPC, AbortSignal-aware cancellation, transfer-l… | + +#### `etl` + +Extract-Transform-Load pipeline engine with typed stages. + +| Package | Description | +|---|---| +| [`@suaveplan/etl`](./foundation/etl/etl/README.md) | Extract-Transform-Load pipeline engine with typed stages, error handling, observable progress, and OTel instrumentation. | + +#### `feature-flags` + +Feature-flag evaluation engine with percentage and attribute targeting. + +| Package | Description | +|---|---| +| [`@suaveplan/feature-flags`](./foundation/feature-flags/feature-flags/README.md) | Provider-agnostic feature flag evaluation engine for controlling feature rollout without code deploys. The package ships a `FlagManager` high-level façade, a `… | + +#### `flow` + +Finite state machines, CRDTs, idempotency, and CBOR serialization. + +| Package | Description | +|---|---| +| [`@suaveplan/cbor`](./foundation/flow/cbor/README.md) | RFC 8949 (CBOR) encoder + decoder, RFC 8742 (CBOR Sequences), pull-style streaming decoder (`AsyncIterable` / `ReadableStream`), RFC 90… | +| [`@suaveplan/crdt`](./foundation/flow/crdt/README.md) | Conflict-free Replicated Data Types (CRDTs) for distributed systems. Provides eight composable CRDT primitives plus a vector-clock and a sync manager that coor… | +| [`@suaveplan/fsm`](./foundation/flow/fsm/README.md) | Typed, generic finite state machine (FSM) for TypeScript. Ships a synchronous-by-default interpreter with guard predicates, ordered transition actions, context… | +| [`@suaveplan/idempotency`](./foundation/flow/idempotency/README.md) | Idempotency key guard and deduplication for async operations. The package provides a complete `pending → completed \| failed` state machine, three store backend… | +| [`@suaveplan/job-scheduler`](./foundation/flow/job-scheduler/README.md) | Universal in-process job scheduler with cron + queued runs, retries, timeouts, concurrency control, and OpenTelemetry observability. Built on `@suaveplan/cron`… | +| [`@suaveplan/queue`](./foundation/flow/queue/README.md) | Enterprise-grade queue management: memory/priority/delayed queues, concurrent workers with retry and dead-letter forwarding, job state machines, and OTel instr… | +| [`@suaveplan/queue-distribution`](./foundation/flow/queue-distribution/README.md) | Worker-pool distribution layer: load-balancing strategies, worker pool management, manager with retry and health checks, in-process `LocalWorker`. Transport-ag… | +| [`@suaveplan/queue-distribution-http`](./foundation/flow/queue-distribution-http/README.md) | HTTP transport plugin for `@suaveplan/queue-distribution`. Ships `HttpWorkerCommunicator` (a fetch-backed `WorkerCommunicator` with a Zod-validated wire envelo… | +| [`@suaveplan/queue-distribution-worker-thread`](./foundation/flow/queue-distribution-worker-thread/README.md) | Web-Worker / Node `worker_threads` transport plugin for `@suaveplan/queue-distribution`. Ships `WorkerThreadCommunicator` (a `ThreadWorkerLike`-based message b… | +| [`@suaveplan/rate-limiter`](./foundation/flow/rate-limiter/README.md) | Enterprise rate limiter with three algorithms, rule-based routing, tenant multipliers, pluggable storage, and OTel instrumentation. | +| [`@suaveplan/retry`](./foundation/flow/retry/README.md) | Retry strategies and circuit-breaker for async operations. The package provides constant, linear, and exponential backoff with four jitter modes (full, equal,… | +| [`@suaveplan/rules`](./foundation/flow/rules/README.md) | Universal rule engine + validation system. Comprehensive `RuleEngine` with async evaluation, depth limit, AbortSignal, plugin registration; fluent `RuleBuilder… | +| [`@suaveplan/rules-hono`](./foundation/flow/rules-hono/README.md) | Hono middleware wrapping `@suaveplan/rules`. Six middleware factories — `ruleMiddleware`, `validationMiddleware`, `accessControl`, `responseValidation`, `rateL… | +| [`@suaveplan/streams`](./foundation/flow/streams/README.md) | WHATWG-Streams-based primitives: backpressure-first transforms, zero-copy `Uint8Array` operations, `AbortSignal` integration end-to-end, structured errors, OTe… | +| [`@suaveplan/streams-chunk-queue`](./foundation/flow/streams-chunk-queue/README.md) | Universal out-of-order chunk reconstitution. Accepts chunks for a file in any order and exposes a sequential `ReadableStream` consumer surface, com… | +| [`@suaveplan/streams-metadata`](./foundation/flow/streams-metadata/README.md) | Universal stream transforms that detect MIME type and extract EXIF/IPTC/XMP image metadata from buffered `Uint8Array` payloads. Three composable transforms (`M… | +| [`@suaveplan/undo`](./foundation/flow/undo/README.md) | Enterprise-grade undo/redo engine with branching history, async commands, history compression, selective undo, and command merging. Built for collaborative edi… | +| [`@suaveplan/workflow`](./foundation/flow/workflow/README.md) | Workflow and pipeline orchestration: sequential and parallel step execution, conditional branching with guard functions, retry strategies, timeouts, saga-patte… | + +#### `random` + +Pseudo-random generators, noise functions, and deterministic sequences. + +| Package | Description | +|---|---| +| [`@suaveplan/noise`](./foundation/random/noise/README.md) | Seeded spatial noise fields for procedural content generation. Provides six field types — Perlin, Simplex (2D/3D/4D), Value, Worley/cellular (F1/F2/F2-F1 modes… | +| [`@suaveplan/pseudo-random`](./foundation/random/pseudo-random/README.md) | Deterministic, seeded pseudo-random number generators (PRNGs) conforming to the `Rng` interface from `@suaveplan/types`. Ships four algorithms — Mulberry32, SF… | +| [`@suaveplan/random`](./foundation/random/random/README.md) | High-level cryptographically secure randomness for application use. This is the everyday random package — it wraps the CSPRNG with ergonomic helpers for every… | + +#### `timing` + +Cron, stopwatches, throttling, debouncing, and scheduling. + +| Package | Description | +|---|---| +| [`@suaveplan/cron`](./foundation/timing/cron/README.md) | Universal cron expression parser, next-fire calculator with timezone + DST awareness, and an opt-in lightweight in-process scheduler. Zero external cron depend… | +| [`@suaveplan/datetime`](./foundation/timing/datetime/README.md) | Timezone-aware date/time utilities covering the most common application-layer date operations that the native `Date` API leaves unaddressed. The package provid… | +| [`@suaveplan/timing`](./foundation/timing/timing/README.md) | Timing and scheduling utilities for application-layer time management. The package covers measurement (stopwatch with lap recording), rate control (throttle an… | + +### `gaming` + +Game engines, entity-component systems, and simulation libraries. + +#### `games` + +Game controllers, entity-component systems, and game-server logic. + +| Package | Description | +|---|---| +| [`@suaveplan/controller`](./gaming/games/controller/README.md) | Universal input controller foundation. Ships the unified `ControllerInput` shape (37 normalised fields in `[0, 255]`), `BaseController` abstract base with inje… | +| [`@suaveplan/ecs`](./gaming/games/ecs/README.md) | Archetype-based Entity Component System with `Uint32`-backed bitset queries, phase-ordered system scheduling, entity-ID recycling, Zod-validated component sche… | +| [`@suaveplan/game-server`](./gaming/games/game-server/README.md) | Universal game-server framework. Migrated from `@suaveplan/game-server` on the reference branch `claude/review-game-engine-arch-Kaykr` (main repo `packages/uni… | + +### `geospatial` + +Geospatial data, mapping, planetary coordinates, and logistics utilities. + +#### `geo` + +Geospatial coordinates, planetary data, and solar-system modelling. + +| Package | Description | +|---|---| +| [`@suaveplan/geo`](./geospatial/geo/geo/README.md) | Abstract spherical and ellipsoidal geometry — pure math with no planet-specific constants. Every operation that needs a body's shape takes an explicit `Ellipso… | +| [`@suaveplan/geo-earth`](./geospatial/geo/geo-earth/README.md) | Earth configuration and legacy geo utilities. | +| [`@suaveplan/geo-planet`](./geospatial/geo/geo-planet/README.md) | Configurable planet surface geometry from `PlanetConfig` — ellipsoid, atmosphere, satellites, and orbital elements. | +| [`@suaveplan/solar-system`](./geospatial/geo/solar-system/README.md) | Solar system provider with astronomy engine. | +| [`@suaveplan/stars`](./geospatial/geo/stars/README.md) | Star catalog provider. | +| [`@suaveplan/tides`](./geospatial/geo/tides/README.md) | Tidal prediction providers. | +| [`@suaveplan/universe`](./geospatial/geo/universe/README.md) | Observer model, coordinate frames, wire protocol, and provider registry. | + +#### `logistics` + +Port data and logistics primitives. + +| Package | Description | +|---|---| +| [`@suaveplan/ports`](./geospatial/logistics/ports/README.md) | Global port database with shipping-lane routing, ETA estimation, and UN/LOCODE port lookups for sea ports, airports, and rail terminals. | + +### `identity` + +Authentication, authorization, identity resolution, and credential management. + +#### `auth` + +Authentication providers, JWT, WebAuthn, OAuth, and session resolution. + +| Package | Description | +|---|---| +| [`@suaveplan/auth`](./identity/auth/auth/README.md) | Provider-agnostic authentication library for Suaveplan. Ships JWT token lifecycle, API key management, session management, and framework-agnostic middleware —… | +| [`@suaveplan/better-auth-surrealdb`](./identity/auth/better-auth-surrealdb/README.md) | Better-Auth Adapter for SurrealDB v3 — bundles the canonical 17-table SurrealQL schema, compiles Better-Auth `Where[]` filters to parameterised SurrealQL, auto… | +| [`@suaveplan/jwt-tenant`](./identity/auth/jwt-tenant/README.md) | JWT-based multi-tenant token issuance and verification for Suaveplan. Ships an Ed25519 / ECDSA-P256 signing pipeline, in-memory JWKS store with rotation and ex… | +| [`@suaveplan/macos-keychain`](./identity/auth/macos-keychain/README.md) | macOS Keychain bridge for generic-password credentials. Wraps the system `/usr/bin/security` CLI behind a strongly-typed CRUD surface with typed errors, AbortS… | +| [`@suaveplan/oauth-client`](./identity/auth/oauth-client/README.md) | Universal OAuth 2.0 / OIDC client for Node.js, browsers, Bun, Deno, and edge runtimes. | +| [`@suaveplan/permissions`](./identity/auth/permissions/README.md) | Full RBAC/ABAC permissions engine for Suaveplan. Ships role management, policy evaluation, CASL-inspired ability builder, TTL permission cache, condition evalu… | +| [`@suaveplan/webauthn`](./identity/auth/webauthn/README.md) | W3C WebAuthn Level 3 client + parser + verifier for Suaveplan. Browser-tier registration / authentication entry points sit on the package root; framework-agnos… | + +### `localization` + +Internationalization, localization, locale detection, and translation infrastructure. + +#### `i18n` + +Internationalization core, backends, detectors, and locale resolution. + +| Package | Description | +|---|---| +| [`@suaveplan/i18n`](./localization/i18n/i18n/README.md) | Slim integration core for the i18n family. After the Wave 6 modular split, this package owns the `MessageCatalog`, the `createI18n` / `I18nInstance` plugin slo… | +| [`@suaveplan/i18n-backend-chained`](./localization/i18n/i18n-backend-chained/README.md) | Universal chained backend orchestrator for the `@suaveplan/i18n` family. Composes N backends into a single `Backend` with read-fallthrough on `BACKEND_LOCALE_N… | +| [`@suaveplan/i18n-backend-fs-multifile`](./localization/i18n/i18n-backend-fs-multifile/README.md) | Server-tier multi-file Node fs/promises translation backend for the @suaveplan/i18n family. Reads //. (nested), /.. (flat), or a caller-supplied glob pattern. JSON built-in; YAML and JSON5 auto-detected via dynamic import. Optional fs.watch loop emits loaded events through the catalog event bus. AbortSignal cancellation, OpenTelemetry instrumentation under i18n.backend.fs_multifile.*. Server-only — uses node:fs/promises; browser consumers should use @suaveplan/i18n-backend-http or @suaveplan/i18n-backend-storage. | +| [`@suaveplan/i18n-backend-http`](./localization/i18n/i18n-backend-http/README.md) | Universal translation backend for the `@suaveplan/i18n` family, backed by an injectable `fetch`. Read-only by design: maps HTTP 404 to `BACKEND_LOCALE_NOT_AVAI… | +| [`@suaveplan/i18n-backend-memory`](./localization/i18n/i18n-backend-memory/README.md) | Universal in-memory translation backend for the `@suaveplan/i18n` family. Backed by `Map>` plus a modification ledger… | +| [`@suaveplan/i18n-backend-storage`](./localization/i18n/i18n-backend-storage/README.md) | Universal translation backend for the `@suaveplan/i18n` family, backed by any `AbstractStorage` implementation from `@suaveplan/storage`. Implements the full `… | +| [`@suaveplan/i18n-detector`](./localization/i18n/i18n-detector/README.md) | Universal locale-detection chain for the `@suaveplan/i18n` family. Ships the chain orchestrator, the BCP-47 default negotiator, the `getTextDirection` / `isRtl… | +| [`@suaveplan/i18n-formatter-collator`](./localization/i18n/i18n-formatter-collator/README.md) | Wrapper around `Intl.Collator` for the `@suaveplan/i18n` family — locale-aware string comparison and sorting (sensitivity, numeric-aware natural sort, case-fir… | +| [`@suaveplan/i18n-formatter-currency`](./localization/i18n/i18n-formatter-currency/README.md) | Locale-aware currency formatting backed by `Intl.NumberFormat` with `style: "currency"`. Wave 3 of the 14-package i18n modular split. Provides both a class (`C… | +| [`@suaveplan/i18n-formatter-date`](./localization/i18n/i18n-formatter-date/README.md) | Wrapper around `Intl.DateTimeFormat` for the `@suaveplan/i18n` family — 8-preset table (short/medium/long/full × date+time/time-only/date-only), range renderin… | +| [`@suaveplan/i18n-formatter-display-name`](./localization/i18n/i18n-formatter-display-name/README.md) | Wrapper around `Intl.DisplayNames` for the `@suaveplan/i18n` family — locale-aware language, region, script, currency, and calendar display names. Universal le… | +| [`@suaveplan/i18n-formatter-list`](./localization/i18n/i18n-formatter-list/README.md) | Locale-aware list joining backed by `Intl.ListFormat`. Wave 3 of the 14-package i18n modular split. Provides both a class (`ListFormatter`) and a standalone he… | +| [`@suaveplan/i18n-formatter-number`](./localization/i18n/i18n-formatter-number/README.md) | Locale-aware number formatting backed by `Intl.NumberFormat`. Wave 3 of the 14-package i18n modular split. Provides both a class (`NumberFormatter`) and a stan… | +| [`@suaveplan/i18n-formatter-relative-time`](./localization/i18n/i18n-formatter-relative-time/README.md) | Locale-aware relative-time formatting backed by `Intl.RelativeTimeFormat`. Wave 3 of the 14-package i18n modular split. Provides both a class (`RelativeTimeFor… | +| [`@suaveplan/i18n-formatter-segmenter`](./localization/i18n/i18n-formatter-segmenter/README.md) | Wrapper around `Intl.Segmenter` for the `@suaveplan/i18n` family — locale-aware text segmentation by grapheme, word, or sentence. Compound emoji count as a sin… | +| [`@suaveplan/i18n-icu-parser`](./localization/i18n/i18n-icu-parser/README.md) | ICU MessageFormat parser, `{{var}}` interpolation engine, and 9-language CLDR pluralization for the `@suaveplan/i18n` family. Universal leaf package — depends… | +| [`@suaveplan/i18n-shared`](./localization/i18n/i18n-shared/README.md) | Shared runtime atoms for the entire `@suaveplan/i18n*` package family — locale constants, BCP-47 normalisation map, RTL set, locale descriptors, interpolation… | +| [`@suaveplan/locale-data`](./localization/i18n/locale-data/README.md) | Static ISO 3166-1 country data and ISO 639-1 language data with typed lookup functions, OTel instrumentation, and Zod schemas. | +| [`@suaveplan/react-i18n`](./localization/i18n/react-i18n/README.md) | React bindings for `@suaveplan/i18n`. Ships the ``, twelve hooks, four headless components, the class-component HOC, the nine built-in loc… | + +### `media` + +Audio, video, image, and font processing libraries. + +#### `audio` + +Audio processing, playback, analysis, and effect plugins. + +| Package | Description | +|---|---| +| [`@suaveplan/audio-analysis-beat`](./media/audio/audio-analysis-beat/README.md) | Universal beat, tempo, and onset detection plugin for the `@suaveplan/audio-*` family. Detects BPM, beat locations, and onset times from `AudioDocument` stream… | +| [`@suaveplan/audio-analysis-loudness`](./media/audio/audio-analysis-loudness/README.md) | Universal ITU-R BS.1770-4 loudness analyser. Drop-in `AnalysisOp` plugin for the `@suaveplan/audio-*` family. | +| [`@suaveplan/audio-analysis-pitch`](./media/audio/audio-analysis-pitch/README.md) | Universal pitch, key, and chord detection Analysis Op plugins for the `@suaveplan/audio-*` family. Three detectors: | +| [`@suaveplan/audio-analysis-spectrum`](./media/audio/audio-analysis-spectrum/README.md) | Universal spectral analysis for the Suaveplan audio stack: real FFT, Hann/Hamming/Blackman windows, mel filterbank, DCT-II, and three high-level analyzers — `S… | +| [`@suaveplan/audio-cli`](./media/audio/audio-cli/README.md) | Server-tier `audio` command-line tool. Thin shell over `@suaveplan/audio-core`, `@suaveplan/audio-codecs`, and `@suaveplan/audio-engine-server`: every audio tr… | +| [`@suaveplan/audio-codec-ffmpeg-native`](./media/audio/audio-codec-ffmpeg-native/README.md) | Server-tier `AudioCodec` plugin for `@suaveplan/audio-codecs` that shells out to the system `ffmpeg` binary via `fluent-ffmpeg` and streams audio through the s… | +| [`@suaveplan/audio-codec-ffmpeg-wasm`](./media/audio/audio-codec-ffmpeg-wasm/README.md) | Browser-tier `AudioCodec` plugin for `@suaveplan/audio-codecs` backed by `@ffmpeg/ffmpeg` running inside a dedicated Web Worker. Decodes and encodes `wav`, `mp… | +| [`@suaveplan/audio-codecs`](./media/audio/audio-codecs/README.md) | Universal audio codec registry: decode/encode plugin loader with magic-byte format detection, progressive streaming decode, native WAV/AIFF/CAF codecs, and laz… | +| [`@suaveplan/audio-controllers`](./media/audio/audio-controllers/README.md) | Universal MIDI hardware controller plugins. Built on `@suaveplan/audio-core`, `@suaveplan/audio-transport`, `@suaveplan/events`, `@suaveplan/fsm`, and `@suavep… | +| [`@suaveplan/audio-core`](./media/audio/audio-core/README.md) | Universal audio data model and processing primitives. Provides a paged `AudioDocument`, a non-destructive `PlanEngine`, a block-level `ProcessPipeline`, and a… | +| [`@suaveplan/audio-decode-wav`](./media/audio/audio-decode-wav/README.md) | Universal WAV decoder wrapper over the upstream `@audio/decode-wav` library. Exposes a stable, OTel-instrumented, AbortSignal-honouring contract over a frozen,… | +| [`@suaveplan/audio-engine-browser`](./media/audio/audio-engine-browser/README.md) | Browser-tier `TimelineAdapter` implementation for the `@suaveplan/audio-*` family. Hosts Web Audio rendering, `AudioWorklet` loading, and the `AudioFxPlugin.cr… | +| [`@suaveplan/audio-engine-server`](./media/audio/audio-engine-server/README.md) | Server-tier audio I/O layer for the `@suaveplan/audio-*` family. Provides the thinnest possible bridge between universal `AudioDocument` primitives and a Node.… | +| [`@suaveplan/audio-fingerprint`](./media/audio/audio-fingerprint/README.md) | High-accuracy audio fingerprinting service. The package is dual-runtime: a Python FastAPI backend (`src/fingerprint.py` + `src/api/app.py`) implements chromagr… | +| [`@suaveplan/audio-metadata`](./media/audio/audio-metadata/README.md) | Universal audio metadata extractor that parses ID3v1/v2, MP4/M4A atoms, FLAC Vorbis comments, Ogg Vorbis, WAV RIFF, and AIFF/AIFC containers, returning a norma… | +| [`@suaveplan/audio-sprite-packer`](./media/audio/audio-sprite-packer/README.md) | Universal audio sprite packer with injectable adapter, Zod-validated boundaries, and OpenTelemetry instrumentation. Zero browser or Node.js dependencies. | +| [`@suaveplan/audio-sprite-player`](./media/audio/audio-sprite-player/README.md) | Universal audio sprite playback engine. Consumes manifests produced by `@suaveplan/audio-sprite-packer`, validates them, schedules voices, runs voice-stealing… | +| [`@suaveplan/audio-timeline`](./media/audio/audio-timeline/README.md) | Headless DAW timeline engine with multi-track arrangements, clips, playback, loop regions, selection, zoom, per-track mixer state, undo/redo, and a pluggable `… | +| [`@suaveplan/audio-transport`](./media/audio/audio-transport/README.md) | Universal musical clock and transport: sample-accurate scheduling with PPQ, BPM automation, swing, time signatures, and loop regions. Zero browser or Node depe… | +| [`@suaveplan/control-surface-schema`](./media/audio/control-surface-schema/README.md) | Universal canonical schema for DAW-style control surfaces. Owns the `ControlSurface` root document, the `ControlNode = Group \| Control` discriminated tree, the… | +| [`@suaveplan/midi`](./media/audio/midi/README.md) | Universal MIDI primitives for the Suaveplan platform. Owns the canonical types, byte parsers, message constructors, control-surface dispatchers (NRPN, RPN, 14-… | +| [`@suaveplan/third-party-elevenlabs`](./media/audio/third-party-elevenlabs/README.md) | | +| [`@suaveplan/voice`](./media/audio/voice/README.md) | Provider-agnostic voice core for Suaveplan. Defines the abstract interfaces, shared types, Zod schemas, and structured error hierarchy that every voice provide… | +| [`@suaveplan/voice-elevenlabs`](./media/audio/voice-elevenlabs/README.md) | ElevenLabs domain adapter for the `@suaveplan/voice` interface family. | + +#### `audio-fx` + +Real-time audio effects and DSP plugins. + +| Package | Description | +|---|---| +| [`@suaveplan/audio-fx-plugin-audio-analyzer`](./media/audio-fx/audio-fx-plugin-audio-analyzer/README.md) | audio-analyzer plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-audio-player`](./media/audio-fx/audio-fx-plugin-audio-player/README.md) | audio-player plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-auto-filter`](./media/audio-fx/audio-fx-plugin-auto-filter/README.md) | auto-filter plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-base`](./media/audio-fx/audio-fx-plugin-base/README.md) | Foundation for the `@suaveplan/audio-fx-plugin-*` family. Universal (browser / server / offline / worklet identical). Zero `@suaveplan/audio-fx-plugin-*` deps… | +| [`@suaveplan/audio-fx-plugin-chorus`](./media/audio-fx/audio-fx-plugin-chorus/README.md) | chorus plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-compressor`](./media/audio-fx/audio-fx-plugin-compressor/README.md) | compressor plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-delay`](./media/audio-fx/audio-fx-plugin-delay/README.md) | delay plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-distortion`](./media/audio-fx/audio-fx-plugin-distortion/README.md) | distortion plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-eq`](./media/audio-fx/audio-fx-plugin-eq/README.md) | Parametric / shelving / high-pass / low-pass equaliser for the `@suaveplan/audio-fx-plugin-*` family. Multi-band biquad implementation, sample-accurate paramet… | +| [`@suaveplan/audio-fx-plugin-filter`](./media/audio-fx/audio-fx-plugin-filter/README.md) | filter plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-flanger`](./media/audio-fx/audio-fx-plugin-flanger/README.md) | flanger plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-game-audio`](./media/audio-fx/audio-fx-plugin-game-audio/README.md) | game-audio plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-gate`](./media/audio-fx/audio-fx-plugin-gate/README.md) | gate plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-glados`](./media/audio-fx/audio-fx-plugin-glados/README.md) | glados plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-limiter`](./media/audio-fx/audio-fx-plugin-limiter/README.md) | limiter plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-microphone`](./media/audio-fx/audio-fx-plugin-microphone/README.md) | microphone plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-mixer`](./media/audio-fx/audio-fx-plugin-mixer/README.md) | mixer plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-phaser`](./media/audio-fx/audio-fx-plugin-phaser/README.md) | phaser plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-pitch-shifter`](./media/audio-fx/audio-fx-plugin-pitch-shifter/README.md) | pitch-shifter plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-reverb`](./media/audio-fx/audio-fx-plugin-reverb/README.md) | reverb plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-sampler`](./media/audio-fx/audio-fx-plugin-sampler/README.md) | sampler plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-spatial`](./media/audio-fx/audio-fx-plugin-spatial/README.md) | spatial plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-spessasynth`](./media/audio-fx/audio-fx-plugin-spessasynth/README.md) | SF2/SF3 SoundFont synthesizer plugin for the `@suaveplan/audio-fx-plugin-*` family. Wraps the MIT-licensed SpessaSynth engine as a standard `AudioFxPlugin`, so… | +| [`@suaveplan/audio-fx-plugin-synthesizer`](./media/audio-fx/audio-fx-plugin-synthesizer/README.md) | synthesizer plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-tremolo`](./media/audio-fx/audio-fx-plugin-tremolo/README.md) | tremolo plugin for the @suaveplan/audio-fx-plugin-* family. | +| [`@suaveplan/audio-fx-plugin-widener`](./media/audio-fx/audio-fx-plugin-widener/README.md) | widener plugin for the @suaveplan/audio-fx-plugin-* family. | + +#### `audio-ir` + +Impulse-response capture, loading, and room-acoustic plugins. + +| Package | Description | +|---|---| +| [`@suaveplan/audio-ir-core`](./media/audio-ir/audio-ir-core/README.md) | Foundation contract for the `@suaveplan/audio-ir-*` family. Universal; zero `@suaveplan/audio-*` runtime deps. Every sibling package (`audio-ir-loader`, `audio… | +| [`@suaveplan/audio-ir-loader`](./media/audio-ir/audio-ir-loader/README.md) | Pipeline package for the `@suaveplan/audio-ir-*` family. Composes `IrRegistry` (from `@suaveplan/audio-ir-core`), a `StorageUriResolver` (from `@suaveplan/stor… | +| [`@suaveplan/audio-ir-room-plugin-club`](./media/audio-ir/audio-ir-room-plugin-club/README.md) | Original audio-ir content package. Ships two bundled room impulse responses (`club1.wav`, `club2.wav`) wired through the `@suaveplan/audio-ir-*` family. | +| [`@suaveplan/audio-ir-room-plugin-pool`](./media/audio-ir/audio-ir-room-plugin-pool/README.md) | Original audio-ir content package. Ships a single `room`-family impulse response — `pool-outdoor-swimming-pool` — sourced from the outdoor-swimming-pool captur… | + +#### `fonts` + +Font packing, compression, subsetting, and conversion tools. + +| Package | Description | +|---|---| +| [`@suaveplan/font-compress`](./media/fonts/font-compress/README.md) | BTF (Binary TypeFace) binary packing and unpacking. Converts `TypefaceFont` (typeface.js JSON format) to a compact `Uint8Array` using dictionary-based integer… | +| [`@suaveplan/font-convert`](./media/fonts/font-convert/README.md) | Converts TTF/OTF/WOFF/WOFF2 font files to the typeface.js JSON format used by Three.js `FontLoader`. Also defines the canonical `TypefaceFont`, `TypefaceGlyph`… | +| [`@suaveplan/font-decompress`](./media/fonts/font-decompress/README.md) | BTF (Binary TypeFace) binary unpacking. Reverses `@suaveplan/font-compress`'s `BinaryFontPacker` output into a typeface.js JSON shape ready for Three.js / R3F… | +| [`@suaveplan/font-subset`](./media/fonts/font-subset/README.md) | Font subsetting and compression library with a codec-agnostic adapter interface. Supports Unicode range subsetting, WOFF2/WOFF/OTF/TTF output, OpenType feature… | + +#### `image` + +Image compression, colour conversion, EXIF handling, and optimisation. + +| Package | Description | +|---|---| +| [`@suaveplan/caddy-imgproxy`](./media/image/caddy-imgproxy/README.md) | Universal TypeScript port of the Caddy imgproxy URL rewriter. Parses the compact `/u/.` grammar, resolves aspect-ra… | +| [`@suaveplan/colour-convert-adapt`](./media/image/colour-convert-adapt/README.md) | Bradford chromatic adaptation for XYZ colour coordinates. Chromatic adaptation adjusts a colour's appearance so that it looks the same under different light so… | +| [`@suaveplan/colour-convert-cieluv`](./media/image/colour-convert-cieluv/README.md) | CIELUV, xyY, LMS, and Bradford chromatic adaptation conversions. This plugin provides colour-space transforms between RGB, CIELUV, xyY, and LMS cone-response s… | +| [`@suaveplan/colour-convert-cmyk`](./media/image/colour-convert-cmyk/README.md) | Bidirectional conversion between RGB and CMYK colour spaces using the standard Euclidean algorithm with black generation. CMYK is the subtractive model used in… | +| [`@suaveplan/colour-convert-hsluv`](./media/image/colour-convert-hsluv/README.md) | HSLuv perceptually-uniform colour space with gamut-mapped ray intersection for sRGB. This plugin provides bidirectional RGB↔HSLuv/HPLuv conversions and uniform… | +| [`@suaveplan/colour-filter-cct`](./media/image/colour-filter-cct/README.md) | Correlated Colour Temperature (CCT) conversions using the McCamy formula and black-body RGB approximation. Convert any RGB colour to its approximate colour tem… | +| [`@suaveplan/colour-filter-cmc`](./media/image/colour-filter-cmc/README.md) | CMC l:c Delta-E colour difference metric with hue-dependent chroma scaling and low-luminance branch handling. This plugin computes perceptual distance between… | +| [`@suaveplan/colour-filter-greyscale`](./media/image/colour-filter-greyscale/README.md) | Converts any RGB colour to its perceptual greyscale equivalent using the ITU-R BT.709 luminance coefficients. Unlike simple channel averaging, this formula wei… | +| [`@suaveplan/colour-filter-sepia`](./media/image/colour-filter-sepia/README.md) | Applies a photographic sepia tone filter to RGB colours using the standard W3C CSS Filters 3×3 matrix. This plugin converts any colour into a warm brownish ton… | +| [`@suaveplan/colours`](./media/image/colours/README.md) | Universal colour manipulation library: parsing, conversion, analysis, mixing, blending, and palette generation. Parses hex (3/4/6/8 digit), CSS `rgb()`, `hsl()… | +| [`@suaveplan/compress-image`](./media/image/compress-image/README.md) | Runtime-agnostic image compression utilities with pluggable adapters for Node.js (Sharp) and testing (MemoryAdapter). Supports resize, quality reduction, forma… | +| [`@suaveplan/emblem-solver`](./media/image/emblem-solver/README.md) | Minimal-rectangle SVG converter for pixelated sprite emblems. | +| [`@suaveplan/exif`](./media/image/exif/README.md) | Dependency-free, runtime-agnostic EXIF/XMP/IPTC metadata reader, writer, and stripper for JPEG and PNG images. Parses JPEG segment chains to locate and decode… | +| [`@suaveplan/image`](./media/image/image/README.md) | Universal image metadata extraction, format detection, resize math, crop validation, and transform pipeline planning. Zero browser or Node dependencies — runs… | +| [`@suaveplan/image-quantisation`](./media/image/image-quantisation/README.md) | Image complexity analysis and adaptive colour quantisation with pool detection, spatial-aware anti-aliasing cleanup, and multiple quantisation algorithms. Desi… | + +#### `video` + +Video encoding, decoding, and thumbnail generation. + +| Package | Description | +|---|---| +| [`@suaveplan/video`](./media/video/video/README.md) | Universal video metadata extraction, magic-byte format detection, resolution math, transform-pipeline planning, and a fluent pipeline builder. Zero browser-onl… | +| [`@suaveplan/video-thumbnails`](./media/video/video-thumbnails/README.md) | Video thumbnail extraction and sprite-sheet generation backed by an injectable `FfmpegRunner`. The default runner — `FluentFfmpegRunner` — wraps `fluent-ffmpeg… | + +### `money` + +Payments, currencies, cryptocurrency, and financial primitives. + +#### `finance` + +Currency conversion, cryptocurrency utilities, and exchange-rate providers. + +| Package | Description | +|---|---| +| [`@suaveplan/cryptocurrency`](./money/finance/cryptocurrency/README.md) | Universal cryptocurrency utilities for wallet address validation, unit conversion, chain registry, gas estimation, ERC-20 token registry, calldata / function-s… | +| [`@suaveplan/currency`](./money/finance/currency/README.md) | Universal currency conversion engine — pluggable `CurrencyProvider` interface, TTL-bounded `RateCache` with direct / inverse / triangulated lookup, primary + f… | +| [`@suaveplan/currency-provider-binance`](./money/finance/currency-provider-binance/README.md) | Binance public-ticker crypto-rates provider for `@suaveplan/currency`. Sibling package in the foundation-with-sibling-plugins shape: implements the `CurrencyPr… | +| [`@suaveplan/currency-provider-coingecko`](./money/finance/currency-provider-coingecko/README.md) | Universal CoinGecko sibling for `@suaveplan/currency-providers`. Implements the `CurrencyProvider` contract from `@suaveplan/currency` against the public `/sim… | +| [`@suaveplan/currency-provider-coinmarketcap`](./money/finance/currency-provider-coinmarketcap/README.md) | CoinMarketCap crypto-rates sibling provider for `@suaveplan/currency`. One of the nine `@suaveplan/currency-provider-` sibling packages spun out of the 2… | +| [`@suaveplan/currency-provider-cryptocompare`](./money/finance/currency-provider-cryptocompare/README.md) | Universal CryptoCompare crypto-rates provider for `@suaveplan/currency`. Sibling provider package on top of the slim `@suaveplan/currency-providers` core (`htt… | +| [`@suaveplan/currency-provider-ecb`](./money/finance/currency-provider-ecb/README.md) | Universal `@suaveplan/currency` rate provider for the European Central Bank's daily exchange-rates XML feed. Free, no API key required. Built on the slim `@sua… | +| [`@suaveplan/currency-provider-fixer`](./money/finance/currency-provider-fixer/README.md) | Fixer.io fiat-rates sibling provider for the slim `@suaveplan/currency-providers` core. Implements the `CurrencyProvider` contract from `@suaveplan/currency`,… | +| [`@suaveplan/currency-provider-kraken`](./money/finance/currency-provider-kraken/README.md) | Universal Kraken public-ticker rate provider for `@suaveplan/currency`. Wraps Kraken's free, no-API-key `/0/public/Ticker` endpoint into a `CurrencyProvider` s… | +| [`@suaveplan/currency-provider-open-exchange-rates`](./money/finance/currency-provider-open-exchange-rates/README.md) | Universal `@suaveplan/currency` provider for openexchangerates.org. Routes `/latest.json` through the slim-core `httpRequest()` helper, validates the upstream… | +| [`@suaveplan/currency-provider-virtual`](./money/finance/currency-provider-virtual/README.md) | In-memory, programmable virtual / game currency provider for `@suaveplan/currency`. Sibling of the `@suaveplan/currency-providers` slim plugin core. No HTTP, n… | +| [`@suaveplan/currency-providers`](./money/finance/currency-providers/README.md) | Slim plugin core for `@suaveplan/currency` rate providers. Ships the `CurrencyProviderRegistry` (name-keyed lookup), the `defineCurrencyProvider` factory, the… | +| [`@suaveplan/money`](./money/finance/money/README.md) | Universal precise currency and money arithmetic using integer minor-unit representation. All operations use `bigint` so consumers never hit floating-point roun… | + +#### `payment` + +Payment intent lifecycle, provider adapters, and fraud detection. + +| Package | Description | +|---|---| +| [`@suaveplan/payment`](./money/payment/payment/README.md) | Universal payment intent lifecycle, webhook signature verification, receipt generation, fraud scoring, refund tracking, tax calculation, retry orchestration, r… | +| [`@suaveplan/payment-provider-adyen`](./money/payment/payment-provider-adyen/README.md) | Universal **Adyen Checkout API v71 adapter** for `@suaveplan/payment`. Implements the `PaymentProvider` interface via the slim `@suaveplan/payment-providers` c… | +| [`@suaveplan/payment-provider-mollie`](./money/payment/payment-provider-mollie/README.md) | Universal Mollie Payments API v2 adapter for `@suaveplan/payment`. Sibling provider package on the slim `@suaveplan/payment-providers` core: implements `Paymen… | +| [`@suaveplan/payment-provider-paypal`](./money/payment/payment-provider-paypal/README.md) | PayPal sibling adapter for the slim `@suaveplan/payment-providers` foundation. Ships `PayPalProvider` — a `PaymentProvider` implementation against the PayPal O… | +| [`@suaveplan/payment-provider-square`](./money/payment/payment-provider-square/README.md) | Universal Square Payments API adapter for `@suaveplan/payment`. Ships the `SquareProvider` class (implements the structural `PaymentProvider` contract with lit… | +| [`@suaveplan/payment-provider-stripe`](./money/payment/payment-provider-stripe/README.md) | Universal Stripe adapter for `@suaveplan/payment`. Implements `PaymentProvider` against the Stripe REST API using the slim `@suaveplan/payment-providers` found… | +| [`@suaveplan/payment-providers`](./money/payment/payment-providers/README.md) | Universal **foundation** for the `@suaveplan/payment-provider-*` sibling-package family. This package ships only the shared abstractions every concrete adapter… | + +### `networking` + +Distributed networking, event buses, drive mesh, and network discovery. + +#### `drive` + +Virtual filesystem, mesh networking, and chunk-addressed storage plugins. + +| Package | Description | +|---|---| +| [`@suaveplan/drive`](./networking/drive/drive/README.md) | Modular virtual filesystem core for Suaveplan. File-level operations over `AbstractStorage` with a plugin slot for middleware, chunking, encryption, and P2P me… | +| [`@suaveplan/drive-mesh`](./networking/drive/drive-mesh/README.md) | P2P mesh orchestrator over the drive chunks plugin. Consumes `ChunkSource` (from `@suaveplan/drive-plugin-chunks`) and one or more `DriveTransport` implementat… | +| [`@suaveplan/drive-mesh-protocol`](./networking/drive/drive-mesh-protocol/README.md) | Wire protocol for chunk discovery, request, and delivery across the mesh. Three envelope shapes (`cd:request`, `cd:advertise`, `cd:response`) with three reques… | +| [`@suaveplan/drive-plugin-cache`](./networking/drive/drive-plugin-cache/README.md) | Read-through cache middleware for `@suaveplan/drive`. Accepts a caller-supplied `AbstractCache` (from `@suaveplan/cache`) and intercepts every `dri… | +| [`@suaveplan/drive-plugin-chunks`](./networking/drive/drive-plugin-chunks/README.md) | Chunk-addressing plugin for `@suaveplan/drive`. Splits files into signed, encrypted chunks using the locked `version 0x0001` binary format, with server-signed… | +| [`@suaveplan/drive-react-sharing`](./networking/drive/drive-react-sharing/README.md) | React-tier UI surface for `@suaveplan/drive-sharing`. Three controlled components plus a real-engine-backed hook. | +| [`@suaveplan/drive-sharing`](./networking/drive/drive-sharing/README.md) | Partitioned drive sharing engine for the Suaveplan ecosystem. Ships envelope encryption with mandatory AAD, per-user key wrapping, partition policies with dete… | +| [`@suaveplan/drive-storage-archive-core`](./networking/drive/drive-storage-archive-core/README.md) | Shared archive-mounting primitives for the Suaveplan drive: magic-byte format sniffing, split-volume sibling resolution, password hook contract, mutation-mode… | +| [`@suaveplan/drive-storage-zip`](./networking/drive/drive-storage-zip/README.md) | ZIP archive adapter for `@suaveplan/drive`. Reads and writes standards-compliant zip archives through the structural `DriveStorage` view; supports ZIP64, split… | +| [`@suaveplan/drive-template`](./networking/drive/drive-template/README.md) | Server-signed drive templates for the dehydrated-drive workflow. A `DriveTemplate` describes a drive's full folder structure and per-file metadata; the actual… | +| [`@suaveplan/drive-transport-https`](./networking/drive/drive-transport-https/README.md) | HTTPS-relay-backed `TransportLike` for the Suaveplan drive mesh. Implements long-poll receive, stateless POST send, exponential backoff with e… | +| [`@suaveplan/drive-transport-webrtc`](./networking/drive/drive-transport-webrtc/README.md) | WebRTC datachannel transport for the drive mesh. Implements the canonical `DriveTransport` interface from `@suaveplan/drive-mesh` over a `@suaveplan/drive-webr… | +| [`@suaveplan/drive-uri`](./networking/drive/drive-uri/README.md) | URI plugins (`drive://`, `drive+mesh://`, `drive+template://`) for `@suaveplan/storage-uri`'s `StorageUriResolver`. Wraps a caller-supplied `Drive` instance in… | +| [`@suaveplan/drive-webrtc`](./networking/drive/drive-webrtc/README.md) | Browser-tier WebRTC P2P chunk-distribution plugin for `@suaveplan/drive`. Provides a complete mesh networking stack — signalling client, ICE-aware WebRTC clien… | + +#### `events` + +Typed event bus, event sourcing, metrics, and transport bridges. + +| Package | Description | +|---|---| +| [`@suaveplan/broadcast-channel`](./networking/events/broadcast-channel/README.md) | Typed cross-tab messaging built on the Web `BroadcastChannel` API. Browser-tier package — leader election, tab presence and heartbeats, message-type handler re… | +| [`@suaveplan/event-sourcing`](./networking/events/event-sourcing/README.md) | Event sourcing patterns for Suaveplan: typed aggregate root, in-memory event store with optimistic concurrency, snapshot support, projections, upcasting, and O… | +| [`@suaveplan/events`](./networking/events/events/README.md) | Typed event-bus substrate for Suaveplan. Pub/sub with deterministic FIFO delivery, interceptor API, bounded-queue backpressure, idempotent listeners, Zod-valid… | +| [`@suaveplan/events-metrics`](./networking/events/events-metrics/README.md) | OTel metrics companion for `@suaveplan/events`. Attaches via the public interceptor API to record dispatch totals, listener error counts, and latency histogram… | +| [`@suaveplan/events-otel`](./networking/events/events-otel/README.md) | OpenTelemetry tracing companion for `@suaveplan/events`. Wraps each dispatch in a span, propagates W3C Trace Context, and records listener exceptions as span e… | +| [`@suaveplan/events-schema`](./networking/events/events-schema/README.md) | Runtime schema-validation companion for `@suaveplan/events`. Validates event payloads at dispatch boundaries via Zod schemas with strict/warn/sample modes and… | +| [`@suaveplan/events-transport`](./networking/events/events-transport/README.md) | Cross-context event bridges for `@suaveplan/events`: `MessageChannel` (at-least-once with ack/retry) and `BroadcastChannel` (at-most-once, fan-out) transports… | + +#### `network` + +Mesh networking, WebSocket transports, bootstrap, and discovery protocols. + +| Package | Description | +|---|---| +| [`@suaveplan/network`](./networking/network/network/README.md) | Core network interfaces and runtime for the mesh system. | +| [`@suaveplan/network-bootstrap`](./networking/network/network-bootstrap/README.md) | Pluggable peer-discovery chain, persistent peer cache, and `NetworkPlugin` wrapper for the `@suaveplan/network` mesh. Provides the canonical way for a freshly… | +| [`@suaveplan/network-discovery-crdt`](./networking/network/network-discovery-crdt/README.md) | Browser-tier `DiscoveryStrategy` for `@suaveplan/network-bootstrap`. Wraps an awareness-document CRDT (Yjs *or* Automerge — chosen at construction) and produce… | +| [`@suaveplan/network-discovery-gundb`](./networking/network/network-discovery-gundb/README.md) | Browser-tier `DiscoveryStrategy` for `@suaveplan/network-bootstrap` chains. Wraps a GunDB instance — gossip-over- WebSocket decentralised graph database — and… | +| [`@suaveplan/network-discovery-hybrid`](./networking/network/network-discovery-hybrid/README.md) | Browser-tier multi-strategy DiscoveryStrategy orchestrator: composes any subset of the five Wave-2 sibling strategies (peerjs / crdt / trystero / webtorrent / gundb) into a single HybridDiscoveryManager with priority-based peer selection, per-strategy health tracking, automatic fallback, de-duplicated peer set with PeerSource provenance, and unified lifecycle. Implements the network-bootstrap DiscoveryStrategy contract so it can itself be chained. | +| [`@suaveplan/network-discovery-peerjs`](./networking/network/network-discovery-peerjs/README.md) | Browser-tier `DiscoveryStrategy` for `@suaveplan/network-bootstrap` that wraps a PeerJS signalling-server client + WebRTC `DataConnection`s into a deduped peer… | +| [`@suaveplan/network-discovery-trystero`](./networking/network/network-discovery-trystero/README.md) | Browser-tier `DiscoveryStrategy` for `@suaveplan/network-bootstrap`. Serverless WebRTC peer discovery via Trystero, with four interchangeable transports — BitT… | +| [`@suaveplan/network-discovery-webtorrent`](./networking/network/network-discovery-webtorrent/README.md) | Browser-tier `DiscoveryStrategy` for `@suaveplan/network-bootstrap` chains. Wraps a `p2pt` instance — WebTorrent-tracker-driven WebRTC peer discovery — and exp… | +| [`@suaveplan/network-gundb-server`](./networking/network/network-gundb-server/README.md) | Server-tier GunDB relay daemon. Hosts a Gun relay peer plus standard `/health` / `/ready` / `/live` probes on a single Node `http.Server`. Browser-tier clients… | +| [`@suaveplan/network-libp2p-server`](./networking/network/network-libp2p-server/README.md) | Server-tier libp2p relay daemon paired with `@suaveplan/network-transport-libp2p`. Hosts a libp2p node configured as a bootstrap + circuit-relay-v2 server alon… | +| [`@suaveplan/network-plugin-assignment`](./networking/network/network-plugin-assignment/README.md) | Mesh auto-assignment and load balancing: live `MeshCapacityTracker`, weighted-multi-criteria `AssignmentEngine`, imbalance-detecting `MeshBalancer` planner, an… | +| [`@suaveplan/network-plugin-audit-mesh`](./networking/network/network-plugin-audit-mesh/README.md) | Tamper-evident, cryptographically signed, append-only audit log chain for the Suaveplan mesh. `SignedLog` produces hash-chained `LogEntry` records keyed by mon… | +| [`@suaveplan/network-plugin-auth`](./networking/network/network-plugin-auth/README.md) | Mesh membership authentication and cross-mesh relay authorization. Bridges `@suaveplan/auth` into the mesh: peer join verification, capability-tier-bound token… | +| [`@suaveplan/network-plugin-circuit-breaker`](./networking/network/network-plugin-circuit-breaker/README.md) | Mesh-level circuit breakers: per-path state machine (`CLOSED → OPEN → HALF_OPEN`), registry, half-open probe loop, and relay middleware integration. Fast-fails… | +| [`@suaveplan/network-plugin-content-delivery`](./networking/network/network-plugin-content-delivery/README.md) | Mesh-as-CDN core for the Suaveplan network. `ChunkIndex` maintains a distributed holder map keyed by chunk hash with gossip-style merge over `ChunkAdvertisemen… | +| [`@suaveplan/network-plugin-crypto-messages`](./networking/network/network-plugin-crypto-messages/README.md) | Cryptographic integrity layer for the Suaveplan mesh. Ed25519-backed `MessageSigner` (sign on send, verify against the registry on receive); `SessionTokenAutho… | +| [`@suaveplan/network-plugin-devtools`](./networking/network/network-plugin-devtools/README.md) | Developer-tools plugin for the Suaveplan mesh. Bundles four subsystems behind a single `NetworkPlugin` lifecycle so engineers can inspect, visualise, and profi… | +| [`@suaveplan/network-plugin-failover`](./networking/network/network-plugin-failover/README.md) | Mesh failover plugin: per-peer heartbeat manager, alive→suspect→dead→recovering health monitor, debounced promoter that triggers emergency elections, and a coo… | +| [`@suaveplan/network-plugin-governance`](./networking/network/network-plugin-governance/README.md) | Election engine for the Suaveplan mesh: candidate scoring, reputation tracking, voting, and host transitions. | +| [`@suaveplan/network-plugin-intra-relay`](./networking/network/network-plugin-intra-relay/README.md) | Intra-mesh peer-to-peer relay for the Suaveplan network. When direct WebRTC fails (symmetric NAT, restrictive firewall), `IntraRelayPlugin` routes the message… | +| [`@suaveplan/network-plugin-middleware`](./networking/network/network-plugin-middleware/README.md) | Priority-ordered middleware chain for the Suaveplan mesh. Inbound and outbound message flow each pass through the same five-band pipeline (CRITICAL → HIGH → NO… | +| [`@suaveplan/network-plugin-migration`](./networking/network/network-plugin-migration/README.md) | Peer state migration between meshes: 8-step `MigrationCoordinator`, snapshot serialize/deserialize via `StateTransferProtocol`, graceful-handoff `ForwardingTun… | +| [`@suaveplan/network-plugin-monitor`](./networking/network/network-plugin-monitor/README.md) | Production monitoring + distributed tracing for the Suaveplan mesh. Collects metrics across four categories (node / connection / message / hierarchy), supports… | +| [`@suaveplan/network-plugin-partition`](./networking/network/network-plugin-partition/README.md) | Split-brain detection and resolution for the mesh: epoch-based `PartitionDetector` (deterministic partition-id from sorted reachable set), `QuorumResolver` wit… | +| [`@suaveplan/network-plugin-protocol`](./networking/network/network-plugin-protocol/README.md) | Network protocol plugin for the mesh system. | +| [`@suaveplan/network-plugin-qos`](./networking/network/network-plugin-qos/README.md) | Bandwidth management and quality-of-service for the mesh: bandwidth-quota enforcer, message-priority classifier, QoS router (bypass / drop / queue / defer), co… | +| [`@suaveplan/network-plugin-registry`](./networking/network/network-plugin-registry/README.md) | Fixed-capacity peer registry with bitpacker-based binary encoding. | +| [`@suaveplan/network-plugin-relay`](./networking/network/network-plugin-relay/README.md) | Cross-mesh relay — the federation layer that lets Tier 0 hosts of different meshes route messages to each other. Composes `RelayRouter`, `HostBackboneTransport… | +| [`@suaveplan/network-plugin-server-bridge`](./networking/network/network-plugin-server-bridge/README.md) | Tier-0 host ↔ central-server bridge for the Suaveplan mesh. | +| [`@suaveplan/network-plugin-session`](./networking/network/network-plugin-session/README.md) | Hierarchical session management for the Suaveplan mesh. `SessionTree` maintains a parent-child session graph rooted at a single auto-created root; `SessionMana… | +| [`@suaveplan/network-plugin-simulation`](./networking/network/network-plugin-simulation/README.md) | Deterministic virtual-network simulation framework for the Suaveplan mesh. `NetworkSimulator` runs scenarios against a seeded RNG with simulated time (accelera… | +| [`@suaveplan/network-plugin-state`](./networking/network/network-plugin-state/README.md) | Mesh-wide synchronized state for the Suaveplan network. Path-based `StateManager` (versioned history with sequence numbers + per-path subscriptions); `DeltaCom… | +| [`@suaveplan/network-plugin-topology`](./networking/network/network-plugin-topology/README.md) | Tiered mesh topology plugin: 3-tier `HierarchicalTopology` (Host / SubHost / Leaf) with promote/demote, latency-bucket-based `LatencyAssigner`, `GroupManager`,… | +| [`@suaveplan/network-plugin-transport-manager`](./networking/network/network-plugin-transport-manager/README.md) | Multi-transport orchestration for the Suaveplan mesh. Maintains a pool of registered transports per peer, negotiates capability bitmaps during handshake, route… | +| [`@suaveplan/network-testing`](./networking/network/network-testing/README.md) | | +| [`@suaveplan/network-transport-hyperswarm`](./networking/network/network-transport-hyperswarm/README.md) | Server-tier Hyperswarm DHT transport for `@suaveplan/network`. Provides hole-punched peer-to-peer streams discovered via Kademlia DHT topics. | +| [`@suaveplan/network-transport-libp2p`](./networking/network/network-transport-libp2p/README.md) | Universal libp2p `Transport` for `@suaveplan/network`. Composes WebSockets or WebRTC sub-transports with Noise + Yamux, identify + ping + bootstrap + circuit-r… | +| [`@suaveplan/network-transport-standby`](./networking/network/network-transport-standby/README.md) | Pre-emptive WebRTC standby transport for `@suaveplan/network`. Maintains a pool of warm `RTCPeerConnection`-like slots so peer attach completes in ~10 ms inste… | +| [`@suaveplan/network-transport-webrtc`](./networking/network/network-transport-webrtc/README.md) | WebRTC transport plugin for mesh networking. | +| [`@suaveplan/network-transport-websockets`](./networking/network/network-transport-websockets/README.md) | WebSocket client utilities with typed message framing, connection lifecycle management, heartbeat, backpressure queue, and injectable transport adapters. | +| [`@suaveplan/network-trystero-server`](./networking/network/network-trystero-server/README.md) | Server-tier Trystero signaling daemon. Hosts an MQTT-style or Nostr-style WebSocket broker shim plus standard `/health` / `/ready` / `/live` probes on a single… | +| [`@suaveplan/react-network-libp2p-demo`](./networking/network/react-network-libp2p-demo/README.md) | React-tier demo UI for `@suaveplan/network-transport-libp2p`. Splits the upstream 749-LOC monolithic demo into per-concern subcomponents (``,… | +| [`@suaveplan/service-discovery`](./networking/network/service-discovery/README.md) | Universal service-registry primitives. Provides the shared `ServiceDescriptor`, `ServiceQuery`, `RegistryEvent`, and `ServiceRegistry` contract consumed by eve… | +| [`@suaveplan/websocket-gateway`](./networking/network/websocket-gateway/README.md) | Server-tier WebSocket gateway daemon with rooms, presence tracking, and channel-multiplexed pub/sub. Pairs with `@suaveplan/network-transport-websockets` on th… | + +### `observability` + +Monitoring, logging, health checks, audit trails, and analytics. + +#### `monitor` + +Logging, health checks, audit logging, and analytics instrumentation. + +| Package | Description | +|---|---| +| [`@suaveplan/analytics-browser`](./observability/monitor/analytics-browser/README.md) | Browser-tier client-side product analytics — `AnalyticsTracker`, `BatchTransport`, `BeaconTransport`, and `SessionManager` with consent gate, PII scrubber, hea… | +| [`@suaveplan/audit-logging`](./observability/monitor/audit-logging/README.md) | Tamper-proof, GDPR-compliant audit logging for Suaveplan. Provides a cryptographic chain-integrity engine, pluggable storage adapters, GDPR data export, config… | +| [`@suaveplan/health-check`](./observability/monitor/health-check/README.md) | Server-tier health-check core for `/health`, `/ready`, `/live` endpoints with dependency checks (HTTP, TCP, custom), aggregated status, caching, and typed life… | +| [`@suaveplan/logger`](./observability/monitor/logger/README.md) | Enterprise-grade structured logger for Suaveplan. Provides a full pipeline: level filtering → OTel trace enrichment → sampling → redaction → sinks. Supports mu… | +| [`@suaveplan/opentelemetry`](./observability/monitor/opentelemetry/README.md) | OpenTelemetry SDK setup and configuration helpers for Suaveplan. Provides batteries-included OTel initialization helpers, resource detection, ergonomic span/me… | + +### `persistence` + +Caching, database adapters, search engines, and storage abstractions. + +#### `cache` + +Caching abstractions, memory caches, and Redis backends. + +| Package | Description | +|---|---| +| [`@suaveplan/cache`](./persistence/cache/cache/README.md) | Type-safe caching abstraction for Suaveplan. Provides `MemoryCache` with LRU/LFU/FIFO/TTL eviction, `NamespacedCache` for shared-storage isolation, a `CacheFac… | +| [`@suaveplan/cache-redis`](./persistence/cache/cache-redis/README.md) | `AbstractCache` backend over a minimal `RedisLike` interface — native `SET ... EX`, `GET`, `DEL`, `EXISTS`, `TTL`, `SCAN`. Reuses `@suaveplan/cache-storage`… | +| [`@suaveplan/cache-storage`](./persistence/cache/cache-storage/README.md) | `AbstractCache` backend that bridges any `@suaveplan/storage` `AbstractStorage` into a typed cache via a 32-byte fixed-width TTL header and pluggable `Codec… | + +#### `database` + +Database adapters, migrations, seeding, and SQLite support. + +| Package | Description | +|---|---| +| [`@suaveplan/db`](./persistence/database/db/README.md) | Universal relational database adapter interface for Suaveplan. Provides the `DatabaseAdapter` contract (extending `DatabaseLike` from `@suaveplan/types`), inje… | +| [`@suaveplan/db-sqlite`](./persistence/database/db-sqlite/README.md) | Universal SQLite adapter for Suaveplan. Runs on `bun:sqlite` on the Bun server and `@sqlite.org/sqlite-wasm` (Web Worker) in the browser, unified behind a sing… | +| [`@suaveplan/migration`](./persistence/database/migration/README.md) | Database-agnostic schema migration runner with ledger tracking, checksum validation, dry-run reporting, distributed locking, event bus integration, and OTel in… | +| [`@suaveplan/seed`](./persistence/database/seed/README.md) | Universal declarative database seeding and fixture framework. Define seed data once, let the runner handle dependency ordering, environment filtering, idempote… | +| [`@suaveplan/surrealdb`](./persistence/database/surrealdb/README.md) | Universal SurrealDB client wrapper for Suaveplan. Implements `@suaveplan/db`'s `DatabaseAdapter` interface with connection lifecycle management, typed CRUD, sc… | + +#### `search` + +Full-text search, BM25, fuzzy matching, and faceted search. + +| Package | Description | +|---|---| +| [`@suaveplan/search`](./persistence/search/search/README.md) | Full-text and fuzzy search primitives with in-memory BM25 engine, trigram fuzzy matching, faceted search, and pagination support. | + +#### `storage` + +Storage abstractions, browser backends, S3, CDN, and URI routing. + +| Package | Description | +|---|---| +| [`@suaveplan/storage`](./persistence/storage/storage/README.md) | Enterprise key-value storage abstractions for Suaveplan. Provides `AbstractStorage` (implementing `StorageLike`), `MemoryStorage` with TTL and zero-copy stream… | +| [`@suaveplan/storage-browser-indexeddb`](./persistence/storage/storage-browser-indexeddb/README.md) | Browser-tier `AbstractStorage` adapter backed by the W3C IndexedDB API (`globalThis.indexedDB`). Provides persistent, origin-scoped key-value storage for brows… | +| [`@suaveplan/storage-browser-localstorage`](./persistence/storage/storage-browser-localstorage/README.md) | Browser-tier `AbstractStorage` adapter backed by the synchronous `Storage` API (`globalThis.localStorage`). Provides namespaced, origin-scoped key-value storag… | +| [`@suaveplan/storage-browser-opfs`](./persistence/storage/storage-browser-opfs/README.md) | Browser-tier `AbstractStorage` adapter backed by the Origin Private File System (OPFS). Provides persistent, origin-scoped key-value storage for browser consum… | +| [`@suaveplan/storage-cdn`](./persistence/storage/storage-cdn/README.md) | Types-only foundation for CDN-flavoured `@suaveplan/storage` adapters. Declares `CdnAdapter` (an abstract base class extending `AbstractStorage` with `purge`,… | +| [`@suaveplan/storage-cdn-bunnycdn`](./persistence/storage/storage-cdn-bunnycdn/README.md) | BunnyCDN Storage Zone + Pull Zone provider for `@suaveplan/storage-cdn`. Full `AbstractStorage` and `CdnAdapter` surface — `get`/`set`/`delete`/`exists`/`getMe… | +| [`@suaveplan/storage-cdn-rackspace`](./persistence/storage/storage-cdn-rackspace/README.md) | Rackspace Cloud Files (OpenStack Swift) origin + Rackspace CDN provider for `@suaveplan/storage-cdn`. Full `AbstractStorage` and `CdnAdapter` surface — `get`/`… | +| [`@suaveplan/storage-file`](./persistence/storage/storage-file/README.md) | Node.js filesystem `AbstractStorage` adapter for `@suaveplan/storage`. Implements atomic writes via temp-file-then-rename, AbortSignal threaded through every a… | +| [`@suaveplan/storage-http`](./persistence/storage/storage-http/README.md) | Universal HTTP/CDN-backed `AbstractStorage` adapter for `@suaveplan/storage`. Reads via `GET`/`HEAD`/`Range` against any `` origin, with optional… | +| [`@suaveplan/storage-plugin-cache`](./persistence/storage/storage-plugin-cache/README.md) | Read-through cache decorator for `AbstractStorage`. Wraps any `@suaveplan/storage` instance with an injectable `AbstractCache`; hit/miss/populate o… | +| [`@suaveplan/storage-s3`](./persistence/storage/storage-s3/README.md) | S3-compatible object storage adapter for `@suaveplan/storage`. Extends `AbstractStorage` backed by `@aws-sdk/client-s3` with presigned URL generation, multipar… | +| [`@suaveplan/storage-uri`](./persistence/storage/storage-uri/README.md) | Universal URI-routed dispatch over `@suaveplan` `StorageLike` adapters. | +| [`@suaveplan/storage-uri-plugin-bundle`](./persistence/storage/storage-uri-plugin-bundle/README.md) | Per-package `bundle://` URI scheme for `@suaveplan/storage-uri`. | +| [`@suaveplan/storage-uri-plugin-fallback`](./persistence/storage/storage-uri-plugin-fallback/README.md) | Universal `fallback://` URI plugin for `@suaveplan/storage-uri`. Ships ordered multi-source resolution with cycle detection, depth cap, mirror writes, list uni… | + +### `security-stack` + +Cryptography, vaults, security utilities, and threat-detection primitives. + +#### `crypto` + +Cryptographic primitives, ciphers, hashes, curves, and key management. + +| Package | Description | +|---|---| +| [`@suaveplan/crypto`](./security-stack/crypto/crypto/README.md) | Universal cryptographic primitives — engine-pluggable AEAD, Ed25519/ECDSA-P256 signing, X25519 key agreement, sealed-box, and auth-box. Built on audited @noble… | +| [`@suaveplan/crypto-bin`](./security-stack/crypto/crypto-bin/README.md) | Suaveplan password-hashing CLI. Ships the `suaveplan-hash-password` binary — Argon2id (default) and BLAKE2b password hashing + verification with PHC/MCF-format… | +| [`@suaveplan/crypto-browser`](./security-stack/crypto/crypto-browser/README.md) | WebCrypto-backed engine implementations for `@suaveplan/crypto` — AES-256-GCM, Ed25519, ECDSA-P256/P384, X25519, ECDH-P256/P384, RSA, AES-KW, and non-extractab… | +| [`@suaveplan/crypto-cipher`](./security-stack/crypto/crypto-cipher/README.md) | Low-level AEAD (Authenticated Encryption with Associated Data) cipher primitives for the `@suaveplan/crypto` stack. Provides three algorithms — AES-256-GCM, Ch… | +| [`@suaveplan/crypto-cli`](./security-stack/crypto/crypto-cli/README.md) | Suaveplan keychain CLI — root + server identity lifecycle (init, roll, revoke, inspect, verify, export-public, restore) | +| [`@suaveplan/crypto-core`](./security-stack/crypto/crypto-core/README.md) | Universal cryptographic primitives — engine-pluggable AEAD, Ed25519/ECDSA-P256 signing, X25519 key agreement, sealed-box, and auth-box. Built on audited @noble… | +| [`@suaveplan/crypto-curve`](./security-stack/crypto/crypto-curve/README.md) | Low-level elliptic-curve building blocks for the `@suaveplan/crypto` stack. Exposes four curves — secp256k1, Ed25519, X25519, and NIST P-256 — each as a standa… | +| [`@suaveplan/crypto-hash`](./security-stack/crypto/crypto-hash/README.md) | Pure-TypeScript hashing substrate. SHA-2 digests, HMAC, HKDF, PBKDF2, Argon2id, and hex/Base64 encoding — no WASM, no browser globals, fully tree-shakeable. | +| [`@suaveplan/crypto-keys`](./security-stack/crypto/crypto-keys/README.md) | Hierarchical keychain chain-signing for the crypto ecosystem. Store-agnostic, free of `node:` / `bun:` imports. | +| [`@suaveplan/crypto-rsa`](./security-stack/crypto/crypto-rsa/README.md) | RSA primitives for Suaveplan — RFC 8017 PKCS #1 v2.2, RFC 5208 / RFC 5958 PKCS #8, RFC 5280 SPKI, RFC 7517 / RFC 7518 JWK, RFC 7468 PEM. Universal package (zer… | +| [`@suaveplan/crypto-sodium`](./security-stack/crypto/crypto-sodium/README.md) | libsodium-backed engine implementations for `@suaveplan/crypto`. Provides AEAD encryption, Ed25519 signing, X25519 key agreement, sealed-box, auth-box, determi… | +| [`@suaveplan/crypto-utils`](./security-stack/crypto/crypto-utils/README.md) | Shared cryptographic utilities consumed internally by all other `@suaveplan/crypto-*` packages. Provides the low-level primitives that every crypto implementat… | +| [`@suaveplan/crypto-vault`](./security-stack/crypto/crypto-vault/README.md) | Cryptographic foundation for the Vaulted password-manager ecosystem. Provides BIP39 mnemonic generation, OWASP-grade Argon2id derivation, two-secret key deriva… | + +#### `security` + +Have-I-Been-Pwned checks, JWS, licensing, and OTP utilities. + +| Package | Description | +|---|---| +| [`@suaveplan/hibp`](./security-stack/security/hibp/README.md) | Privacy-preserving Have I Been Pwned v3 client. Universal — works in Node, Bun, Deno, browsers, edge workers. The only required runtime primitive is `fetch`. | +| [`@suaveplan/jws`](./security-stack/security/jws/README.md) | RFC 7515 **JSON Web Signature** (verify + sign). Pure TypeScript over `Uint8Array` + `DataView` plus the workspace crypto primitives (`@suaveplan/crypto-rsa`,… | +| [`@suaveplan/license`](./security-stack/security/license/README.md) | Compact, offline-verifiable, secp256k1-signed software-license-key format. Bit-for-bit wire-format compatible with upstream `@suaveplan/license`. runs unchange… | +| [`@suaveplan/otp`](./security-stack/security/otp/README.md) | RFC 4226 (HOTP) + RFC 6238 (TOTP) + RFC 6287 (OCRA) + Google Authenticator Key URI Format + Base32 (RFC 4648 §6) + recovery codes + clock-drift detector — zero browser/Node deps | +| [`@suaveplan/password-formats`](./security-stack/security/password-formats/README.md) | Universal import/export layer for common password-manager export formats. Parses Apple Passwords CSV, Bitwarden JSON, Chrome CSV, and KeePass XML into a normal… | +| [`@suaveplan/password-generator`](./security-stack/security/password-generator/README.md) | Cryptographically-strong password and passphrase generator — char-class, pronounceable, EFF Diceware, and PIN modes with bias-free RNG, real entropy estimates,… | +| [`@suaveplan/password-strength`](./security-stack/security/password-strength/README.md) | zxcvbn-style password strength estimator — pattern-matching + dictionary cracker model per Wheeler 2016. Universal; zero browser/Node/React deps. Re-implementa… | +| [`@suaveplan/security-codes`](./security-stack/security/security-codes/README.md) | Detect and sanitise sensitive security-code leakage in strings. Handles API keys, JWTs, credit cards, GitHub tokens, Stripe keys, SSH keys, PEM blocks, AWS acc… | +| [`@suaveplan/server-keys`](./security-stack/security/server-keys/README.md) | Operator-facing CLI bundle for the Suaveplan server-key lifecycle: 18 bins covering root + server keychain generation (including hierarchical `ChainedKeySigner… | +| [`@suaveplan/slsa`](./security-stack/security/slsa/README.md) | SLSA L1-L2 supply-chain security for Suaveplan. Generates and verifies in-toto / SLSA v1.0 provenance, CycloneDX 1.5 SBOMs, DSSE attestation envelopes, and RFC… | +| [`@suaveplan/srp`](./security-stack/security/srp/README.md) | SRP-6a zero-knowledge password proof per RFC 5054 / RFC 2945. Universal — client and server roles in one package, bundled 2048-bit safe-prime group, optional 1… | +| [`@suaveplan/tpm-struct`](./security-stack/security/tpm-struct/README.md) | Zero-runtime-dep TPM 2.0 attestation-structure parser and serialiser. Decodes `TPMS_ATTEST` (TCG TPM 2.0 Library Part 2 §10.12), decodes `TPMT_PUBLIC` (§12.2),… | +| [`@suaveplan/vault`](./security-stack/security/vault/README.md) | Vault orchestration layer for the Vaulted password-manager ecosystem. Provides a drive-backed encrypted SQLite-style container, a strict `locked` ↔ `unlocked`… | +| [`@suaveplan/vault-sync`](./security-stack/security/vault-sync/README.md) | Domain-specific sync and conflict-resolution engine for the Vaulted password-manager ecosystem. Builds on `@suaveplan/crdt` and `@suaveplan/diff` (RFC 6902 JSO… | +| [`@suaveplan/x509`](./security-stack/security/x509/README.md) | RFC 5280 X.509 v3 certificate parser and certification-path validator. Universal (zero browser, Node, or React deps). Pure TypeScript over `Uint8Array` / `Data… | + +### `testkit` + +Testing frameworks, A/B testing, and quality-assurance utilities. + +#### `testing` + +Testing runners, DOM helpers, E2E harnesses, and A/B testing. + +| Package | Description | +|---|---| +| [`@suaveplan/ab-testing`](./testkit/testing/ab-testing/README.md) | Enterprise A/B testing and experimentation engine with deterministic FNV-1a bucketing, targeting rules, variant assignment, conversion tracking, result aggrega… | +| [`@suaveplan/testing`](./testkit/testing/testing/README.md) | Shared test infrastructure for Suaveplan. Provides runner primitives (Vitest or bun-test via conditional exports), structured builders, a deterministic FakeClo… | +| [`@suaveplan/testing-dom`](./testkit/testing/testing-dom/README.md) | DOM and React component testing utilities for Suaveplan. Provides a single install that covers vitest config generation with WSL2-safe defaults, `@testing-libr… | +| [`@suaveplan/testing-e2e`](./testkit/testing/testing-e2e/README.md) | Playwright E2E testing utilities for Suaveplan, with the default `browser` worker fixture launching `cloakbrowser` — a real Chromium binary with 49 source-leve… | +| [`@suaveplan/testing-integration`](./testkit/testing/testing-integration/README.md) | Core integration test infrastructure for Vitest: fixture lifecycle management, health polling, and the global-setup bridge. | +| [`@suaveplan/testing-integration-garage-s3`](./testkit/testing/testing-integration-garage-s3/README.md) | Garage S3 v2.0.0 testcontainers fixture for `@suaveplan/testing-integration`. | +| [`@suaveplan/testing-integration-mailpit`](./testkit/testing/testing-integration-mailpit/README.md) | Mailpit testcontainers fixture + `assertMail()` helper for `@suaveplan/testing-integration`. | +| [`@suaveplan/testing-integration-oauth-mock`](./testkit/testing/testing-integration-oauth-mock/README.md) | Real-HTTP mock OAuth 2.0 Identity Provider for integration tests. | +| [`@suaveplan/testing-integration-postgres`](./testkit/testing/testing-integration-postgres/README.md) | PostgreSQL 16 testcontainers fixture for `@suaveplan/testing-integration`. | +| [`@suaveplan/testing-integration-redis`](./testkit/testing/testing-integration-redis/README.md) | Redis 7 testcontainers fixture for `@suaveplan/testing-integration`. | +| [`@suaveplan/testing-integration-step-ca`](./testkit/testing/testing-integration-step-ca/README.md) | A `ServiceFixture` for `smallstep/step-ca` that gives any integration test suite a real, ephemeral certificate authority — root cert, JWK provisioner, and an `… | +| [`@suaveplan/testing-integration-surrealdb`](./testkit/testing/testing-integration-surrealdb/README.md) | SurrealDB v3 testcontainers fixture for `@suaveplan/testing-integration`. | +| [`@suaveplan/testing-integration-typesense`](./testkit/testing/testing-integration-typesense/README.md) | Typesense 27 testcontainers fixture for `@suaveplan/testing-integration`. | + +### `threejs` + +Three.js and React Three Fiber integrations. + +#### `r3f` + +React Three Fiber networking and scene components. + +| Package | Description | +|---|---| +| [`@suaveplan/r3f-networking`](./threejs/r3f/r3f-networking/README.md) | R3F-tier multiplayer state-synchronisation for React-Three-Fiber scenes. Composes any `@suaveplan/network` `Transport` (canonical: `@suaveplan/network-transpor… | + +### `ui` + +React components, forms, and user-interface primitives. + +#### `forms` + +Form builders, validation, and React form components. + +| Package | Description | +|---|---| +| [`@suaveplan/form-builder`](./ui/forms/form-builder/README.md) | Universal dynamic form schema engine. Renderer-agnostic — no DOM, no React, no Node-specific globals. Drives every dynamic form surface in the Suaveplan. | +| [`@suaveplan/react-forms`](./ui/forms/react-forms/README.md) | React forms library for the Suaveplan ecosystem. Wraps react-hook-form + Zod with a primitives + factory + recipes architecture: every user-facing string is ty… | + +#### `react` + +React hooks and components for audio, auth, and UI surfaces. + +| Package | Description | +|---|---| +| [`@suaveplan/react-audio`](./ui/react/react-audio/README.md) | React surface for the Suaveplan audio family. **Phase 1 of 3 — foundation** (provider + hooks + stores + error codes + a11y helpers). Components ship in Phase… | +| [`@suaveplan/react-audio-fingerprint`](./ui/react/react-audio-fingerprint/README.md) | React 19 surface for client-side audio fingerprinting and identity matching. The package implements the classic Shazam-style constellation algorithm (2D-peak d… | +| [`@suaveplan/react-audio-player`](./ui/react/react-audio-player/README.md) | Track-style media-player surface for the Suaveplan audio family. The package ships two kinds of exports: | +| [`@suaveplan/react-audio-stream`](./ui/react/react-audio-stream/README.md) | React 19 surface for live audio streaming sessions: a Provider, six hooks, and four accessible components. Chunk C of the four-chunk `enterprise-react-audio-st… | +| [`@suaveplan/react-auth`](./ui/react/react-auth/README.md) | React authentication core for Suaveplan apps — a typed wrapper around `better-auth/client`, an `AuthProvider` React context, an `AuthGuard` route component, `u… | +| [`@suaveplan/react-auth-whitelabel`](./ui/react/react-auth-whitelabel/README.md) | White-label authentication React components with tenant branding wired through the `@suaveplan/react-ui` runtime theme-token mutator. | +| [`@suaveplan/react-control-surface`](./ui/react/react-control-surface/README.md) | React 19 atomic-control surface renderer for `@suaveplan/control-surface-schema`. | +| [`@suaveplan/react-midi`](./ui/react/react-midi/README.md) | React 19 adapter for the Web MIDI API. Provides a strict-mode-safe `` that requests `MIDIAccess` exactly once, seven typed hooks for common consu… | +| [`@suaveplan/react-ui`](./ui/react/react-ui/README.md) | React UI component library — opinionated providers, theme/pack plugin contracts, bundled translations, telemetry, shadcn-compatible registry generator. | + diff --git a/docs/_intro.md b/docs/_intro.md new file mode 100644 index 0000000..d123bd9 --- /dev/null +++ b/docs/_intro.md @@ -0,0 +1,3 @@ +# `packages` + +Suaveplan package tree. Every `@suaveplan/*` library lives under a category (`packages//`) and a subcategory (`packages///`). diff --git a/docs/api-stack/README.md b/docs/api-stack/README.md new file mode 100644 index 0000000..fac85cd --- /dev/null +++ b/docs/api-stack/README.md @@ -0,0 +1,106 @@ +# `api-stack` + +API infrastructure, plugin framework, and HTTP orchestration layer for Suaveplan. + + +## Subcategories + +1 subcategory, 90 packages. + +### `api` + +API orchestration, plugin lifecycle, routing, workers, and tenant resolution. + +| Package | Description | +|---|---| +| [`@suaveplan/api`](./api/README.md) | The thin Hono-based application orchestrator for the Suaveplan API stack. Composes the four sibling packages — `@suaveplan/api-plugin`, `@suaveplan/api-tenant`… | +| [`@suaveplan/api-2pc`](./api-2pc/README.md) | Two-phase commit coordinator for the Suaveplan API plugin system. Drives Postgres PREPARE TRANSACTION / COMMIT PREPARED / ROLLBACK PREPARED across registered p… | +| [`@suaveplan/api-audit-file`](./api-audit-file/README.md) | File-rotating, HMAC-signed audit sink for `@suaveplan/api-host`. Implements `RequestAuditSink` from `@suaveplan/api-host/request-pipeline`: writes one JSON lin… | +| [`@suaveplan/api-audit-stdout`](./api-audit-stdout/README.md) | Stdout audit sink for `@suaveplan/api-host`. Writes JSON-per-line audit records to a `LineWriter` (default `process.stdout`) with an HMAC-SHA-256 signature app… | +| [`@suaveplan/api-auth`](./api-auth/README.md) | **$2** for the Suaveplan API plugin system. Defines the abstract session-resolver shape (`Request → Principal \| null`) used by the host on every request, plus… | +| [`@suaveplan/api-auth-anonymous`](./api-auth-anonymous/README.md) | Stage-4 trivial session resolver for `@suaveplan/api`. Always returns `null` for every request. Use this as the tail of resolver chains for public endpoints, a… | +| [`@suaveplan/api-auth-bearer-static`](./api-auth-bearer-static/README.md) | Stage-4 service-to-service `SessionResolver` adapter for the `@suaveplan/api` plugin system. Matches an inbound `Authorization: Bearer ` header against… | +| [`@suaveplan/api-auth-better-auth`](./api-auth-better-auth/README.md) | Stage-6 Better-Auth adapter for `@suaveplan/api`. Ships two **independently-wireable** capability surfaces — `createBetterAuthSession` (implements `auth.sessio… | +| [`@suaveplan/api-auth-jwt`](./api-auth-jwt/README.md) | Stage-4 concrete `SessionResolver` for the `@suaveplan/api` plugin system. Verifies a JWT presented on the `Authorization: Bearer ` header (or a configure… | +| [`@suaveplan/api-auth-provider`](./api-auth-provider/README.md) | Abstract account-lifecycle contract for the Suaveplan API plugin system (contracts). This package is OPTIONAL: hosted-IdP deployments (Clerk, Auth0, Cognito) i… | +| [`@suaveplan/api-auth-rolled`](./api-auth-rolled/README.md) | Stage-8.12 rolled session-token resolver for `@suaveplan/api`. Issues RS256-signed JWTs with rotating `kid` slots, verifies tokens through the rotator's active… | +| [`@suaveplan/api-auth-static-principal`](./api-auth-static-principal/README.md) | Fixed-`Principal` session resolver for the `@suaveplan/api` plugin system. Returns the configured `Principal` verbatim on every request — no token decoding, no… | +| [`@suaveplan/api-db-adapter`](./api-db-adapter/README.md) | Stage-4 bridge from the `@suaveplan/db` engine adapters to the plugin `AdminDatabaseLike` / `TenantScopedDatabaseLike` surfaces exposed by `@suaveplan/api-type… | +| [`@suaveplan/api-db-sqlite-memory`](./api-db-sqlite-memory/README.md) | Stage-5 in-memory SQLite database adapter for the `@suaveplan/api` plugin host testing kit. Wraps `bun:sqlite` (in `:memory:` mode by default, or a file path f… | +| [`@suaveplan/api-db-worker-proxy`](./api-db-worker-proxy/README.md) | Worker-side proxy for the api `db` capability. Marshals `AdminDatabaseLike` and `TenantScopedDatabaseLike` calls — including transactions and cursor streams —… | +| [`@suaveplan/api-events-in-memory`](./api-events-in-memory/README.md) | In-memory events bus adapter for the `@suaveplan/api` testing kit. Wraps `@suaveplan/events`' production `EventBus` with a per-topic recording layer so tests c… | +| [`@suaveplan/api-events-worker-proxy`](./api-events-worker-proxy/README.md) | Worker-tier proxy over a main-process `@suaveplan/events` `EventBus`. | +| [`@suaveplan/api-graphql`](./api-graphql/README.md) | Stage-1 abstract GraphQL contract for the Suaveplan API plugin system. | +| [`@suaveplan/api-graphql-apollo`](./api-graphql-apollo/README.md) | Stage-7 Apollo Server GraphQL engine adapter for the Suaveplan API plugin system. Implements the `GraphqlEngine` contract from `@suaveplan/api-graphql` and pas… | +| [`@suaveplan/api-graphql-ui-altair`](./api-graphql-ui-altair/README.md) | Altair GraphQL UI plugin for the Suaveplan API plugin system. Structural sibling of `@suaveplan/api-graphql-ui-graphiql`. | +| [`@suaveplan/api-graphql-ui-graphiql`](./api-graphql-ui-graphiql/README.md) | GraphiQL UI mount for the Suaveplan API plugin system. Stage 7 of the umbrella plan. | +| [`@suaveplan/api-graphql-yoga`](./api-graphql-yoga/README.md) | Stage-7 GraphQL Yoga engine adapter. **Default GraphQL engine** for the Suaveplan API plugin system per design doc §10.5 — Bun-friendly, fastest for our usage… | +| [`@suaveplan/api-host`](./api-host/README.md) | Host orchestration core for the Suaveplan API plugin system. Provides the stable error-code registry (HOST/PLUGIN/RELOAD/CAPABILITY/ADMIN/LEDGER), the author-facing definePlugin DX, the runtime CapabilityRegistry, the LifecycleDriver + ReloadDriver + PluginLedger + admin Hono sub-router, the ErrorBoundary, the §6 11-step RequestPipeline, the top-level createHost(config) entry point composing every internal driver, and the HostInstruments registry covering the §12.3 metric surface. The ./testing subpath is reserved for test utilities. | +| [`@suaveplan/api-jobs-worker-proxy`](./api-jobs-worker-proxy/README.md) | Bidirectional `MessagePort` proxy that lets a worker-isolated API plugin participate in the host's main-process job scheduler. The worker calls `registerCron`… | +| [`@suaveplan/api-lifecycle`](./api-lifecycle/README.md) | Stage-1 contract package for the Suaveplan API plugin system: the plugin-lifecycle finite state machine definition, the legal-transition table, the side-effect… | +| [`@suaveplan/api-loader`](./api-loader/README.md) | Stage-1 contract package for the Suaveplan API plugin system. | +| [`@suaveplan/api-logger-worker-proxy`](./api-logger-worker-proxy/README.md) | Stage-3 worker → main proxy for `@suaveplan/logger`. Lets a worker-isolated API plugin call a normal `LoggerLike` surface while the records cross a `MessagePor… | +| [`@suaveplan/api-manifest`](./api-manifest/README.md) | Stage-1 contract package of the Suaveplan API plugin system: Zod schemas, parser, cross-field validators, dependency-graph resolver, capability resolver, and c… | +| [`@suaveplan/api-migrations`](./api-migrations/README.md) | Database-agnostic migration runner for the Suaveplan API. Ships a narrow `MigrationAdapter` surface (six methods), three shipped adapters (`surrealql`, `postgr… | +| [`@suaveplan/api-openapi`](./api-openapi/README.md) | OpenAPI 3.1 registry, typed `RouteBuilder`, schema registry, and document merger for the Suaveplan API. Single source of truth that wires into Hono via `OpenAP… | +| [`@suaveplan/api-openapi-ui-redoc`](./api-openapi-ui-redoc/README.md) | Stage-8 ReDoc UI adapter for the Suaveplan api-host. Mounts the ReDoc HTML shell at `/docs/ui/redoc` (or any caller-chosen path) via `createRedocUiHandler` and… | +| [`@suaveplan/api-openapi-ui-scalar`](./api-openapi-ui-scalar/README.md) | Scalar UI adapter for the Suaveplan OpenAPI plugin system. | +| [`@suaveplan/api-openapi-ui-swagger`](./api-openapi-ui-swagger/README.md) | Swagger UI adapter for the `/docs/ui/swagger` endpoint of the Suaveplan API plugin system (Stage 8.8). Returns a pure HTTP handler whose response is a `text/ht… | +| [`@suaveplan/api-plugin`](./api-plugin/README.md) | Plugin-system foundation for the Suaveplan API. Universal — runs unchanged in Bun, Node, and the browser. | +| [`@suaveplan/api-plugin-audit`](./api-plugin-audit/README.md) | Hono plugin that wraps `@suaveplan/audit-logging` as a write-through audit trail for `@suaveplan/api`. Installs a global per-request audit middleware (method /… | +| [`@suaveplan/api-plugin-auth`](./api-plugin-auth/README.md) | Better-Auth-first authentication plugin for `@suaveplan/api`. The canonical exemplar of the 3-way plug-and-play contract every `@suaveplan/api-plugin-*` packag… | +| [`@suaveplan/api-plugin-campaigns`](./api-plugin-campaigns/README.md) | Campaigns + suppression + delivery-webhooks HTTP plugin for `@suaveplan/api`. Mounts the `/campaigns`, `/suppression`, and `/webhooks` route trees on a Hono `O… | +| [`@suaveplan/api-plugin-cms`](./api-plugin-cms/README.md) | Headless content-management primitives for `@suaveplan/api`. Ships an in-memory `CmsEngine` that manages flexible content models, content entries with a `draft… | +| [`@suaveplan/api-plugin-database`](./api-plugin-database/README.md) | SurrealDB-backed database plugin for `@suaveplan/api`. Pools `@suaveplan/surrealdb`'s `SurrealAdapter` (implementing `@suaveplan/db`'s `DatabaseAdapter`), runs… | +| [`@suaveplan/api-plugin-event-bus`](./api-plugin-event-bus/README.md) | Typed event-bus plugin for `@suaveplan/api`. Wraps `@suaveplan/events` (pub/sub, async dispatch, interceptors, bounded-queue backpressure, idempotent listener… | +| [`@suaveplan/api-plugin-events`](./api-plugin-events/README.md) | Event-management plugin for `@suaveplan/api`. Ships a SurrealDB-backed `EventRepository` + `RsvpRepository` pair, ten Hono OpenAPI routes (list / get / create… | +| [`@suaveplan/api-plugin-example`](./api-plugin-example/README.md) | Reference plugin for the `@suaveplan/api-host` plugin system. The package is a load-bearing integration target, not a tutorial: every contract surface the host… | +| [`@suaveplan/api-plugin-export`](./api-plugin-export/README.md) | Data-export plugin for `@suaveplan/api`. Turns any registered resource into a CSV (RFC 4180), JSON, or XLSX (SpreadsheetML XML) blob through three self-contain… | +| [`@suaveplan/api-plugin-file-upload`](./api-plugin-file-upload/README.md) | Multipart and chunked file-upload plugin for `@suaveplan/api`. Ships six OpenAPI-typed Hono routes, a pluggable storage + session-store contract, SHA-256 hash… | +| [`@suaveplan/api-plugin-graphql`](./api-plugin-graphql/README.md) | GraphQL description + resolver-composition layer for `@suaveplan/api`. Server-tier — runs in Bun and Node. | +| [`@suaveplan/api-plugin-import`](./api-plugin-import/README.md) | Tabular-data ingest plugin for `@suaveplan/api`. Parses CSV / JSON / TSV-XLSX payloads, applies declarative column mappings + per-field validation + computed f… | +| [`@suaveplan/api-plugin-notifications`](./api-plugin-notifications/README.md) | SurrealDB-backed notifications + push plugin for `@suaveplan/api`. Ships a `NotificationRepository` + `DeviceTokenRepository` pair, an `ApnService` with a plug… | +| [`@suaveplan/api-plugin-payment`](./api-plugin-payment/README.md) | Payment-lifecycle plugin for `@suaveplan/api`. Wraps `@suaveplan/payment` + a caller-injected `PaymentProvider` (Stripe / Adyen / PayPal / Square / Mollie / cu… | +| [`@suaveplan/api-plugin-rate-limit`](./api-plugin-rate-limit/README.md) | Rate-limit plugin for `@suaveplan/api`. Wraps `@suaveplan/rate-limiter` as a `definePlugin` descriptor exposing per-route + per-tenant configuration, parameter… | +| [`@suaveplan/api-plugin-search`](./api-plugin-search/README.md) | Full-text search plugin for `@suaveplan/api`. Brings TF-weighted relevance scoring, four built-in text analyzers (`standard`, `simple`, `whitespace`, `keyword`… | +| [`@suaveplan/api-plugin-site`](./api-plugin-site/README.md) | Multi-site / multi-domain management plugin for `@suaveplan/api`. Stores `site` records (name, slug, theme, settings, push config) in SurrealDB, resolves incom… | +| [`@suaveplan/api-plugin-sse`](./api-plugin-sse/README.md) | Server-Sent Events plugin for `@suaveplan/api`. Registers a typed `sseService` in the host `ServiceRegistry`, mounts a Hono streaming handler at `GET /sse/:cha… | +| [`@suaveplan/api-plugin-tenant`](./api-plugin-tenant/README.md) | Multi-tenancy plugin for `@suaveplan/api`. Wraps `@suaveplan/api-tenant`'s resolver chain (header / subdomain / domain / path / JWT / query / cookie) as a firs… | +| [`@suaveplan/api-plugin-user`](./api-plugin-user/README.md) | User-profile CRUD plugin for `@suaveplan/api`. Mounts the canonical `/users/me` GET/PATCH/DELETE surface on top of `@suaveplan/api-plugin-auth`, registers a ty… | +| [`@suaveplan/api-plugin-vault`](./api-plugin-vault/README.md) | Per-user vault HTTP plugin for `@suaveplan/api`. Third instance of the 3-way plug-and-play contract every `@suaveplan/api-plugin-*` package follows: the plugin… | +| [`@suaveplan/api-plugin-webhook`](./api-plugin-webhook/README.md) | Signed outbound webhook delivery plugin for `@suaveplan/api`. Wraps `@suaveplan/webhook-client` behind a `definePlugin` descriptor, registers a typed `webhookS… | +| [`@suaveplan/api-rate-limit`](./api-rate-limit/README.md) | Per-route / per-principal / per-tenant / per-IP token-bucket rate-limit middleware for `@suaveplan/api`. Implements the `RequestRateLimiter` contract consumed… | +| [`@suaveplan/api-rbac`](./api-rbac/README.md) | Scope + rule-based authorisation middleware for the Suaveplan API plugin system. Produces a framework-agnostic `Middleware` that consumes the resolved `Princip… | +| [`@suaveplan/api-router`](./api-router/README.md) | Stage-1 contract package for the Suaveplan API plugin system. | +| [`@suaveplan/api-router-hono`](./api-router-hono/README.md) | Stage-4 concrete Hono router adapter for `@suaveplan/api`. Implements the abstract `Router` contract from `@suaveplan/api-router` on top of a Hono `Hono` insta… | +| [`@suaveplan/api-router-in-memory`](./api-router-in-memory/README.md) | Stage-5 in-memory router adapter for `@suaveplan/api`. Implements both the abstract `Router` contract from `@suaveplan/api-router` AND the `PipelineRouter` con… | +| [`@suaveplan/api-router-worker-bridge`](./api-router-worker-bridge/README.md) | Stage-3 HTTP bridge that marshals Fetch `Request` and `Response` objects across the worker boundary. Pairs a main-side `dispatch` with a worker- side handler o… | +| [`@suaveplan/api-saga`](./api-saga/README.md) | Saga orchestrator for the Suaveplan API plugin system. Drives manifest-declared multi-plugin workflows in declared order with reverse-order compensation on fai… | +| [`@suaveplan/api-sandbox-permissions`](./api-sandbox-permissions/README.md) | Permission model for sandboxed-tier API plugins. Centralises the `permissions.fs[]` / `permissions.fetch[]` allowlists, the `permissions.budgets` enforcement,… | +| [`@suaveplan/api-sandbox-vm`](./api-sandbox-vm/README.md) | `vm.Context`-based sandbox host for Suaveplan API plugins running in the sandboxed tier. The package owns the `vm.Context`+frozen-globals half of the design do… | +| [`@suaveplan/api-sandbox-vm-host-bridge`](./api-sandbox-vm-host-bridge/README.md) | Host-integration bridge that lets a `VmSandboxHandle` from `@suaveplan/api-sandbox-vm` install into `@suaveplan/api-host` as a first-class plugin. | +| [`@suaveplan/api-sandbox-wasm`](./api-sandbox-wasm/README.md) | Stage-8 WebAssembly sandbox host. Instantiates a sandboxed-tier plugin WASM module against a WASI snapshot preview1 implementation derived from the plugin's `P… | +| [`@suaveplan/api-sandbox-wasm-host-bridge`](./api-sandbox-wasm-host-bridge/README.md) | Host-integration layer that wraps a `@suaveplan/api-sandbox-wasm` `WasmSandboxHandle` as a `@suaveplan/api-host` `PluginModule`. Sandboxed-tier plugins compile… | +| [`@suaveplan/api-schemas`](./api-schemas/README.md) | Shared Zod schemas describing Suaveplan API request/response shapes. The single source of truth for server plugins, React data hooks, and generated OpenAPI doc… | +| [`@suaveplan/api-secrets`](./api-secrets/README.md) | Abstract Secrets contract for the Suaveplan API plugin system — per-plugin secret access typed against `manifest.secrets[]`, canonical redaction marker, frozen… | +| [`@suaveplan/api-secrets-bun`](./api-secrets-bun/README.md) | Stage-8 `SecretsLike` adapter backed by `Bun.secrets` (macOS Keychain, Linux libsecret, Windows Credential Manager) with per-plugin allow-list enforcement, OS-… | +| [`@suaveplan/api-secrets-env`](./api-secrets-env/README.md) | Stage-4 `SecretsLike` adapter backed by `process.env` / `Bun.env` with per-plugin allowed-keys enforcement. | +| [`@suaveplan/api-secrets-vault`](./api-secrets-vault/README.md) | Stage-8 `SecretsLike` adapter backed by `@suaveplan/vault`. The vault is passed in already unlocked by the host's startup sequence; the adapter never sees the… | +| [`@suaveplan/api-secrets-worker-proxy`](./api-secrets-worker-proxy/README.md) | Stage-3 worker → main `SecretsLike` proxy for the API plugin system. | +| [`@suaveplan/api-sse`](./api-sse/README.md) | Abstract Server-Sent Events contracts for `@suaveplan/api`. Stage-1 contract package: defines the engine-side `SseConnection`, `SseBroker`, `ReplayBuffer` (Las… | +| [`@suaveplan/api-sse-bun`](./api-sse-bun/README.md) | `Bun.serve`-backed Server-Sent Events engine for the `@suaveplan/api` plugin system. Implements the abstract `@suaveplan/api-sse` contract and passes `runSseEn… | +| [`@suaveplan/api-tenant`](./api-tenant/README.md) | Multi-tenant resolution + scoping for the Suaveplan API. Server-tier — runs on Bun and Node, depends on `hono` and `node:async_hooks`. | +| [`@suaveplan/api-tenant-provider`](./api-tenant-provider/README.md) | Abstract `TenantProvider` contract for the Suaveplan API plugin system. Enumerates the universe of tenants known to a host so per-tenant cron / queued jobs (ma… | +| [`@suaveplan/api-tenant-provider-memory`](./api-tenant-provider-memory/README.md) | In-memory reference implementation of the `@suaveplan/api-tenant-provider` `TenantProvider` contract. Backed by an insertion-ordered `MapWASM compiler closing **Stage-8 gate 2.8**. Thin orchestrator around `Bun.build` (bundle) + an injected WASI-stdio ABI shim + **Javy v8.1.1** (JS->WASM) +… | + diff --git a/docs/api-stack/_intro.md b/docs/api-stack/_intro.md new file mode 100644 index 0000000..2500639 --- /dev/null +++ b/docs/api-stack/_intro.md @@ -0,0 +1,3 @@ +# `api-stack` + +API infrastructure, plugin framework, and HTTP orchestration layer for Suaveplan. diff --git a/docs/api-stack/api/README.md b/docs/api-stack/api/README.md new file mode 100644 index 0000000..c3aa907 --- /dev/null +++ b/docs/api-stack/api/README.md @@ -0,0 +1,102 @@ +# `api` + +API orchestration, plugin lifecycle, routing, workers, and tenant resolution. + + +## Packages in `api` + +90 packages. + +| Package | Description | +|---|---| +| [`@suaveplan/api`](./api/README.md) | The thin Hono-based application orchestrator for the Suaveplan API stack. Composes the four sibling packages — `@suaveplan/api-plugin`, `@suaveplan/api-tenant`… | +| [`@suaveplan/api-2pc`](./api-2pc/README.md) | Two-phase commit coordinator for the Suaveplan API plugin system. Drives Postgres PREPARE TRANSACTION / COMMIT PREPARED / ROLLBACK PREPARED across registered p… | +| [`@suaveplan/api-audit-file`](./api-audit-file/README.md) | File-rotating, HMAC-signed audit sink for `@suaveplan/api-host`. Implements `RequestAuditSink` from `@suaveplan/api-host/request-pipeline`: writes one JSON lin… | +| [`@suaveplan/api-audit-stdout`](./api-audit-stdout/README.md) | Stdout audit sink for `@suaveplan/api-host`. Writes JSON-per-line audit records to a `LineWriter` (default `process.stdout`) with an HMAC-SHA-256 signature app… | +| [`@suaveplan/api-auth`](./api-auth/README.md) | **$2** for the Suaveplan API plugin system. Defines the abstract session-resolver shape (`Request → Principal \| null`) used by the host on every request, plus… | +| [`@suaveplan/api-auth-anonymous`](./api-auth-anonymous/README.md) | Stage-4 trivial session resolver for `@suaveplan/api`. Always returns `null` for every request. Use this as the tail of resolver chains for public endpoints, a… | +| [`@suaveplan/api-auth-bearer-static`](./api-auth-bearer-static/README.md) | Stage-4 service-to-service `SessionResolver` adapter for the `@suaveplan/api` plugin system. Matches an inbound `Authorization: Bearer ` header against… | +| [`@suaveplan/api-auth-better-auth`](./api-auth-better-auth/README.md) | Stage-6 Better-Auth adapter for `@suaveplan/api`. Ships two **independently-wireable** capability surfaces — `createBetterAuthSession` (implements `auth.sessio… | +| [`@suaveplan/api-auth-jwt`](./api-auth-jwt/README.md) | Stage-4 concrete `SessionResolver` for the `@suaveplan/api` plugin system. Verifies a JWT presented on the `Authorization: Bearer ` header (or a configure… | +| [`@suaveplan/api-auth-provider`](./api-auth-provider/README.md) | Abstract account-lifecycle contract for the Suaveplan API plugin system (contracts). This package is OPTIONAL: hosted-IdP deployments (Clerk, Auth0, Cognito) i… | +| [`@suaveplan/api-auth-rolled`](./api-auth-rolled/README.md) | Stage-8.12 rolled session-token resolver for `@suaveplan/api`. Issues RS256-signed JWTs with rotating `kid` slots, verifies tokens through the rotator's active… | +| [`@suaveplan/api-auth-static-principal`](./api-auth-static-principal/README.md) | Fixed-`Principal` session resolver for the `@suaveplan/api` plugin system. Returns the configured `Principal` verbatim on every request — no token decoding, no… | +| [`@suaveplan/api-db-adapter`](./api-db-adapter/README.md) | Stage-4 bridge from the `@suaveplan/db` engine adapters to the plugin `AdminDatabaseLike` / `TenantScopedDatabaseLike` surfaces exposed by `@suaveplan/api-type… | +| [`@suaveplan/api-db-sqlite-memory`](./api-db-sqlite-memory/README.md) | Stage-5 in-memory SQLite database adapter for the `@suaveplan/api` plugin host testing kit. Wraps `bun:sqlite` (in `:memory:` mode by default, or a file path f… | +| [`@suaveplan/api-db-worker-proxy`](./api-db-worker-proxy/README.md) | Worker-side proxy for the api `db` capability. Marshals `AdminDatabaseLike` and `TenantScopedDatabaseLike` calls — including transactions and cursor streams —… | +| [`@suaveplan/api-events-in-memory`](./api-events-in-memory/README.md) | In-memory events bus adapter for the `@suaveplan/api` testing kit. Wraps `@suaveplan/events`' production `EventBus` with a per-topic recording layer so tests c… | +| [`@suaveplan/api-events-worker-proxy`](./api-events-worker-proxy/README.md) | Worker-tier proxy over a main-process `@suaveplan/events` `EventBus`. | +| [`@suaveplan/api-graphql`](./api-graphql/README.md) | Stage-1 abstract GraphQL contract for the Suaveplan API plugin system. | +| [`@suaveplan/api-graphql-apollo`](./api-graphql-apollo/README.md) | Stage-7 Apollo Server GraphQL engine adapter for the Suaveplan API plugin system. Implements the `GraphqlEngine` contract from `@suaveplan/api-graphql` and pas… | +| [`@suaveplan/api-graphql-ui-altair`](./api-graphql-ui-altair/README.md) | Altair GraphQL UI plugin for the Suaveplan API plugin system. Structural sibling of `@suaveplan/api-graphql-ui-graphiql`. | +| [`@suaveplan/api-graphql-ui-graphiql`](./api-graphql-ui-graphiql/README.md) | GraphiQL UI mount for the Suaveplan API plugin system. Stage 7 of the umbrella plan. | +| [`@suaveplan/api-graphql-yoga`](./api-graphql-yoga/README.md) | Stage-7 GraphQL Yoga engine adapter. **Default GraphQL engine** for the Suaveplan API plugin system per design doc §10.5 — Bun-friendly, fastest for our usage… | +| [`@suaveplan/api-host`](./api-host/README.md) | Host orchestration core for the Suaveplan API plugin system. Provides the stable error-code registry (HOST/PLUGIN/RELOAD/CAPABILITY/ADMIN/LEDGER), the author-facing definePlugin DX, the runtime CapabilityRegistry, the LifecycleDriver + ReloadDriver + PluginLedger + admin Hono sub-router, the ErrorBoundary, the §6 11-step RequestPipeline, the top-level createHost(config) entry point composing every internal driver, and the HostInstruments registry covering the §12.3 metric surface. The ./testing subpath is reserved for test utilities. | +| [`@suaveplan/api-jobs-worker-proxy`](./api-jobs-worker-proxy/README.md) | Bidirectional `MessagePort` proxy that lets a worker-isolated API plugin participate in the host's main-process job scheduler. The worker calls `registerCron`… | +| [`@suaveplan/api-lifecycle`](./api-lifecycle/README.md) | Stage-1 contract package for the Suaveplan API plugin system: the plugin-lifecycle finite state machine definition, the legal-transition table, the side-effect… | +| [`@suaveplan/api-loader`](./api-loader/README.md) | Stage-1 contract package for the Suaveplan API plugin system. | +| [`@suaveplan/api-logger-worker-proxy`](./api-logger-worker-proxy/README.md) | Stage-3 worker → main proxy for `@suaveplan/logger`. Lets a worker-isolated API plugin call a normal `LoggerLike` surface while the records cross a `MessagePor… | +| [`@suaveplan/api-manifest`](./api-manifest/README.md) | Stage-1 contract package of the Suaveplan API plugin system: Zod schemas, parser, cross-field validators, dependency-graph resolver, capability resolver, and c… | +| [`@suaveplan/api-migrations`](./api-migrations/README.md) | Database-agnostic migration runner for the Suaveplan API. Ships a narrow `MigrationAdapter` surface (six methods), three shipped adapters (`surrealql`, `postgr… | +| [`@suaveplan/api-openapi`](./api-openapi/README.md) | OpenAPI 3.1 registry, typed `RouteBuilder`, schema registry, and document merger for the Suaveplan API. Single source of truth that wires into Hono via `OpenAP… | +| [`@suaveplan/api-openapi-ui-redoc`](./api-openapi-ui-redoc/README.md) | Stage-8 ReDoc UI adapter for the Suaveplan api-host. Mounts the ReDoc HTML shell at `/docs/ui/redoc` (or any caller-chosen path) via `createRedocUiHandler` and… | +| [`@suaveplan/api-openapi-ui-scalar`](./api-openapi-ui-scalar/README.md) | Scalar UI adapter for the Suaveplan OpenAPI plugin system. | +| [`@suaveplan/api-openapi-ui-swagger`](./api-openapi-ui-swagger/README.md) | Swagger UI adapter for the `/docs/ui/swagger` endpoint of the Suaveplan API plugin system (Stage 8.8). Returns a pure HTTP handler whose response is a `text/ht… | +| [`@suaveplan/api-plugin`](./api-plugin/README.md) | Plugin-system foundation for the Suaveplan API. Universal — runs unchanged in Bun, Node, and the browser. | +| [`@suaveplan/api-plugin-audit`](./api-plugin-audit/README.md) | Hono plugin that wraps `@suaveplan/audit-logging` as a write-through audit trail for `@suaveplan/api`. Installs a global per-request audit middleware (method /… | +| [`@suaveplan/api-plugin-auth`](./api-plugin-auth/README.md) | Better-Auth-first authentication plugin for `@suaveplan/api`. The canonical exemplar of the 3-way plug-and-play contract every `@suaveplan/api-plugin-*` packag… | +| [`@suaveplan/api-plugin-campaigns`](./api-plugin-campaigns/README.md) | Campaigns + suppression + delivery-webhooks HTTP plugin for `@suaveplan/api`. Mounts the `/campaigns`, `/suppression`, and `/webhooks` route trees on a Hono `O… | +| [`@suaveplan/api-plugin-cms`](./api-plugin-cms/README.md) | Headless content-management primitives for `@suaveplan/api`. Ships an in-memory `CmsEngine` that manages flexible content models, content entries with a `draft… | +| [`@suaveplan/api-plugin-database`](./api-plugin-database/README.md) | SurrealDB-backed database plugin for `@suaveplan/api`. Pools `@suaveplan/surrealdb`'s `SurrealAdapter` (implementing `@suaveplan/db`'s `DatabaseAdapter`), runs… | +| [`@suaveplan/api-plugin-event-bus`](./api-plugin-event-bus/README.md) | Typed event-bus plugin for `@suaveplan/api`. Wraps `@suaveplan/events` (pub/sub, async dispatch, interceptors, bounded-queue backpressure, idempotent listener… | +| [`@suaveplan/api-plugin-events`](./api-plugin-events/README.md) | Event-management plugin for `@suaveplan/api`. Ships a SurrealDB-backed `EventRepository` + `RsvpRepository` pair, ten Hono OpenAPI routes (list / get / create… | +| [`@suaveplan/api-plugin-example`](./api-plugin-example/README.md) | Reference plugin for the `@suaveplan/api-host` plugin system. The package is a load-bearing integration target, not a tutorial: every contract surface the host… | +| [`@suaveplan/api-plugin-export`](./api-plugin-export/README.md) | Data-export plugin for `@suaveplan/api`. Turns any registered resource into a CSV (RFC 4180), JSON, or XLSX (SpreadsheetML XML) blob through three self-contain… | +| [`@suaveplan/api-plugin-file-upload`](./api-plugin-file-upload/README.md) | Multipart and chunked file-upload plugin for `@suaveplan/api`. Ships six OpenAPI-typed Hono routes, a pluggable storage + session-store contract, SHA-256 hash… | +| [`@suaveplan/api-plugin-graphql`](./api-plugin-graphql/README.md) | GraphQL description + resolver-composition layer for `@suaveplan/api`. Server-tier — runs in Bun and Node. | +| [`@suaveplan/api-plugin-import`](./api-plugin-import/README.md) | Tabular-data ingest plugin for `@suaveplan/api`. Parses CSV / JSON / TSV-XLSX payloads, applies declarative column mappings + per-field validation + computed f… | +| [`@suaveplan/api-plugin-notifications`](./api-plugin-notifications/README.md) | SurrealDB-backed notifications + push plugin for `@suaveplan/api`. Ships a `NotificationRepository` + `DeviceTokenRepository` pair, an `ApnService` with a plug… | +| [`@suaveplan/api-plugin-payment`](./api-plugin-payment/README.md) | Payment-lifecycle plugin for `@suaveplan/api`. Wraps `@suaveplan/payment` + a caller-injected `PaymentProvider` (Stripe / Adyen / PayPal / Square / Mollie / cu… | +| [`@suaveplan/api-plugin-rate-limit`](./api-plugin-rate-limit/README.md) | Rate-limit plugin for `@suaveplan/api`. Wraps `@suaveplan/rate-limiter` as a `definePlugin` descriptor exposing per-route + per-tenant configuration, parameter… | +| [`@suaveplan/api-plugin-search`](./api-plugin-search/README.md) | Full-text search plugin for `@suaveplan/api`. Brings TF-weighted relevance scoring, four built-in text analyzers (`standard`, `simple`, `whitespace`, `keyword`… | +| [`@suaveplan/api-plugin-site`](./api-plugin-site/README.md) | Multi-site / multi-domain management plugin for `@suaveplan/api`. Stores `site` records (name, slug, theme, settings, push config) in SurrealDB, resolves incom… | +| [`@suaveplan/api-plugin-sse`](./api-plugin-sse/README.md) | Server-Sent Events plugin for `@suaveplan/api`. Registers a typed `sseService` in the host `ServiceRegistry`, mounts a Hono streaming handler at `GET /sse/:cha… | +| [`@suaveplan/api-plugin-tenant`](./api-plugin-tenant/README.md) | Multi-tenancy plugin for `@suaveplan/api`. Wraps `@suaveplan/api-tenant`'s resolver chain (header / subdomain / domain / path / JWT / query / cookie) as a firs… | +| [`@suaveplan/api-plugin-user`](./api-plugin-user/README.md) | User-profile CRUD plugin for `@suaveplan/api`. Mounts the canonical `/users/me` GET/PATCH/DELETE surface on top of `@suaveplan/api-plugin-auth`, registers a ty… | +| [`@suaveplan/api-plugin-vault`](./api-plugin-vault/README.md) | Per-user vault HTTP plugin for `@suaveplan/api`. Third instance of the 3-way plug-and-play contract every `@suaveplan/api-plugin-*` package follows: the plugin… | +| [`@suaveplan/api-plugin-webhook`](./api-plugin-webhook/README.md) | Signed outbound webhook delivery plugin for `@suaveplan/api`. Wraps `@suaveplan/webhook-client` behind a `definePlugin` descriptor, registers a typed `webhookS… | +| [`@suaveplan/api-rate-limit`](./api-rate-limit/README.md) | Per-route / per-principal / per-tenant / per-IP token-bucket rate-limit middleware for `@suaveplan/api`. Implements the `RequestRateLimiter` contract consumed… | +| [`@suaveplan/api-rbac`](./api-rbac/README.md) | Scope + rule-based authorisation middleware for the Suaveplan API plugin system. Produces a framework-agnostic `Middleware` that consumes the resolved `Princip… | +| [`@suaveplan/api-router`](./api-router/README.md) | Stage-1 contract package for the Suaveplan API plugin system. | +| [`@suaveplan/api-router-hono`](./api-router-hono/README.md) | Stage-4 concrete Hono router adapter for `@suaveplan/api`. Implements the abstract `Router` contract from `@suaveplan/api-router` on top of a Hono `Hono` insta… | +| [`@suaveplan/api-router-in-memory`](./api-router-in-memory/README.md) | Stage-5 in-memory router adapter for `@suaveplan/api`. Implements both the abstract `Router` contract from `@suaveplan/api-router` AND the `PipelineRouter` con… | +| [`@suaveplan/api-router-worker-bridge`](./api-router-worker-bridge/README.md) | Stage-3 HTTP bridge that marshals Fetch `Request` and `Response` objects across the worker boundary. Pairs a main-side `dispatch` with a worker- side handler o… | +| [`@suaveplan/api-saga`](./api-saga/README.md) | Saga orchestrator for the Suaveplan API plugin system. Drives manifest-declared multi-plugin workflows in declared order with reverse-order compensation on fai… | +| [`@suaveplan/api-sandbox-permissions`](./api-sandbox-permissions/README.md) | Permission model for sandboxed-tier API plugins. Centralises the `permissions.fs[]` / `permissions.fetch[]` allowlists, the `permissions.budgets` enforcement,… | +| [`@suaveplan/api-sandbox-vm`](./api-sandbox-vm/README.md) | `vm.Context`-based sandbox host for Suaveplan API plugins running in the sandboxed tier. The package owns the `vm.Context`+frozen-globals half of the design do… | +| [`@suaveplan/api-sandbox-vm-host-bridge`](./api-sandbox-vm-host-bridge/README.md) | Host-integration bridge that lets a `VmSandboxHandle` from `@suaveplan/api-sandbox-vm` install into `@suaveplan/api-host` as a first-class plugin. | +| [`@suaveplan/api-sandbox-wasm`](./api-sandbox-wasm/README.md) | Stage-8 WebAssembly sandbox host. Instantiates a sandboxed-tier plugin WASM module against a WASI snapshot preview1 implementation derived from the plugin's `P… | +| [`@suaveplan/api-sandbox-wasm-host-bridge`](./api-sandbox-wasm-host-bridge/README.md) | Host-integration layer that wraps a `@suaveplan/api-sandbox-wasm` `WasmSandboxHandle` as a `@suaveplan/api-host` `PluginModule`. Sandboxed-tier plugins compile… | +| [`@suaveplan/api-schemas`](./api-schemas/README.md) | Shared Zod schemas describing Suaveplan API request/response shapes. The single source of truth for server plugins, React data hooks, and generated OpenAPI doc… | +| [`@suaveplan/api-secrets`](./api-secrets/README.md) | Abstract Secrets contract for the Suaveplan API plugin system — per-plugin secret access typed against `manifest.secrets[]`, canonical redaction marker, frozen… | +| [`@suaveplan/api-secrets-bun`](./api-secrets-bun/README.md) | Stage-8 `SecretsLike` adapter backed by `Bun.secrets` (macOS Keychain, Linux libsecret, Windows Credential Manager) with per-plugin allow-list enforcement, OS-… | +| [`@suaveplan/api-secrets-env`](./api-secrets-env/README.md) | Stage-4 `SecretsLike` adapter backed by `process.env` / `Bun.env` with per-plugin allowed-keys enforcement. | +| [`@suaveplan/api-secrets-vault`](./api-secrets-vault/README.md) | Stage-8 `SecretsLike` adapter backed by `@suaveplan/vault`. The vault is passed in already unlocked by the host's startup sequence; the adapter never sees the… | +| [`@suaveplan/api-secrets-worker-proxy`](./api-secrets-worker-proxy/README.md) | Stage-3 worker → main `SecretsLike` proxy for the API plugin system. | +| [`@suaveplan/api-sse`](./api-sse/README.md) | Abstract Server-Sent Events contracts for `@suaveplan/api`. Stage-1 contract package: defines the engine-side `SseConnection`, `SseBroker`, `ReplayBuffer` (Las… | +| [`@suaveplan/api-sse-bun`](./api-sse-bun/README.md) | `Bun.serve`-backed Server-Sent Events engine for the `@suaveplan/api` plugin system. Implements the abstract `@suaveplan/api-sse` contract and passes `runSseEn… | +| [`@suaveplan/api-tenant`](./api-tenant/README.md) | Multi-tenant resolution + scoping for the Suaveplan API. Server-tier — runs on Bun and Node, depends on `hono` and `node:async_hooks`. | +| [`@suaveplan/api-tenant-provider`](./api-tenant-provider/README.md) | Abstract `TenantProvider` contract for the Suaveplan API plugin system. Enumerates the universe of tenants known to a host so per-tenant cron / queued jobs (ma… | +| [`@suaveplan/api-tenant-provider-memory`](./api-tenant-provider-memory/README.md) | In-memory reference implementation of the `@suaveplan/api-tenant-provider` `TenantProvider` contract. Backed by an insertion-ordered `MapWASM compiler closing **Stage-8 gate 2.8**. Thin orchestrator around `Bun.build` (bundle) + an injected WASI-stdio ABI shim + **Javy v8.1.1** (JS->WASM) +… | + diff --git a/docs/api-stack/api/_intro.md b/docs/api-stack/api/_intro.md new file mode 100644 index 0000000..fe483f4 --- /dev/null +++ b/docs/api-stack/api/_intro.md @@ -0,0 +1 @@ +API orchestration, plugin lifecycle, routing, workers, and tenant resolution. diff --git a/docs/api-stack/api/api-2pc/README.md b/docs/api-stack/api/api-2pc/README.md new file mode 100644 index 0000000..841ec23 --- /dev/null +++ b/docs/api-stack/api/api-2pc/README.md @@ -0,0 +1,109 @@ +# @suaveplan/api-2pc - Two-phase commit coordinator for the Suaveplan API plugin system. + +Two-phase commit coordinator for the Suaveplan API plugin system. Drives Postgres PREPARE TRANSACTION / COMMIT PREPARED / ROLLBACK PREPARED across registered participants with a host-owned ledger in suaveplan_2pc_transactions. Refuses non-preparable engines as writers (SQLite, SurrealDB) but accepts them as read-only voters. Default timeoutMs 5000, hard ceiling 30000, default outstanding-prepared cap 256, all operator-tunable. Ships boot-time orphan resolution via pg_prepared_xacts, the full TWOPC_* error namespace, OTel transaction/prepare/commit/rollback spans plus prepare_duration_ms / commit_duration_ms histograms / transactions_total counter / outstanding_prepared gauge, and run2pcParticipantConformance on the ./testing subpath. Server-tier — Bun + Node. + +> **Postgres-only writer surface.** SQLite and SurrealDB cannot honour +> `PREPARE TRANSACTION` and are refused as writers at install time. +> They MAY participate as read-only voters that contribute a +> `commit`/`abort` vote based on their own consistency check, but the +> coordinator never sends them prepare / commit / rollback SQL. + + +## Documentation tree + +- [coordinator](./src/coordinator/coordinator.md) — Top-level orchestration for the 2PC protocol. `createTwoPcCoordinator` builds a fully-wired coordinator that holds a pa… + - [coordinator](./src/coordinator/coordinator.md) — Top-level orchestration for the 2PC protocol. `createTwoPcCoordinator` builds a fully-wired coordinator that holds a pa… +- [error-codes](./src/error-codes/error-codes.md) — This module owns the `TWOPC_*` error-code namespace and the `TwoPcError` concrete class for the `@suaveplan/api-2pc` pa… + - [error-codes](./src/error-codes/error-codes.md) — This module owns the `TWOPC_*` error-code namespace and the `TwoPcError` concrete class for the `@suaveplan/api-2pc` pa… +- [instruments](./src/instruments/instruments.md) — Builds the OTel instrument registry the 2PC coordinator emits against on every transaction. Each instrument's name foll… + - [instruments](./src/instruments/instruments.md) — Builds the OTel instrument registry the 2PC coordinator emits against on every transaction. Each instrument's name foll… +- [outstanding-cap](./src/limits/outstanding-cap.md) — Admission control for in-flight 2PC transactions. The coordinator holds a fixed-size budget of "outstanding prepared tr… +- [timeout-ceiling](./src/limits/timeout-ceiling.md) — Enforces the hard 30 000 ms ceiling on caller-supplied `timeoutMs` values. The check fires at the public entry point of… +- [options](./src/options/options.md) — Defines the boundary-validated option shape consumed by `createTwoPcCoordinator`. Every tunable that affects coordinato… + - [options](./src/options/options.md) — Defines the boundary-validated option shape consumed by `createTwoPcCoordinator`. Every tunable that affects coordinato… +- [persistence](./src/persistence/persistence.md) — Persists every coordinator state transition into the `suaveplan_2pc_transactions` ledger table. The table is owned by `… + - [persistence](./src/persistence/persistence.md) — Persists every coordinator state transition into the `suaveplan_2pc_transactions` ledger table. The table is owned by `… +- [commit](./src/phases/commit.md) — Phase-2 commit for a single participant. Once every participant has returned `commit` from phase 1 and the coordinator… +- [gid](./src/phases/gid.md) — Builds and parses the global transaction id (gid) string passed to Postgres' `PREPARE TRANSACTION ''`. The format… +- [prepare](./src/phases/prepare.md) — Implements phase 1 of the 2PC protocol for a single participant. The coordinator iterates participants and calls this m… +- [rollback](./src/phases/rollback.md) — Phase-2 rollback for a single participant. Used both by the coordinator's abort path (vote_abort or prepare failure) an… +- [recovery](./src/recovery/recovery.md) — Boot-time orphan resolution for the 2PC coordinator. When a host crashes between phase 1 and phase 2, prepared transact… + - [recovery](./src/recovery/recovery.md) — Boot-time orphan resolution for the 2PC coordinator. When a host crashes between phase 1 and phase 2, prepared transact… +- [registry](./src/registry/participant-registry.md) — The participant registry is the install-time admission control between plugins and the 2PC coordinator. Plugins declare… + - [participant-registry](./src/registry/participant-registry.md) — The participant registry is the install-time admission control between plugins and the 2PC coordinator. Plugins declare… +- [testing](./src/testing/conformance.md) — Provides `run2pcParticipantConformance(factory)` — a runnable test suite that pins the contract every 2PC writer partic… + - [conformance](./src/testing/conformance.md) — Provides `run2pcParticipantConformance(factory)` — a runnable test suite that pins the contract every 2PC writer partic… + + +## Why + +Some cross-database workflows demand atomic visibility — no partial +state, no eventual convergence. Per the API Plugin Foundation design +doc §9.2 the coordinator runs phase-1 prepare across every registered +participant, persists the vote tally to `suaveplan_2pc_transactions` +on the host's metadata DB, then issues `COMMIT PREPARED` or +`ROLLBACK PREPARED` against every writer participant. Recovery on the +next boot resolves any prepared transactions left over from a host +crash. + +## Modules + +- `coordinator/` — `createTwoPcCoordinator` + `run2pc` factory and + state machine. +- `registry/` — `TwoPcParticipantRegistry` (admission control). +- `phases/` — `preparePhaseOne`, `commitPhaseTwo`, `rollbackPhaseTwo`, + `gid` helpers. +- `persistence/` — `TwoPcLedgerStore` over the host-owned + `suaveplan_2pc_transactions` table. +- `recovery/` — boot-time orphan resolution via `pg_prepared_xacts`. +- `limits/` — `OutstandingPreparedCap` (admission), `assertTimeoutBelowCeiling` + (per-call ceiling). +- `instruments/` — OTel meter/tracer bundle. +- `options/` — Zod-validated coordinator options + defaults. +- `error-codes/` — 10 `TWOPC_*` codes + `TwoPcError`. +- `types/` — `Run2PcInput`, `Run2PcOutcome`, participant + state types. +- `testing/` — `run2pcParticipantConformance(factory)` suite. + +## Quick start + +```ts +import { createTwoPcCoordinator } from "@suaveplan/api-2pc"; + +const coordinator = createTwoPcCoordinator({ + options: { hostInstanceId: "host-01" }, + registry, + ledgerDb, + clock: () => Date.now(), + idGenerator: () => crypto.randomUUID(), +}); + +const outcome = await coordinator.run2pc({ + participants: [ + { id: "billing", input: { invoiceId: "inv-1" } }, + { id: "inventory", input: { sku: "abc-9" } }, + ], +}); +// outcome.state is "committed" | "aborted" | "in_doubt" +``` + +## Defaults + +- `timeoutMs`: **5000** (operator-tunable per-call up to the + 30000 ms ceiling). +- `outstandingPreparedCap`: **256** (operator-tunable via host + config). + +## Error namespace + +Every production code path throws `TwoPcError` with one of the ten +`TWOPC_*` codes. See `src/error-codes/error-codes.md` for the full +catalogue. + +## Conformance + +Every adapter implementing a writer participant MUST run +`run2pcParticipantConformance({ create: ... })` in a +`tests/conformance/run-2pc-participant.test.ts` file. The harness +pins prepare / commit / rollback semantics and the idempotency +contract. + diff --git a/docs/api-stack/api/api-2pc/src/coordinator/coordinator.md b/docs/api-stack/api/api-2pc/src/coordinator/coordinator.md new file mode 100644 index 0000000..fcde5f1 --- /dev/null +++ b/docs/api-stack/api/api-2pc/src/coordinator/coordinator.md @@ -0,0 +1,150 @@ +# `coordinator/` + + +_(no submodules)_ + + +## Purpose + +Top-level orchestration for the 2PC protocol. `createTwoPcCoordinator` +builds a fully-wired coordinator that holds a participant registry, a +ledger store, an admission counter, and an OTel instrument bundle. +The `run2pc({ participants, timeoutMs? })` entry point owns the full +state machine described in design doc §9.2: + +1. Admission via the outstanding-prepared cap. +2. Ledger insert at `voting`. +3. Phase-1 prepare per participant, with the + `2pc.prepare_duration_ms` histogram and a `2pc.prepare` span per + participant. +4. Either unanimous commit → `markAllVotedCommit` → phase-2 + `COMMIT PREPARED` per writer; OR any abort/error → + `markAborting` → phase-2 `ROLLBACK PREPARED` per prepared writer. +5. Terminal ledger stamp (`committed` / `aborted` / `in_doubt`). + +The coordinator is the only path application code ever touches. +Every smaller module (phases, persistence, recovery, limits) is +internal plumbing this factory composes. + +## Features + +- Single public surface: `createTwoPcCoordinator(deps)` returns + `{ run2pc, outstandingCount, options }`. +- Default `timeoutMs` from options (5000), per-call override accepted + up to the 30000 ceiling (enforced via + `limits/timeout-ceiling`). +- Admission cap (default 256) enforced via + `limits/outstanding-cap`; over-cap calls fail with + `TWOPC_OUTSTANDING_LIMIT_EXCEEDED` before any participant is + contacted. +- Hooks every documented OTel instrument (`2pc.transaction` span, + `2pc.prepare` / `2pc.commit` / `2pc.rollback` child spans, + `2pc.transactions_total` counter, `prepare`/`commit_duration_ms` + histograms, `outstanding_prepared` gauge). +- Ledger persistence is bidirectional — every state transition writes + through `TwoPcLedgerStore`, so the recovery runner has a full audit + trail on restart. +- Abort handling: vote_abort, prepare_failed, and timeout all funnel + to the rollback branch; rollback errors escalate to `in_doubt` + rather than failing the rollback path itself. + +## Usage: Basic + +```ts +import { createTwoPcCoordinator } from "@suaveplan/api-2pc/coordinator"; + +const coordinator = createTwoPcCoordinator({ + options: { hostInstanceId: "host-01" }, + registry, + ledgerDb, + clock: () => Date.now(), + idGenerator: () => crypto.randomUUID(), +}); + +const outcome = await coordinator.run2pc({ + participants: [ + { id: "billing", input: { invoiceId: "inv-1" } }, + { id: "inventory", input: { sku: "abc-9" } }, + ], +}); +console.log(outcome.state); // "committed" | "aborted" | "in_doubt" +``` + +## Usage: Advanced + +Inject a custom instruments bundle to feed a hand-rolled +MeterProvider, override the default timeout per call, and consume the +per-participant vote summary on the outcome: + +```ts +import { createTwoPcCoordinator } from "@suaveplan/api-2pc/coordinator"; +import { createTwoPcInstruments } from "@suaveplan/api-2pc/instruments"; + +const instruments = createTwoPcInstruments({ + meterProvider, + outstandingPreparedSnapshot: () => coordinator.outstandingCount(), +}); + +const coordinator = createTwoPcCoordinator({ + options: { + hostInstanceId: "host-01", + defaultTimeoutMs: 10_000, + outstandingPreparedCap: 64, + }, + registry, + ledgerDb, + clock: () => Date.now(), + idGenerator: () => crypto.randomUUID(), + instruments, +}); + +const outcome = await coordinator.run2pc({ + participants: [ + { id: "billing", input: { invoiceId } }, + { id: "audit", input: { event: "invoice.created" } }, + ], + timeoutMs: 2_500, +}); +for (const v of outcome.votes) { + auditLog.append({ + txId: outcome.txId, + participant: v.participantId, + vote: v.vote, + }); +} +``` + +## API Reference + +- `interface TwoPcCoordinatorDeps` + - `options: TwoPcCoordinatorOptions` + - `registry: TwoPcParticipantRegistry` + - `ledgerDb: LedgerDb` + - `clock: Clock` + - `idGenerator: IdGenerator` + - `instruments?: TwoPcInstruments` +- `interface TwoPcCoordinator` + - `run2pc(input: Run2PcInput): Promise` + - `outstandingCount(): number` + - `options: ResolvedTwoPcCoordinatorOptions` +- `createTwoPcCoordinator(deps): TwoPcCoordinator` — factory. + +## Implementation Notes + +The function is structured as one large `try` / `finally` so cleanup +(span end, deadline timer clear, admission release) runs regardless +of which branch fires. The pattern keeps the happy path linear and +the failure paths exhaustive without nested try blocks. + +The "any commit failure → in_doubt" escalation is deliberate. Once +the coordinator has issued `COMMIT PREPARED` against at least one +participant, the only correct follow-up is to keep trying — but the +hot path cannot block on that. Instead, the row is marked `in_doubt`, +the OTel counter ticks the `in_doubt` outcome, and the recovery +runner picks it up on the next boot. + +Vote-abort and prepare-failed paths both call `ac.abort()` BEFORE +running phase 2, so any prepared participants whose subsequent SQL +hits the signal map to `TWOPC_TIMEOUT` rather than getting stuck. The +deadline timer is cleared in the `finally` so a successful commit +does not leave a dangling abort handle on the AbortController. diff --git a/docs/api-stack/api/api-2pc/src/error-codes/error-codes.md b/docs/api-stack/api/api-2pc/src/error-codes/error-codes.md new file mode 100644 index 0000000..3cbcfb6 --- /dev/null +++ b/docs/api-stack/api/api-2pc/src/error-codes/error-codes.md @@ -0,0 +1,97 @@ +# `error-codes/` + + +_(no submodules)_ + + +## Purpose + +This module owns the `TWOPC_*` error-code namespace and the `TwoPcError` +concrete class for the `@suaveplan/api-2pc` package. The registry is the +canonical contract every production code path in the coordinator throws +against — observability dashboards, support runbooks, and integrating +plugins all join on these stable string codes. + +The codes are intentionally enumerated up-front rather than grown +ad-hoc: a missing code is a spec deviation that a CI gate can detect, +and the closed set lets operators write alerting rules without +constantly chasing schema drift. + +## Features + +- Ten stable codes (`TIMEOUT`, `VOTE_ABORT`, `PREPARE_FAILED`, + `COMMIT_FAILED`, `ROLLBACK_FAILED`, `IN_DOUBT`, + `PARTICIPANT_NOT_PREPARABLE`, `READ_ONLY_PARTICIPANT_CANNOT_WRITE`, + `OUTSTANDING_LIMIT_EXCEEDED`, `TIMEOUT_CEILING_EXCEEDED`). +- Each code is exposed via `TWOPC_CODES.` returning the prefixed + string `"TWOPC."` produced by `defineCodes`. +- `TwoPcError` extends `SuaveplanError` so cause-chain traversal, + Zod-validated wire format, and the OTel span-event adapter from + `@suaveplan/error` all apply unchanged. + +## Usage: Basic + +```ts +import { TWOPC_CODES, TwoPcError } from "@suaveplan/api-2pc/error-codes"; + +throw new TwoPcError( + TWOPC_CODES.TIMEOUT, + "Phase-1 deadline elapsed", + { context: { txId, timeoutMs: 5000 } } +); +``` + +## Usage: Advanced + +Branching on error code at the boundary between coordinator and caller +is the recommended consumer pattern. The narrowed `twoPcCode` field +gives an exhaustive switch the compiler can check: + +```ts +import { TWOPC_CODES, TwoPcError } from "@suaveplan/api-2pc/error-codes"; + +try { + await run2pc({ participants, timeoutMs: 5000 }, ctx); +} catch (err) { + if (err instanceof TwoPcError) { + switch (err.twoPcCode) { + case TWOPC_CODES.TIMEOUT: + metrics.incr("billing.2pc.timeout"); + return retryWithBackoff(); + case TWOPC_CODES.VOTE_ABORT: + return surfaceUserError(); + case TWOPC_CODES.IN_DOUBT: + pageOncall(err); + return; + default: + throw err; + } + } + throw err; +} +``` + +## API Reference + +- `TWOPC_CODES` — frozen object `{ TIMEOUT: "TWOPC.TIMEOUT", ... }`. +- `type TwoPcErrorCode` — string-literal union of every value in + `TWOPC_CODES`. +- `class TwoPcError extends SuaveplanError` — exposes + `twoPcCode` as a same-typed accessor for ergonomic narrowing without + re-asserting at every catch site. + +## Implementation Notes + +`defineCodes` from `@suaveplan/error` produces the prefixed values at +runtime, so every code string starts with `"TWOPC."`. This matches the +prefix convention used by sibling api-stack packages (`HOST.*`, +`PLUGIN.*`, `RELOAD.*`, `LEDGER.*`). The `TwoPcError` class carries a +redundant `twoPcCode` field — duplicating `code` — purely to give +callers a name they don't have to import the generic +`SuaveplanError` type to narrow against. The duplication is +deliberate and harmless because the base class makes `code` readonly. + +The registry is closed; adding a code requires an OpenSpec change so +every consumer dashboard and runbook stays in sync. Coverage assertions +ensure every code is actually thrown by a production path before this +package can graduate to `1.0.0`. diff --git a/docs/api-stack/api/api-2pc/src/instruments/instruments.md b/docs/api-stack/api/api-2pc/src/instruments/instruments.md new file mode 100644 index 0000000..af31281 --- /dev/null +++ b/docs/api-stack/api/api-2pc/src/instruments/instruments.md @@ -0,0 +1,105 @@ +# `instruments/` + + +_(no submodules)_ + + +## Purpose + +Builds the OTel instrument registry the 2PC coordinator emits against +on every transaction. Each instrument's name follows design doc §9.2 +exactly so a missing entry is a spec deviation a CI gate could detect. +Centralising creation keeps the coordinator code free of meter / tracer +plumbing — every phase module simply records against the frozen +bundle returned here. + +The observable gauge wires into the coordinator's outstanding-prepared +counter via a snapshot callback, so dashboards see the live admission +state without the coordinator pushing on every change. + +## Features + +- One span: `2pc.transaction` per transaction lifetime; per-phase + child spans `2pc.prepare`, `2pc.commit`, `2pc.rollback` (started by + the phase modules themselves, using the tracer this bundle exposes). +- One counter: `2pc.transactions_total` labelled `{ outcome }`. +- Two histograms: `2pc.prepare_duration_ms`, `2pc.commit_duration_ms` + labelled `{ outcome }`. +- One observable gauge: `2pc.outstanding_prepared` wired to a + snapshot callback supplied at construction. +- Provider defaults to the OTel globals (no-op when no SDK is + installed) so unit tests do not have to wire a provider. + +## Usage: Basic + +```ts +import { createTwoPcInstruments } from "@suaveplan/api-2pc/instruments"; + +const instruments = createTwoPcInstruments({ + outstandingPreparedSnapshot: () => coordinator.outstandingCount(), +}); + +instruments.transactionsTotal.add(1, { outcome: "committed" }); +``` + +## Usage: Advanced + +Inject a real OTel SDK and a custom snapshot to feed a live dashboard: + +```ts +import { metrics, trace } from "@opentelemetry/api"; +import { MeterProvider } from "@opentelemetry/sdk-metrics"; +import { createTwoPcInstruments } from "@suaveplan/api-2pc/instruments"; + +const meterProvider = new MeterProvider({ /* readers/exporters */ }); +metrics.setGlobalMeterProvider(meterProvider); + +const instruments = createTwoPcInstruments({ + meterProvider, + tracerProvider: trace.getTracerProvider(), + outstandingPreparedSnapshot: () => coordinator.outstandingCount(), +}); + +const span = instruments.tracer.startSpan("2pc.transaction", { + attributes: { "tx.id": txId, participant_count: 2 }, +}); +try { + // ... + instruments.prepareDurationMs.record(prepareElapsedMs, { + outcome: "committed", + }); +} finally { + span.end(); +} +``` + +## API Reference + +- `type TwoPcOutcome = "committed" | "aborted" | "in_doubt"` — values + attached to the `outcome` attribute on every counter / histogram + observation. +- `interface TwoPcInstrumentsConfig` + - `meterProvider?: MeterProvider` + - `tracerProvider?: TracerProvider` + - `outstandingPreparedSnapshot: () => number` +- `interface TwoPcInstruments` — frozen bundle exposing `meter`, + `tracer`, `transactionsTotal`, `prepareDurationMs`, + `commitDurationMs`, `outstandingPreparedGauge`. +- `createTwoPcInstruments(config): TwoPcInstruments` — factory. + +## Implementation Notes + +The observable gauge's callback fires whenever the SDK collects metrics +(typically on a fixed interval driven by the exporter). The snapshot +returned by `outstandingPreparedSnapshot` is therefore an +eventually-consistent value — operators must not treat it as a strict +upper bound for admission decisions. The strict upper bound is enforced +inside `limits/outstanding-cap.ts`; the gauge is purely a dashboard +signal. + +Histogram unit is set explicitly to `"ms"` per OTel naming convention. +The two histograms are named after the phases they measure so a single +dashboard panel can render side-by-side latency for prepare and commit +without re-labelling — operators flagging long prepares typically +care more about phase-1 latency because that is when row-level locks +are held on every participant. diff --git a/docs/api-stack/api/api-2pc/src/limits/outstanding-cap.md b/docs/api-stack/api/api-2pc/src/limits/outstanding-cap.md new file mode 100644 index 0000000..05595b0 --- /dev/null +++ b/docs/api-stack/api/api-2pc/src/limits/outstanding-cap.md @@ -0,0 +1,104 @@ +# `limits/outstanding-cap` + +## Purpose + +Admission control for in-flight 2PC transactions. The coordinator +holds a fixed-size budget of "outstanding prepared transactions"; once +the budget is exhausted new `run2pc` calls refuse rather than queue. +The default is 256 (design doc §14's open question, pinned by this +package's spec) and operators can tune it via host config. + +Refusing rather than queuing is intentional: Postgres holds row-level +locks for every prepared transaction, so a backed-up coordinator +would otherwise convert a transient overload into a global lock +storm. Failing fast lets callers route to a degraded path +(degraded-write, retry queue, etc.). + +## Features + +- `OutstandingPreparedCap` — synchronous counter with `admit()`, + `release()`, `snapshot()`, `capacity()`. +- Constructor validates that the cap is a positive integer (rejects + zero, negatives, fractions, `NaN`). +- `release()` is idempotent below zero — a buggy double-release in + caller code cannot silently expand the real cap. +- Synchronous-only — relies on the event-loop atomicity guarantee + between `admit` / `release` pairs in JavaScript runtimes. + +## Usage: Basic + +```ts +import { OutstandingPreparedCap } from "@suaveplan/api-2pc/limits"; + +const cap = new OutstandingPreparedCap(256); + +cap.admit(); +try { + // run the 2PC transaction +} finally { + cap.release(); +} +``` + +## Usage: Advanced + +Wrap admission inside the coordinator's public entry to centralise the +release in one `finally`. The snapshot fuels the OTel gauge: + +```ts +import { TWOPC_CODES, TwoPcError } from "@suaveplan/api-2pc/error-codes"; +import { OutstandingPreparedCap } from "@suaveplan/api-2pc/limits"; + +class MiniCoordinator { + private readonly cap = new OutstandingPreparedCap(256); + + snapshot() { + return this.cap.snapshot(); + } + + async run(fn: () => Promise): Promise { + try { + this.cap.admit(); + } catch (err) { + if ( + err instanceof TwoPcError && + err.twoPcCode === TWOPC_CODES.OUTSTANDING_LIMIT_EXCEEDED + ) { + // route to degraded path + throw err; + } + throw err; + } + try { + return await fn(); + } finally { + this.cap.release(); + } + } +} +``` + +## API Reference + +- `class OutstandingPreparedCap` + - `constructor(cap: number)` — throws + `TWOPC_OUTSTANDING_LIMIT_EXCEEDED` on invalid `cap`. + - `admit(): void` — throws + `TWOPC_OUTSTANDING_LIMIT_EXCEEDED` when at capacity. + - `release(): void` — idempotent below zero. + - `snapshot(): number` — current outstanding count. + - `capacity(): number` — configured cap. + +## Implementation Notes + +Construction-time validation re-uses the same error code as the +runtime cap-exceeded path. This is deliberate: operators tuning the +cap via host config want one error string to alert on, regardless of +whether the misconfiguration was a fractional value at startup or a +real overload at steady state. The context object on the thrown +`TwoPcError` distinguishes the two cases (`cap` only vs. +`cap` + `outstanding`). + +The class is intentionally tiny — no async, no internal queue, no +external dependencies. Adding a queue here would re-introduce the +lock-storm risk the cap exists to prevent. diff --git a/docs/api-stack/api/api-2pc/src/limits/timeout-ceiling.md b/docs/api-stack/api/api-2pc/src/limits/timeout-ceiling.md new file mode 100644 index 0000000..95cecd7 --- /dev/null +++ b/docs/api-stack/api/api-2pc/src/limits/timeout-ceiling.md @@ -0,0 +1,77 @@ +# `limits/timeout-ceiling` + +## Purpose + +Enforces the hard 30 000 ms ceiling on caller-supplied `timeoutMs` +values. The check fires at the public entry point of `run2pc` so +above-ceiling calls never contact a participant; the operational +warning in design doc §9.2 is that long prepares hold row-level locks, +so surfacing the misuse loudly is more useful than silently clamping. + +This module is intentionally tiny — one function — because the +behaviour is small but the gate is one of the most-asserted contracts +in the spec. + +## Features + +- `assertTimeoutBelowCeiling(timeoutMs)` — throws + `TWOPC_TIMEOUT_CEILING_EXCEEDED` for above-ceiling, non-positive, + non-finite, or `NaN` inputs. +- Re-uses the `TIMEOUT_CEILING_MS` constant from `options/` so the + ceiling stays a single source of truth. + +## Usage: Basic + +```ts +import { assertTimeoutBelowCeiling } from "@suaveplan/api-2pc/limits"; + +assertTimeoutBelowCeiling(5000); // ok +assertTimeoutBelowCeiling(30001); // throws TWOPC_TIMEOUT_CEILING_EXCEEDED +``` + +## Usage: Advanced + +The function is intentionally side-effect-free so callers can wrap it +in a per-tenant override path: + +```ts +import { TIMEOUT_CEILING_MS } from "@suaveplan/api-2pc/options"; +import { assertTimeoutBelowCeiling } from "@suaveplan/api-2pc/limits"; + +function resolveTimeout( + requested: number | undefined, + tenantMax: number +): number { + const effective = requested ?? DEFAULT_TIMEOUT_MS; + assertTimeoutBelowCeiling(effective); + if (effective > tenantMax) { + return tenantMax; + } + if (effective > TIMEOUT_CEILING_MS) { + // unreachable given the assert above — included only to + // illustrate that the ceiling acts as the strict upper bound. + return TIMEOUT_CEILING_MS; + } + return effective; +} +``` + +## API Reference + +- `function assertTimeoutBelowCeiling(timeoutMs: number): void` + - Throws `TwoPcError(TWOPC_CODES.TIMEOUT_CEILING_EXCEEDED)` for any + of: `NaN`, `Infinity`, `-Infinity`, values `<= 0`, values + `> TIMEOUT_CEILING_MS`. + +## Implementation Notes + +The check rejects non-positive values for the same reason it rejects +above-ceiling ones: an immediate or backwards-in-time deadline would +collapse phase 1 to a single tick and the rollback path would fire +before any participant could finish a real prepare. Treating that as +the same misuse class as "30 minutes" is a deliberate ergonomic +choice — operators get one error code to grep for. + +`Number.isFinite` is used in preference to `Number.isNaN` because the +former covers `Infinity` and `-Infinity` in addition to `NaN`. The +explicit `<= 0` check then excludes zero and negative-finite values. diff --git a/docs/api-stack/api/api-2pc/src/options/options.md b/docs/api-stack/api/api-2pc/src/options/options.md new file mode 100644 index 0000000..ab13824 --- /dev/null +++ b/docs/api-stack/api/api-2pc/src/options/options.md @@ -0,0 +1,96 @@ +# `options/` + + +_(no submodules)_ + + +## Purpose + +Defines the boundary-validated option shape consumed by +`createTwoPcCoordinator`. Every tunable that affects coordinator +behaviour (host instance id, outstanding-prepared cap, default phase-1 +timeout) lives here, with Zod validation at the seam and explicit +defaults pinned to the design doc §9.2 numbers. + +Centralising option resolution in one module keeps the coordinator +free of conditional fallback logic — by the time it sees the resolved +shape every field is concrete, so subsequent code never has to +re-check `undefined`. + +## Features + +- `DEFAULT_TIMEOUT_MS = 5000` — phase-1 deadline default per design + doc §9.2. +- `TIMEOUT_CEILING_MS = 30000` — hard ceiling enforced at call time + (the coordinator's `limits/timeout-ceiling` module imports this). +- `DEFAULT_OUTSTANDING_PREPARED_CAP = 256` — admission-control default + per design doc §14. +- `twoPcCoordinatorOptionsSchema` — Zod schema, `strict()` so typos + surface as Zod errors instead of being silently ignored. +- `resolveTwoPcCoordinatorOptions(raw)` — validates and fills in + defaults; returns the fully-populated `ResolvedTwoPcCoordinatorOptions` + shape the coordinator consumes. + +## Usage: Basic + +```ts +import { + DEFAULT_TIMEOUT_MS, + resolveTwoPcCoordinatorOptions, +} from "@suaveplan/api-2pc/options"; + +const resolved = resolveTwoPcCoordinatorOptions({ + hostInstanceId: "host-01", +}); + +console.log(resolved.defaultTimeoutMs === DEFAULT_TIMEOUT_MS); // true +``` + +## Usage: Advanced + +Override every default — useful for canary hosts where operators want +a tighter admission cap and a longer prepare window: + +```ts +import { resolveTwoPcCoordinatorOptions } from "@suaveplan/api-2pc/options"; + +const resolved = resolveTwoPcCoordinatorOptions({ + hostInstanceId: "canary-eu-west-1", + outstandingPreparedCap: 64, + defaultTimeoutMs: 15_000, +}); +``` + +Calls supplying `defaultTimeoutMs` above `TIMEOUT_CEILING_MS` raise a +Zod error at this boundary — the coordinator's runtime ceiling check +in `limits/timeout-ceiling.ts` then surfaces the misuse on per-call +overrides as well. + +## API Reference + +- `const DEFAULT_TIMEOUT_MS: number` — 5000. +- `const TIMEOUT_CEILING_MS: number` — 30000. +- `const DEFAULT_OUTSTANDING_PREPARED_CAP: number` — 256. +- `interface TwoPcCoordinatorOptions` — caller-supplied input shape. +- `interface ResolvedTwoPcCoordinatorOptions` — internal shape after + defaults. +- `const twoPcCoordinatorOptionsSchema: z.ZodType` — strict-shape + Zod schema. +- `function resolveTwoPcCoordinatorOptions(raw): ResolvedTwoPcCoordinatorOptions` + — validates and resolves defaults. + +## Implementation Notes + +The schema uses `.strict()` so unknown keys fail validation rather than +silently being dropped. The default for `defaultTimeoutMs` is applied +post-parse with `?? DEFAULT_TIMEOUT_MS` rather than via +`z.default(...)` so the schema continues to reject above-ceiling +values regardless of whether the caller supplied the field — Zod's +`default` would short-circuit `.max()` checks when the field is +omitted, which is the wrong shape for a ceiling-enforced option. + +The module deliberately does NOT re-throw Zod failures as +`TwoPcError` — that's the responsibility of the coordinator's +public entry points. Keeping this module pure of cross-package error +mapping makes it reusable from tests that want a raw Zod surface for +property-based shape testing. diff --git a/docs/api-stack/api/api-2pc/src/persistence/persistence.md b/docs/api-stack/api/api-2pc/src/persistence/persistence.md new file mode 100644 index 0000000..276a723 --- /dev/null +++ b/docs/api-stack/api/api-2pc/src/persistence/persistence.md @@ -0,0 +1,114 @@ +# `persistence/` + + +_(no submodules)_ + + +## Purpose + +Persists every coordinator state transition into the +`suaveplan_2pc_transactions` ledger table. The table is owned by +`@suaveplan/api-host` (migration id 2, `saga-2pc-reserved`); this +module only reads and writes rows so the host stays the single source +of truth for schema evolution. + +The ledger is what makes 2PC durable across coordinator restarts. +Without it, a host that crashes mid-prepare would lose track of which +participants were `PREPARE TRANSACTION`'d and could not safely choose +between commit and rollback on the next boot. + +## Features + +- `TwoPcLedgerStore` — CRUD facade over `suaveplan_2pc_transactions` + with statements for every state transition (`insert`, + `markAllVotedCommit`, `markAborting`, `markCommitted`, `markAborted`, + `markInDoubt`). +- `findById` — single-row lookup for state inspection. +- `findRecoverable` — scan returning every non-terminal row for the + current host instance id. Drives `recovery/`. +- `TwoPcLedgerStore.decodeParticipants` — static helper that parses the + `participants_json` blob back into a typed array. +- Structural `LedgerDb` / `LedgerStatement` interfaces so the store + works with `bun:sqlite`, `@suaveplan/db-sqlite`'s thin wrapper, and + `better-sqlite3` without any concrete dependency. + +## Usage: Basic + +```ts +import { Database } from "bun:sqlite"; +import { TwoPcLedgerStore } from "@suaveplan/api-2pc/persistence"; + +const db = new Database(":memory:"); +// Schema is created by api-host's migration runner — see migrations.ts +// migration id 2 (`saga-2pc-reserved`). In tests, run the host runner +// against the same database. + +const store = new TwoPcLedgerStore(db as never); +store.insert({ + id: "tx-1", + coordinator: "host-instance-01", + participants: [ + { participantId: "billing", voterMode: "writer", vote: null }, + ], +}); +``` + +## Usage: Advanced + +Walk the recovery candidates and decode each blob — the typical shape +used inside `recovery/recovery.ts`: + +```ts +import { TwoPcLedgerStore } from "@suaveplan/api-2pc/persistence"; + +function listRecoverable(store: TwoPcLedgerStore, hostId: string) { + const rows = store.findRecoverable(hostId); + return rows.map((row) => ({ + id: row.id, + state: row.state, + participants: TwoPcLedgerStore.decodeParticipants(row), + })); +} +``` + +The static `decodeParticipants` is deliberately exposed so callers +working with raw rows (e.g. ad-hoc admin scripts) do not have to +recreate the JSON contract themselves. + +## API Reference + +- `interface LedgerStatement` / `interface LedgerDb` — structural + SQLite-shaped views. +- `interface TwoPcLedgerRow` — exact row shape returned by `findById` + / `findRecoverable`. +- `interface LedgerParticipantEntry` — per-participant entry in + `participants_json`. +- `class TwoPcLedgerStore` + - `constructor(db: LedgerDb)` + - `insert({ id, coordinator, participants })` + - `markAllVotedCommit({ id, participants, preparedAt })` + - `markAborting({ id, participants })` + - `markCommitted(id, committedAt)` + - `markAborted(id, abortedAt)` + - `markInDoubt(id)` + - `findById(id): TwoPcLedgerRow | null` + - `findRecoverable(coordinator): readonly TwoPcLedgerRow[]` + - `static decodeParticipants(row): readonly LedgerParticipantEntry[]` + +## Implementation Notes + +Every UPDATE uses a single statement with the new `state` value +matched against `TwoPcCoordinatorState`'s string-literal union — the +`satisfies TwoPcCoordinatorState` annotation catches typos at compile +time. The store does NOT enforce a state machine on top of the table; +that responsibility belongs to the coordinator. Keeping the +persistence layer state-machine-free lets recovery use the same store +without conflating "what changed in this lifetime" with "what the row +looked like after a crash". + +The `participants_json` blob is stored as a JSON string rather than a +side table — the coordinator never queries by participant id, only by +transaction id, so a JSON blob has zero indexing cost and survives +schema evolution painlessly. `decodeParticipants` returns an empty +array when the blob is not an array — defensive against rows +hand-written by ad-hoc admin scripts. diff --git a/docs/api-stack/api/api-2pc/src/phases/commit.md b/docs/api-stack/api/api-2pc/src/phases/commit.md new file mode 100644 index 0000000..e94b550 --- /dev/null +++ b/docs/api-stack/api/api-2pc/src/phases/commit.md @@ -0,0 +1,94 @@ +# `phases/commit` + +## Purpose + +Phase-2 commit for a single participant. Once every participant has +returned `commit` from phase 1 and the coordinator has persisted the +`all-voted-commit` state to the ledger, this module emits +`COMMIT PREPARED ''` against each writer participant and records +`2pc.commit_duration_ms`. + +Phase 2 is intentionally unbounded by timeout — the protocol cannot +tolerate giving up on a commit-prepared mid-flight, because doing so +would leave the system in `in_doubt` state and require the recovery +runner to resolve it on the next boot. + +## Features + +- Skips participants that did not actually prepare (`outcome.prepared + === false`) — read-only voters and abort-voters never see commit + SQL. +- Emits a `2pc.commit` span with `tx.id`, `participant.id`, and `gid` + attributes. +- Records `2pc.commit_duration_ms` tagged with `outcome: "committed"` + on success. +- Failure preserves the underlying cause on a thrown + `TwoPcError(TWOPC_COMMIT_FAILED)`; the coordinator escalates to + `TWOPC_IN_DOUBT` once it has tried every participant. + +## Usage: Basic + +```ts +import { commitPhaseTwo } from "@suaveplan/api-2pc/phases"; + +await commitPhaseTwo({ + txId, + participant, + outcome: preparedOutcome, + instruments, +}); +``` + +## Usage: Advanced + +The coordinator collects per-participant failures rather than +short-circuiting — every participant gets attempted exactly once so +operators can see the full picture in the ledger: + +```ts +import { TWOPC_CODES, TwoPcError } from "@suaveplan/api-2pc/error-codes"; +import { commitPhaseTwo } from "@suaveplan/api-2pc/phases"; + +const failures: TwoPcError[] = []; +for (const outcome of preparedOutcomes) { + if (!outcome.prepared) continue; + try { + await commitPhaseTwo({ + txId, + participant: registry.get(outcome.participantId)!, + outcome, + instruments, + }); + } catch (err) { + if (err instanceof TwoPcError) failures.push(err); + else throw err; + } +} +if (failures.length > 0) { + // ledger.markInDoubt(txId); recovery resolves on next boot +} +``` + +## API Reference + +- `interface CommitPhaseInput` + - `txId: string` + - `participant: RegisteredTwoPcParticipant` + - `outcome: ParticipantPrepareOutcome` — the phase-1 result. + - `instruments: TwoPcInstruments` +- `function commitPhaseTwo(input): Promise` + - no-op for `outcome.prepared === false` + - throws `TwoPcError(TWOPC_COMMIT_FAILED)` on SQL failure. + +## Implementation Notes + +The gid stored on the prepare outcome is the single source of truth — +this module never rebuilds it. Reusing the prepare-time value +defends against the unlikely case where a host-config change between +phases would have produced a different gid: the SQL the coordinator +needs to send is exactly the one it prepared with. + +The SQL escape (`replace(/'/g, "''")`) matches the prepare-phase +treatment so a gid containing the unlikely quote character would +still produce valid SQL. The escape is cheap; the defence-in-depth +costs nothing on the happy path. diff --git a/docs/api-stack/api/api-2pc/src/phases/gid.md b/docs/api-stack/api/api-2pc/src/phases/gid.md new file mode 100644 index 0000000..13b9680 --- /dev/null +++ b/docs/api-stack/api/api-2pc/src/phases/gid.md @@ -0,0 +1,85 @@ +# `phases/gid` + +## Purpose + +Builds and parses the global transaction id (gid) string passed to +Postgres' `PREPARE TRANSACTION ''`. The format embeds the host +instance id so the recovery scanner can filter `pg_prepared_xacts` to +only the rows this coordinator owns — without that anchor, two +coordinators sharing a Postgres host would clobber each other's +recovery decisions. + +The module is intentionally pure: no SQL, no client. Centralising the +gid format here makes the recovery filter and the per-participant +prepare path share a single source of truth. + +## Features + +- `buildGid(hostInstanceId, txId, participantId)` — produces + `2pc---`. +- `parseGid(gid, hostInstanceId)` — extracts `{ txId, participantId }` + for gids written by the supplied host; returns `null` otherwise so + recovery skips foreign prepared transactions silently. The + hostInstanceId is supplied by the caller (the recovery runner) + because the host id itself may contain hyphens and the parser cannot + recover it unambiguously from the gid alone. +- `gidPrefixFor(hostInstanceId)` — the prefix the recovery SQL filter + uses; centralised so SQL and parser never drift. + +## Usage: Basic + +```ts +import { buildGid, parseGid } from "@suaveplan/api-2pc/phases"; + +const gid = buildGid("host-01", "tx-abc", "billing"); +// "2pc-host-01-tx-abc-billing" + +const parts = parseGid(gid, "host-01"); +// { txId: "tx-abc", participantId: "billing" } +``` + +## Usage: Advanced + +Recovery uses the prefix filter to ignore prepared transactions +written by other components sharing the database: + +```ts +import { gidPrefixFor, parseGid } from "@suaveplan/api-2pc/phases"; + +const prefix = gidPrefixFor("host-01"); +const rows = await db.run<{ gid: string }>( + `SELECT gid FROM pg_prepared_xacts WHERE gid LIKE $1`, + [`${prefix}%`] +); +for (const row of rows) { + const parts = parseGid(row.gid, "host-01"); + if (parts === null) continue; // foreign prepared transaction + // ... +} +``` + +## API Reference + +- `buildGid(hostInstanceId: string, txId: string, participantId: string): string` +- `parseGid(gid: string, hostInstanceId: string): { txId, participantId } | null` +- `gidPrefixFor(hostInstanceId: string): string` + +## Implementation Notes + +`parseGid` takes the caller-supplied `hostInstanceId` and strips the +prefix `2pc--` before extracting `txId` and `participantId`. +The host instance id is supplied explicitly because hyphens are +allowed inside it (production hosts often look like `host-eu-west-1`) +and the parser cannot recover the boundary from the gid alone. The +recovery runner always knows its own host id, so this constraint is +ergonomic in practice. + +Participant ids are constrained by the registry (and by host config) +to not contain hyphens, so the LAST hyphen after the prefix +unambiguously delimits the `participantId` from the `txId`. + +The function returns `null` rather than throwing on unrecognised gids +because the recovery scan iterates over rows that may include prepared +transactions written by code outside this package's control — Postgres +has no participant-tag column, only the gid string itself, so the +shared-database scenario is a legitimate concern. diff --git a/docs/api-stack/api/api-2pc/src/phases/prepare.md b/docs/api-stack/api/api-2pc/src/phases/prepare.md new file mode 100644 index 0000000..d058422 --- /dev/null +++ b/docs/api-stack/api/api-2pc/src/phases/prepare.md @@ -0,0 +1,105 @@ +# `phases/prepare` + +## Purpose + +Implements phase 1 of the 2PC protocol for a single participant. The +coordinator iterates participants and calls this module for each; +unanimous commit votes trigger phase 2, any abort or prepare failure +short-circuits to rollback. This module is the only place the +`PREPARE TRANSACTION ''` SQL is emitted, so the gid format +(`phases/gid`) and the SQL emission point stay co-located. + +Phase 1 is the latency-sensitive half of 2PC: every participant holds +row-level locks for the duration. The module records +`2pc.prepare_duration_ms` so operators can spot creeping lock holds +before they cause throughput regressions. + +## Features + +- Runs the participant's `prepare` callback, then the + `PREPARE TRANSACTION` SQL when the vote is `commit` AND the + participant is a writer. +- Skips the SQL for read-only voters — they participate in the vote + only. +- Refuses a read-only voter that returned `writeIntent: true` with + `TWOPC_READ_ONLY_PARTICIPANT_CANNOT_WRITE`. +- Honours an `AbortSignal` for the phase-1 deadline; aborted SQL is + remapped to `TWOPC_TIMEOUT`. +- Emits a `2pc.prepare` span around the whole call and records a + `2pc.prepare_duration_ms` observation tagged with the outcome. +- Failure cases preserve the underlying cause on the thrown + `TwoPcError`. + +## Usage: Basic + +```ts +import { preparePhaseOne } from "@suaveplan/api-2pc/phases"; + +const outcome = await preparePhaseOne({ + hostInstanceId: "host-01", + txId, + participant, + payload: { invoiceId: "inv-1" }, + instruments, + signal: ac.signal, +}); +if (outcome.vote === "abort") { + // run rollback for every participant that voted commit +} +``` + +## Usage: Advanced + +The coordinator runs this in a loop. Read-only voters interleave +freely with writers — the outcome's `prepared` flag tells phase 2 +whether to send commit/rollback SQL: + +```ts +import { preparePhaseOne } from "@suaveplan/api-2pc/phases"; + +const outcomes: ParticipantPrepareOutcome[] = []; +for (const p of registry.list()) { + const o = await preparePhaseOne({ + hostInstanceId, + txId, + participant: p, + payload: payloadFor(p), + instruments, + signal, + }); + outcomes.push(o); + if (o.vote === "abort") break; // short-circuit +} + +// phase 2: commit only those with prepared === true +const writers = outcomes.filter((o) => o.prepared); +``` + +## API Reference + +- `interface ParticipantPrepareOutcome` — `{ participantId, vote, + prepared, gid }`. +- `interface PreparePhaseInput` — `{ hostInstanceId, txId, + participant, payload, instruments, signal }`. +- `function preparePhaseOne(input): Promise` + - throws `TWOPC_PREPARE_FAILED` when the participant callback or + SQL raises (signal not aborted), + - throws `TWOPC_TIMEOUT` when the signal aborted around the SQL, + - throws `TWOPC_READ_ONLY_PARTICIPANT_CANNOT_WRITE` when a read-only + voter returned `writeIntent: true`. + +## Implementation Notes + +The SQL escape strategy is conservative: gids are built from the host +instance id, transaction id, and participant id — all three are +already validated at host config / id-generator / registry time — but +the function still calls `.replace(/'/g, "''")` before interpolating +into the `PREPARE TRANSACTION` statement. The runtime cost is zero on +the happy path and the defence-in-depth is cheap. The coordinator +never accepts user-supplied SQL fragments. + +The span is started before the prepare callback so the participant's +own work shows up in the trace as a child of the `2pc.prepare` span if +the participant opens its own spans against the same tracer. The +`finally`-block `span.end()` guarantees the span is closed regardless +of which branch fires. diff --git a/docs/api-stack/api/api-2pc/src/phases/rollback.md b/docs/api-stack/api/api-2pc/src/phases/rollback.md new file mode 100644 index 0000000..7dcf51c --- /dev/null +++ b/docs/api-stack/api/api-2pc/src/phases/rollback.md @@ -0,0 +1,92 @@ +# `phases/rollback` + +## Purpose + +Phase-2 rollback for a single participant. Used both by the +coordinator's abort path (vote_abort or prepare failure) and by the +recovery runner (orphan with no `all-voted-commit` ledger row). + +The function is idempotent at the protocol level: Postgres returns +`42704` (`undefined_object`, "prepared transaction does not exist") +for a gid that was already rolled back, and this module catches that +specific error and treats it as a no-op. That property is what makes +recovery safe to re-run on every boot. + +## Features + +- Emits `ROLLBACK PREPARED ''` against the participant's + connection. +- Idempotent against Postgres `42704` — a second rollback against the + same gid is a no-op. +- Skips participants that did not actually prepare (`outcome.prepared + === false`). +- Emits a `2pc.rollback` span with `tx.id`, `participant.id`, and + `gid` attributes. +- Failure preserves the underlying cause on a thrown + `TwoPcError(TWOPC_ROLLBACK_FAILED)`. +- Exports `isUnknownPreparedTransaction(cause)` so the recovery + runner can apply the same idempotency check without duplicating the + SQLSTATE sniff. + +## Usage: Basic + +```ts +import { rollbackPhaseTwo } from "@suaveplan/api-2pc/phases"; + +await rollbackPhaseTwo({ + txId, + participant, + outcome: preparedOutcome, + instruments, +}); +``` + +## Usage: Advanced + +Recovery uses the same idempotency check directly to short-circuit +when the row was concurrently resolved: + +```ts +import { + isUnknownPreparedTransaction, + rollbackPhaseTwo, +} from "@suaveplan/api-2pc/phases"; + +try { + await rollbackPhaseTwo({ txId, participant, outcome, instruments }); +} catch (err) { + if ( + err instanceof TwoPcError && + err.twoPcCode === TWOPC_CODES.ROLLBACK_FAILED && + isUnknownPreparedTransaction(err.cause) + ) { + // race: another process already rolled this back — treat as success + } else { + throw err; + } +} +``` + +## API Reference + +- `interface RollbackPhaseInput` — same fields as `CommitPhaseInput`. +- `function rollbackPhaseTwo(input): Promise` + - no-op for `outcome.prepared === false` + - throws `TwoPcError(TWOPC_ROLLBACK_FAILED)` on non-idempotency SQL + failure. +- `function isUnknownPreparedTransaction(cause: unknown): boolean` + - matches SQLSTATE `42704` AND the substring `"does not exist"` as + a fallback for drivers that omit the SQLSTATE. + +## Implementation Notes + +The idempotency check sniffs both `cause.code` and `cause.message` +because the two postgres clients in use (`postgres`/porsager and +`pg.Client`) surface the SQLSTATE differently. Using both lets the +module work against either driver without a wrapper layer. + +The function is split into a small public `rollbackPhaseTwo` and an +exported `isUnknownPreparedTransaction` helper so recovery can re-use +the idempotency predicate without re-implementing it. Recovery sees +this exact race regularly: the coordinator and the recovery runner +both target the same prepared gid when a host restarts mid-rollback. diff --git a/docs/api-stack/api/api-2pc/src/recovery/recovery.md b/docs/api-stack/api/api-2pc/src/recovery/recovery.md new file mode 100644 index 0000000..e3f960e --- /dev/null +++ b/docs/api-stack/api/api-2pc/src/recovery/recovery.md @@ -0,0 +1,133 @@ +# `recovery/` + + +_(no submodules)_ + + +## Purpose + +Boot-time orphan resolution for the 2PC coordinator. When a host +crashes between phase 1 and phase 2, prepared transactions remain +held in `pg_prepared_xacts` on every writer participant. The recovery +runner sweeps those rows on the next boot, consults the host-owned +ledger, and either commits or rolls back each one — guaranteeing the +"once prepared, eventually resolved" half of the 2PC durability +property. + +The runner is the only path that should ever resolve an in-doubt +transaction. The coordinator's hot path NEVER auto-recovers; it +escalates to `TWOPC_IN_DOUBT` and lets the next-boot recovery sweep +handle it. That separation keeps the hot path's failure handling +small and the recovery path testable in isolation. + +## Features + +- `resolveRecovery({ hostInstanceId, ledger, probes, onResolved })` — + the entry point. Returns a `RecoveryReport` enumerating committed, + rolled-back, skipped, and errored gids. +- Idempotent — re-running the function on a host with no outstanding + prepared transactions is a no-op (the inner `queryOrphans` returns + an empty list). +- Treats Postgres `42704` ("does not exist") as success during + rollback — covers the race where another process already resolved + the orphan. +- Marks rows as `in_doubt` on unresolvable errors so the next sweep + can retry; errored gids are surfaced on the report rather than + thrown. +- `buildProbeFromRegistry(registry)` — convenience adapter that + spins up one probe per writer participant. + +## Usage: Basic + +```ts +import { + buildProbeFromRegistry, + resolveRecovery, +} from "@suaveplan/api-2pc/recovery"; + +const report = await resolveRecovery({ + hostInstanceId: "host-01", + ledger, + probes: buildProbeFromRegistry(registry), +}); + +console.log( + `committed=${report.committed.length} ` + + `rolledBack=${report.rolledBack.length} ` + + `errors=${report.errors.length}` +); +``` + +## Usage: Advanced + +Wire a custom probe to feed an alternate identifier convention or a +replicated-read connection — useful when the recovery sweep should +hit a read replica to avoid contending with the live writer: + +```ts +import { gidPrefixFor } from "@suaveplan/api-2pc/phases"; +import { resolveRecovery, type RecoveryProbe } from "@suaveplan/api-2pc/recovery"; + +const probes: RecoveryProbe[] = [ + { + participantId: "billing", + async queryOrphans(prefix) { + const rows = await readReplica.unsafe<{ gid: string }[]>( + `SELECT gid FROM pg_prepared_xacts WHERE gid LIKE $1`, + [`${prefix}%`] + ); + return rows.map((r) => r.gid); + }, + async commit(gid) { + await primary.unsafe(`COMMIT PREPARED $1`, [gid]); + }, + async rollback(gid) { + await primary.unsafe(`ROLLBACK PREPARED $1`, [gid]); + }, + }, +]; + +const report = await resolveRecovery({ + hostInstanceId: "host-01", + ledger, + probes, + onResolved: (e) => log.info(e), +}); +``` + +## API Reference + +- `interface RecoveryProbe` + - `participantId: string` + - `queryOrphans(prefix: string): Promise` + - `commit(gid: string): Promise` + - `rollback(gid: string): Promise` +- `interface RecoveryReport` + - `committed: readonly string[]` + - `rolledBack: readonly string[]` + - `skipped: readonly string[]` + - `errors: readonly { gid; error: TwoPcError }[]` +- `interface RecoveryInput` + - `hostInstanceId, ledger, probes, onResolved?` +- `function resolveRecovery(input): Promise` +- `function buildProbeFromRegistry(registry): readonly RecoveryProbe[]` + +## Implementation Notes + +The ledger lookup uses the gid's parsed `txId` as the primary key — +the gid format from `phases/gid.ts` is what makes that mapping +unambiguous. Rows whose ledger state is `committing` OR `committed` +trigger `COMMIT PREPARED`; everything else (including missing rows) +triggers `ROLLBACK PREPARED`. That asymmetric default ("rollback by +default") is the safe choice — committing a row whose ledger does +not explicitly say "all voted commit" would violate the design +guarantee. + +The `42704` swallow during rollback is what makes the runner safe to +re-execute: if the previous sweep crashed AFTER rolling back the +prepared transaction but BEFORE updating the ledger, the second +sweep will see the orphan listed in `pg_prepared_xacts` (or not, if +truly gone) and will not throw on the "does not exist" follow-up. +Errors that cannot be classified as idempotency are captured per-gid +and surfaced on the report — operators page-on `errors.length > 0`, +not on a generic throw. diff --git a/docs/api-stack/api/api-2pc/src/registry/participant-registry.md b/docs/api-stack/api/api-2pc/src/registry/participant-registry.md new file mode 100644 index 0000000..5e946ca --- /dev/null +++ b/docs/api-stack/api/api-2pc/src/registry/participant-registry.md @@ -0,0 +1,111 @@ +# `registry/` + + +_(no submodules)_ + + +## Purpose + +The participant registry is the install-time admission control between +plugins and the 2PC coordinator. Plugins declare +`twoPhaseCommit.participates: true` in their manifest; the host +registers them with this registry; the registry refuses any writer +whose bound database engine cannot honour `PREPARE TRANSACTION`. + +This is where the design doc §9.2 rule "SQLite and SurrealDB MUST NOT +participate as writers" is enforced. The capability check is injected +as a callback so the registry stays decoupled from +`@suaveplan/api-host`'s concrete `CapabilityRegistry`. + +## Features + +- `TwoPcParticipantRegistry.register(participant)` — refuses writers + without `db.preparable`; accepts read-only voters regardless of + engine. +- `get(id)` / `list()` / `size()` / `unregister(id)` — standard + registry surface. +- Injection seam: `PreparableCapabilityCheck` is a plain + `(id: string) => boolean` callback — zero coupling to api-host. + +## Usage: Basic + +```ts +import { TwoPcParticipantRegistry } from "@suaveplan/api-2pc/registry"; + +const isPreparable = (pluginId: string) => + pluginId === "billing" || pluginId === "inventory"; + +const registry = new TwoPcParticipantRegistry(isPreparable); +registry.register({ + id: "billing", + voterMode: "writer", + connection: { engine: "postgres", run: pg.unsafe.bind(pg) }, + prepare: billingPrepareCallback, +}); +``` + +## Usage: Advanced + +Refusing a SQLite-backed plugin as a writer happens at register-time +— wrap the registration in a try/catch to surface the failure to the +plugin loader without crashing the host boot: + +```ts +import { TWOPC_CODES, TwoPcError } from "@suaveplan/api-2pc/error-codes"; +import { TwoPcParticipantRegistry } from "@suaveplan/api-2pc/registry"; + +function safeRegisterParticipants( + registry: TwoPcParticipantRegistry, + participants: ReadonlyArray +) { + const failures: { id: string; reason: string }[] = []; + for (const p of participants) { + try { + registry.register(p); + } catch (err) { + if ( + err instanceof TwoPcError && + err.twoPcCode === TWOPC_CODES.PARTICIPANT_NOT_PREPARABLE + ) { + failures.push({ id: p.id, reason: err.message }); + continue; + } + throw err; + } + } + return failures; +} +``` + +The same plugin can then re-register as a `read-only` voter — the +registry accepts read-only voters regardless of engine, because the +coordinator never sends them prepare/commit SQL. + +## API Reference + +- `type PreparableCapabilityCheck = (participantId: string) => boolean` + — capability resolver injected at construction. +- `class TwoPcParticipantRegistry` + - `constructor(isPreparable: PreparableCapabilityCheck)` + - `register(participant): void` — throws + `TWOPC_PARTICIPANT_NOT_PREPARABLE` on writer refusal. + - `get(id): RegisteredTwoPcParticipant | undefined` + - `list(): readonly RegisteredTwoPcParticipant[]` + - `size(): number` + - `unregister(id): boolean` + +## Implementation Notes + +The registry refuses a writer at `register`-time rather than at +`run2pc`-time. This is deliberate — admission failures should surface +during plugin install, not when the first 2PC transaction is attempted +in production. The capability check fires only for writers; read-only +voters are accepted unconditionally because the coordinator drops their +connection from phase-2 SQL traffic. The second-half guard against +read-only voters that try to write a payload lives in +`phases/prepare.ts` (raising `TWOPC_READ_ONLY_PARTICIPANT_CANNOT_WRITE` +when the participant returns `writeIntent: true`). + +`unregister` exists for hot-reload paths: when a plugin is removed +from the running host, the registry drops its participant entry so +subsequent `run2pc` calls cannot accidentally route to it. diff --git a/docs/api-stack/api/api-2pc/src/testing/conformance.md b/docs/api-stack/api/api-2pc/src/testing/conformance.md new file mode 100644 index 0000000..fd7dd98 --- /dev/null +++ b/docs/api-stack/api/api-2pc/src/testing/conformance.md @@ -0,0 +1,100 @@ +# `testing/` + + +_(no submodules)_ + + +## Purpose + +Provides `run2pcParticipantConformance(factory)` — a runnable test +suite that pins the contract every 2PC writer participant MUST honour. +Adapter authors drop a single import + invocation into a +`tests/conformance/run-2pc-participant.test.ts` file in their package; +the harness handles the rest. + +Shipping the harness on this package's `./testing` subpath keeps +participants accountable to the same prepare/commit/rollback semantics +the coordinator depends on at runtime. Without this harness, drift +between participant implementations would only surface during +integration testing — too late. + +## Features + +- Six pinned invariants (engine identifier, voter mode, prepare-then- + prepare-SQL, commit-prepared, rollback-prepared, idempotency-on- + second-rollback). +- Per-scenario factory: every test starts from a fresh participant + + teardown so the suite is isolation-safe under parallel runs. +- Uses `@suaveplan/testing/runner` — works under both Vitest and + Bun:test without re-importing. +- Generates unique gids per scenario so re-runs do not collide. + +## Usage: Basic + +```ts +// In an adapter package's tests/conformance/run-2pc-participant.test.ts +import { run2pcParticipantConformance } from "@suaveplan/api-2pc/testing"; +import { createMyParticipant, teardownMyParticipant } from "../helpers"; + +run2pcParticipantConformance({ + async create() { + const participant = await createMyParticipant(); + return { + participant, + teardown: () => teardownMyParticipant(participant), + }; + }, +}); +``` + +## Usage: Advanced + +The harness exposes no surface beyond `run2pcParticipantConformance` — +deliberately. Adapter-specific assertions belong in adapter test +files, not in the conformance harness. If your adapter needs to +exercise behaviour the suite does not cover (e.g. cancellation, +custom serialization), add a sibling test file: + +```ts +import { describe, it } from "@suaveplan/testing/runner"; +import { run2pcParticipantConformance } from "@suaveplan/api-2pc/testing"; + +describe("my-participant", () => { + run2pcParticipantConformance({ create: createMyParticipant }); + + it("cancels a stuck prepare on signal abort", { timeout: 30_000 }, async () => { + // adapter-specific assertion + }); +}); +``` + +## API Reference + +- `interface TwoPcParticipantFactory` + - `create(): Promise<{ participant: RegisteredTwoPcParticipant; teardown: () => Promise }>` +- `function run2pcParticipantConformance(factory): void` + - Registers six `describe`/`it` blocks against the surrounding + runner. Returns nothing. + +## Implementation Notes + +The harness deliberately does NOT use a shared Postgres connection +across scenarios. Each scenario calls `factory.create()` to get a +fresh participant; the factory is expected to wire its own connection +(directly to a Postgres container, against a shared pool, or against +an `env-bridge` passthrough URL). This isolation prevents one +scenario's leftover prepared transactions from contaminating the +next. + +Gids embed `Date.now()` + a random suffix so re-runs within the same +millisecond never collide on the underlying `pg_prepared_xacts` +table. The cleanup `ROLLBACK PREPARED` at the end of the +prepare-only scenario is best-effort: failure to roll back leaves +the gid prepared until the next teardown sweep, but the harness's +own teardown handle is the primary cleanup path. + +The harness is intentionally NOT exported from the package root (`./` +subpath) — only `./testing`. This mirrors the convention used by +sibling packages (`@suaveplan/i18n-shared/testing`, +`@suaveplan/api-host/testing`) so production code can not accidentally +depend on test-only symbols. diff --git a/docs/api-stack/api/api-2pc/src/types/types.types.md b/docs/api-stack/api/api-2pc/src/types/types.types.md new file mode 100644 index 0000000..f6826fa --- /dev/null +++ b/docs/api-stack/api/api-2pc/src/types/types.types.md @@ -0,0 +1,108 @@ +# `types/` + +## Purpose + +Shared cross-module type definitions for the 2PC coordinator. Holds +the `TwoPcCoordinatorState` state-machine alphabet, the +`PreparableConnection` and `RegisteredTwoPcParticipant` participant +shapes, the `Run2PcInput` / `Run2PcOutcome` public input/output +contracts, and the `TwoPcPrepareResult` per-participant prepare +return type. + +Centralising these types here prevents the cyclic-import smell that +would otherwise emerge from `coordinator/`, `phases/`, `recovery/`, +and `registry/` all needing to know the same wire shapes. The +sibling modules import from this barrel and stay decoupled from each +other at the type level. + +## Features + +- `TwoPcCoordinatorState` — string-literal union covering + `voting`, `committing`, `aborting`, `committed`, `aborted`, + `in_doubt`. +- `PreparableConnection` — structural connection shape exposing + `engine` (a `DatabaseEngine` from `@suaveplan/api-types/db`) and + `run(sql, params?)` returning a `Promise`. +- `RegisteredTwoPcParticipant` — coordinator-side participant view + carrying `id`, `voterMode`, `connection`, and an async + `prepare(txId, payload) => TwoPcPrepareResult` callback. +- `TwoPcPrepareResult` — `{ vote, writeIntent }` returned by a + participant's `prepare` callback. +- `Run2PcInput` / `Run2PcOutcome` — public input/output contracts + accepted and returned by `run2pc`. + +## Usage: Basic + +```ts +import type { + Run2PcInput, + RegisteredTwoPcParticipant, +} from "@suaveplan/api-2pc"; + +const input: Run2PcInput = { + participants: [{ id: "billing", input: { invoiceId: "inv-1" } }], + timeoutMs: 5000, +}; + +const billing: RegisteredTwoPcParticipant = { + id: "billing", + voterMode: "writer", + connection: { engine: "postgres", run: pg.unsafe.bind(pg) }, + prepare: async (_txId) => ({ vote: "commit", writeIntent: true }), +}; +``` + +## Usage: Advanced + +Read-only voter typing — combine `voterMode: "read-only"` with a +`writeIntent: false` invariant on the `prepare` return shape: + +```ts +import type { + RegisteredTwoPcParticipant, + TwoPcPrepareResult, +} from "@suaveplan/api-2pc"; + +async function auditPrepare(): Promise { + const ok = await checkConsistency(); + return { vote: ok ? "commit" : "abort", writeIntent: false }; +} + +const audit: RegisteredTwoPcParticipant = { + id: "audit", + voterMode: "read-only", + connection: { engine: "surrealdb", run: surrealUnsafe }, + prepare: () => auditPrepare(), +}; +``` + +The coordinator refuses a read-only voter whose `prepare` returns +`writeIntent: true` with `TWOPC_READ_ONLY_PARTICIPANT_CANNOT_WRITE` +— the static type doesn't enforce that pairing, but the runtime +boundary does. + +## API Reference + +- `type TwoPcCoordinatorState` +- `interface PreparableConnection` +- `interface RegisteredTwoPcParticipant` +- `interface TwoPcPrepareResult` +- `interface Run2PcInput` +- `interface Run2PcOutcome` + +## Implementation Notes + +Every interface is `readonly` on every field. This is deliberate — +the coordinator caches inputs (participant lookups, ledger entries) +and a mutation by accident would corrupt in-flight state. The +strictness is enforced at the type level via `readonly` plus +`ReadonlyArray<...>` and at the runtime level by the boundary Zod +schemas in `options/` (for caller-facing inputs). + +The `Run2PcOutcome.state` field uses `Extract` so callers do not have to +exhaustively switch over the in-flight states (`voting`, +`committing`, `aborting`) that never appear on a returned outcome. +The structural typing of `PreparableConnection` keeps the package +independent of `pg` and `postgres` (porsager) — both clients can be +adapted at the seam with a one-line wrapper. diff --git a/docs/api-stack/api/api-audit-file/README.md b/docs/api-stack/api/api-audit-file/README.md new file mode 100644 index 0000000..dd73d29 --- /dev/null +++ b/docs/api-stack/api/api-audit-file/README.md @@ -0,0 +1,85 @@ +# @suaveplan/api-audit-file — audit sink writing JSON-per-line, HMAC-SHA-256 signed records to a rotated file. Size + time rotation, maxFiles retention, bounded-queue backpressure with observable drops, append + strict-sync write modes. Implements `RequestAuditSink` from `@suaveplan/api-host/request-pipeline`. + +File-rotating, HMAC-signed audit sink for `@suaveplan/api-host`. +Implements `RequestAuditSink` from +`@suaveplan/api-host/request-pipeline`: writes one JSON line per +record with an HMAC-SHA-256 signature, rolls the file on a size OR age +trigger, and prunes the oldest rotated siblings to a configurable +`maxFiles` retention cap. + +Suitable for single-host deployments, on-prem environments without a +log shipper, and any host that prefers durable local storage of the +audit trail. The sibling `@suaveplan/api-audit-stdout` covers the +log-shipped use case; both sinks share the wire shape so dashboards +union on metric name and partition by the `sink` attribute. + + +## Documentation tree + +- [error-codes](./src/error-codes/error-codes.md) — Frozen registry of the six stable `AUDIT_FILE.*` error codes raised by the file-rotating audit sink, plus the concrete… + - [error-codes](./src/error-codes/error-codes.md) — Frozen registry of the six stable `AUDIT_FILE.*` error codes raised by the file-rotating audit sink, plus the concrete… +- [fs-helpers](./src/fs-helpers/fs-helpers.md) — Isolates the `node:fs` surface the sink touches behind an injectable `FsAdapter` interface and concrete `nodeFsAdapter`… + - [fs-helpers](./src/fs-helpers/fs-helpers.md) — Isolates the `node:fs` surface the sink touches behind an injectable `FsAdapter` interface and concrete `nodeFsAdapter`… +- [hmac](./src/hmac/hmac.md) — Wraps `@suaveplan/crypto-hash` HMAC-SHA-256 into the two operations the file sink needs: signing a canonical record on… + - [hmac](./src/hmac/hmac.md) — Wraps `@suaveplan/crypto-hash` HMAC-SHA-256 into the two operations the file sink needs: signing a canonical record on… +- [instruments](./src/instruments/instruments.md) — Constructs the OTel counter bundle the file sink emits and exposes the canonical `sink="file"` attribute set. Every obs… + - [instruments](./src/instruments/instruments.md) — Constructs the OTel counter bundle the file sink emits and exposes the canonical `sink="file"` attribute set. Every obs… +- [retention](./src/retention/retention.md) — Enforces the `maxFiles` retention dimension of the rotation policy by deleting the oldest rotated files until at most `… + - [retention](./src/retention/retention.md) — Enforces the `maxFiles` retention dimension of the rotation policy by deleting the oldest rotated files until at most `… +- [rotation](./src/rotation/rotation.md) — Resolves the rotation policy carried by every `createFileAuditSink` instance and implements the rotation primitive itse… + - [rotation](./src/rotation/rotation.md) — Resolves the rotation policy carried by every `createFileAuditSink` instance and implements the rotation primitive itse… +- [schema](./src/schema/schema.md) — Defines the Zod schema and canonical-bytes function that bracket every audit record before it is signed and written. Th… + - [schema](./src/schema/schema.md) — Defines the Zod schema and canonical-bytes function that bracket every audit record before it is signed and written. Th… +- [sink](./src/sink/sink.md) — The public entry point of `@suaveplan/api-audit-file`. The `createFileAuditSink` factory composes the schema, hmac, rot… + - [sink](./src/sink/sink.md) — The public entry point of `@suaveplan/api-audit-file`. The `createFileAuditSink` factory composes the schema, hmac, rot… + + +## Install + +```bash +bun add @suaveplan/api-audit-file +``` + +## Quickstart + +```ts +import { createFileAuditSink } from "@suaveplan/api-audit-file/sink"; + +const sink = await createFileAuditSink({ + path: "/var/log/suaveplan/audit.log", + hmacKey: new TextEncoder().encode(process.env.AUDIT_HMAC_KEY ?? ""), + rotation: { maxSizeBytes: 100 * 1024 * 1024, maxAgeMs: 86_400_000, maxFiles: 30 }, + appendMode: "strict-sync", +}); + +await sink.emit(envelopeFromHostPipeline); +await sink.dispose(); +``` + +## Modules + +- `./sink` — `createFileAuditSink`, `FileAuditSink`, `CreateFileAuditSinkOptions`, `AppendMode`. +- `./rotation` — `RotationPolicy`, `RotationState`, `resolveRotationPolicy`, `shouldRotate`, `rotate`. +- `./retention` — `enforceRetention`. +- `./schema` — `AuditRecord`, `AuditRecordSchema`, `canonicalise`, `buildSignedLine`. +- `./hmac` — `signRecord`, `verifyRecord`. +- `./instruments` — `AuditFileInstruments`, `createAuditFileInstruments`, `SINK_ATTRIBUTE`. +- `./fs-helpers` — `FsAdapter`, `nodeFsAdapter`, `listRotatedFiles`, `rotatedFilePathAt`. +- `./error-codes` — `AUDIT_FILE_CODES`, `AuditFileError`, `AuditFileCode`. + +## Error codes + +`AUDIT_FILE.INVALID_RECORD`, `AUDIT_FILE.WRITER_FAILED`, +`AUDIT_FILE.QUEUE_FULL`, `AUDIT_FILE.ROTATION_FAILED`, +`AUDIT_FILE.RETENTION_FAILED`, `AUDIT_FILE.PATH_NOT_WRITEABLE`. + +## OTel instruments + +- `api.audit.records_total{sink="file"}` +- `api.audit.dropped_total{sink="file"}` +- `api.audit.rotation_evicted_total{sink="file"}` + +## Tier + +Server-tier — depends on `node:fs/promises`. + diff --git a/docs/api-stack/api/api-audit-file/src/error-codes/error-codes.md b/docs/api-stack/api/api-audit-file/src/error-codes/error-codes.md new file mode 100644 index 0000000..7df0008 --- /dev/null +++ b/docs/api-stack/api/api-audit-file/src/error-codes/error-codes.md @@ -0,0 +1,83 @@ +# `error-codes` + + +_(no submodules)_ + + +## Purpose + +Frozen registry of the six stable `AUDIT_FILE.*` error codes raised by +the file-rotating audit sink, plus the concrete +`AuditFileError extends SuaveplanError` subclass that carries them. +Operators rely on the codes for dashboard slicing; package consumers +rely on the typed subclass to differentiate sink failures from generic +host errors without parsing message strings. + +The registry is built with `defineCodes("AUDIT_FILE", [...])` from +`@suaveplan/error`, so every code is recorded in the global registry +exactly once at module load. The OpenSpec conformance gate verifies +every entry here is also raised by a production code path elsewhere in +`src/` — no dead codes are permitted. + +## Features + +- Six stable codes: `INVALID_RECORD`, `WRITER_FAILED`, `QUEUE_FULL`, + `ROTATION_FAILED`, `RETENTION_FAILED`, `PATH_NOT_WRITEABLE`. +- Typed union `AuditFileCode` for narrowing on `error.code`. +- `AuditFileError` subclass with stable `error.name === "AuditFileError"`. +- Forwards `cause`, `context`, `redacted`, and other + `SuaveplanErrorOptions` to the base constructor unchanged. + +## Usage: Basic + +```ts +import { + AUDIT_FILE_CODES, + AuditFileError, +} from "@suaveplan/api-audit-file/error-codes"; + +throw new AuditFileError( + AUDIT_FILE_CODES.PATH_NOT_WRITEABLE, + "error.audit.file.path_not_writeable", + { context: { path: "/var/log/suaveplan/audit.log" } } +); +``` + +## Usage: Advanced + +Narrow on the union after catching to drive code-specific recovery: + +```ts +import { + AUDIT_FILE_CODES, + type AuditFileCode, + AuditFileError, +} from "@suaveplan/api-audit-file/error-codes"; + +function recover(err: unknown): "retry" | "drop" { + if (!(err instanceof AuditFileError)) throw err; + const code: AuditFileCode = err.code; + if (code === AUDIT_FILE_CODES.QUEUE_FULL) return "drop"; + if (code === AUDIT_FILE_CODES.WRITER_FAILED) return "retry"; + if (code === AUDIT_FILE_CODES.ROTATION_FAILED) return "retry"; + throw err; +} +``` + +## API Reference + +- `AUDIT_FILE_CODES: Readonly">>` +- `type AuditFileCode = (typeof AUDIT_FILE_CODES)[keyof typeof AUDIT_FILE_CODES]` +- `AUDIT_FILE_ERROR_NAME = "AuditFileError"` +- `class AuditFileError extends SuaveplanError` + - `new AuditFileError(code, messageKey, options?)` + +## Implementation Notes + +The codes are declared `as const` so TypeScript freezes both the keys +and the fully-qualified string values. The `name` literal is exported +separately because some structured loggers group errors on `name` +before they inspect `code` — pinning a constant keeps that grouping +stable across releases. The module is side-effect-imported from +`src/index.ts` so a consumer who only loads a subpath +(`@suaveplan/api-audit-file/sink`) still triggers code registration. diff --git a/docs/api-stack/api/api-audit-file/src/fs-helpers/fs-helpers.md b/docs/api-stack/api/api-audit-file/src/fs-helpers/fs-helpers.md new file mode 100644 index 0000000..78fd4c9 --- /dev/null +++ b/docs/api-stack/api/api-audit-file/src/fs-helpers/fs-helpers.md @@ -0,0 +1,86 @@ +# `fs-helpers` + + +_(no submodules)_ + + +## Purpose + +Isolates the `node:fs` surface the sink touches behind an injectable +`FsAdapter` interface and concrete `nodeFsAdapter` implementation. The +indirection lets tests run the sink against a real filesystem under a +temp directory (the default for this package's test suite) while +keeping a clean seam for in-memory adapters used by external consumers. + +The module also exports the rotated-file enumeration helper used by +the retention module — keeping the file-name conventions next to the +filesystem primitives means rotation, retention, and sink all share +the same view of "what counts as a rotated sibling of this base path". + +## Features + +- `FsAdapter` — six-method surface: `appendLine`, `fileSize`, `rename`, + `unlink`, `readdir`, `ensureWriteableDir`. +- `nodeFsAdapter` — production adapter against `node:fs/promises`. +- `listRotatedFiles(fs, basePath)` — returns full paths of every + rotated sibling, sorted oldest-first by embedded timestamp. +- `rotatedFilePathAt(basePath, iso)` — builds the rotated path for the + supplied ISO timestamp; `:` is replaced with `-` so the name is + Windows-safe and grep-friendly. + +## Usage: Basic + +```ts +import { nodeFsAdapter } from "@suaveplan/api-audit-file/fs-helpers"; + +await nodeFsAdapter.ensureWriteableDir("/var/log/suaveplan"); +await nodeFsAdapter.appendLine("/var/log/suaveplan/audit.log", "...\n", false); +``` + +## Usage: Advanced + +Provide an injectable adapter to drive the sink against an in-memory +filesystem: + +```ts +import type { FsAdapter } from "@suaveplan/api-audit-file/fs-helpers"; + +const inMemory = new Map(); +const adapter: FsAdapter = { + async appendLine(p, line) { + inMemory.set(p, (inMemory.get(p) ?? "") + line); + }, + async fileSize(p) { + return Buffer.byteLength(inMemory.get(p) ?? "", "utf8"); + }, + async rename(from, to) { + inMemory.set(to, inMemory.get(from) ?? ""); + inMemory.delete(from); + }, + async unlink(p) { + inMemory.delete(p); + }, + async readdir() { + return [...inMemory.keys()]; + }, + async ensureWriteableDir() { + /* always writeable */ + }, +}; +``` + +## API Reference + +- `interface FsAdapter` — see Features above. +- `const nodeFsAdapter: FsAdapter` +- `listRotatedFiles(fs: FsAdapter, basePath: string): Promise` +- `rotatedFilePathAt(basePath: string, isoTimestamp: string): string` + +## Implementation Notes + +`ensureWriteableDir` calls `mkdir(..., { recursive: true })` then a +`W_OK` `access` probe so a fresh boot creates the directory and a +borked permission setup throws `PATH_NOT_WRITEABLE` synchronously +during sink construction. `fileSize` swallows `ENOENT` and returns `0` +so the rotation logic naturally treats a not-yet-created file as +empty — that simplifies the open-on-first-write code path. diff --git a/docs/api-stack/api/api-audit-file/src/hmac/hmac.md b/docs/api-stack/api/api-audit-file/src/hmac/hmac.md new file mode 100644 index 0000000..f2525b8 --- /dev/null +++ b/docs/api-stack/api/api-audit-file/src/hmac/hmac.md @@ -0,0 +1,76 @@ +# `hmac` + + +_(no submodules)_ + + +## Purpose + +Wraps `@suaveplan/crypto-hash` HMAC-SHA-256 into the two operations the +file sink needs: signing a canonical record on write and verifying a +record + signature on read. The wrapper hex-encodes the digest so the +on-disk line stays human-greppable and ASCII-clean, and exposes a +constant-time verifier so tampering checks do not leak position +information through timing. + +## Features + +- `signRecord(key, bytes): string` — 64-char lowercase hex of + HMAC-SHA-256 over `bytes` using `key`. +- `verifyRecord(key, bytes, hmacHex): boolean` — constant-time + comparison of recomputed HMAC against the provided hex. +- Empty-key guard raises a typed `Error` so misconfiguration cannot + silently produce a deterministic null-MAC. + +## Usage: Basic + +```ts +import { signRecord, verifyRecord } from "@suaveplan/api-audit-file/hmac"; + +const key = new TextEncoder().encode("super-secret-rotating-key"); +const bytes = new TextEncoder().encode('{"requestId":"r-1"}'); +const hmac = signRecord(key, bytes); +verifyRecord(key, bytes, hmac); // → true +``` + +## Usage: Advanced + +Use with the canonical-bytes helper to verify an on-disk line: + +```ts +import { + AuditRecordSchema, + canonicalise, +} from "@suaveplan/api-audit-file/schema"; +import { verifyRecord } from "@suaveplan/api-audit-file/hmac"; + +for await (const line of lines) { + const { record, hmac } = JSON.parse(line) as { + record: unknown; + hmac: string; + }; + const parsed = AuditRecordSchema.parse(record); + const ok = verifyRecord(key, canonicalise(parsed), hmac); + if (!ok) throw new Error("hmac mismatch"); +} +``` + +## API Reference + +- `signRecord(key: Uint8Array, bytes: Uint8Array): string` +- `verifyRecord(key: Uint8Array, bytes: Uint8Array, hmacHex: string): boolean` + +## Implementation Notes + +The hex encoder is hand-rolled rather than borrowed from +`@suaveplan/crypto-utils` so this module stays a leaf of the dependency +graph — the sink runs on every audit-emitting request, and keeping the +hot path's transitive deps minimal helps cold-start latency on +serverless deploys. Constant-time comparison XORs each character code +and accumulates into a bitmask; the boolean conversion at the end keeps +the early-return branch (length mismatch) bounded to attacker-visible +metadata only. The 64-character length check up front is intentionally +outside the constant-time region because the length of the supplied +HMAC is not secret — an attacker who supplies a malformed hex string +sees an immediate rejection but learns nothing about the recomputed +digest. diff --git a/docs/api-stack/api/api-audit-file/src/instruments/instruments.md b/docs/api-stack/api/api-audit-file/src/instruments/instruments.md new file mode 100644 index 0000000..81bf980 --- /dev/null +++ b/docs/api-stack/api/api-audit-file/src/instruments/instruments.md @@ -0,0 +1,78 @@ +# `instruments` + + +_(no submodules)_ + + +## Purpose + +Constructs the OTel counter bundle the file sink emits and exposes the +canonical `sink="file"` attribute set. Every observation carries the +attribute so a dashboard tracking `api.audit.records_total` across the +sink family — `stdout`, `file`, and future siblings — can union the +metric name and partition by `sink`. The three counters answer the +operator questions "are records flowing?", "are records dropping?", +and "is retention pruning old files?". + +## Features + +- `createAuditFileInstruments({ meterProvider? })` — returns a frozen + bundle of three counters bound to the supplied or global + `MeterProvider`. +- `SINK_ATTRIBUTE` — frozen `{ sink: "file" }` literal exported for + reuse by the sink, retention, and test harnesses. +- Counters: `api.audit.records_total`, `api.audit.dropped_total`, + `api.audit.rotation_evicted_total`. + +## Usage: Basic + +```ts +import { createAuditFileInstruments } from "@suaveplan/api-audit-file/instruments"; + +const instruments = createAuditFileInstruments(); +instruments.recordsTotal.add(1, { sink: "file" }); +``` + +## Usage: Advanced + +Install a real `MeterProvider` and assert deltas in tests: + +```ts +import { + MeterProvider, + InMemoryMetricExporter, + PeriodicExportingMetricReader, +} from "@opentelemetry/sdk-metrics"; +import { createAuditFileInstruments } from "@suaveplan/api-audit-file/instruments"; + +const exporter = new InMemoryMetricExporter(0); +const reader = new PeriodicExportingMetricReader({ exporter }); +const provider = new MeterProvider({ readers: [reader] }); + +const instruments = createAuditFileInstruments({ meterProvider: provider }); +instruments.recordsTotal.add(1, { sink: "file" }); + +await reader.collect(); +``` + +## API Reference + +- `interface AuditFileInstruments` + - `meter: Meter` + - `recordsTotal: Counter` + - `droppedTotal: Counter` + - `rotationEvictedTotal: Counter` +- `interface AuditFileInstrumentsConfig` + - `meterProvider?: MeterProvider` +- `createAuditFileInstruments(config?): AuditFileInstruments` +- `SINK_ATTRIBUTE: Readonly<{ sink: "file" }>` + +## Implementation Notes + +The bundle is intentionally NOT module-level cached — every sink +instance gets its own bundle so an operator who reconstructs the host +under a fresh `MeterProvider` (a test-host pattern in +`@suaveplan/api-host/testing`) sees deltas against the right provider. +Counters from the sibling `api-audit-stdout` sink share the metric +NAMES with this package so a single dashboard panel covers the family; +the `sink="file"` attribute distinguishes the source. diff --git a/docs/api-stack/api/api-audit-file/src/retention/retention.md b/docs/api-stack/api/api-audit-file/src/retention/retention.md new file mode 100644 index 0000000..1fc82ea --- /dev/null +++ b/docs/api-stack/api/api-audit-file/src/retention/retention.md @@ -0,0 +1,67 @@ +# `retention` + + +_(no submodules)_ + + +## Purpose + +Enforces the `maxFiles` retention dimension of the rotation policy by +deleting the oldest rotated files until at most `maxFiles` remain. +Retention runs immediately after each rotation succeeds so the disk +footprint is bounded across long-running deployments — an audit +directory left to grow unchecked is the most common operator pain +point with file-based sinks, and this module's existence is exactly +the answer to it. + +The increment on `api.audit.rotation_evicted_total{sink="file"}` makes +eviction observable. Operators alert on an unexpectedly high rate so a +runaway rotation cycle (e.g. clock skew, misconfigured `maxAgeMs`) is +visible before the retention sweep drops historical data. + +## Features + +- `enforceRetention(fs, basePath, maxFiles, instruments)` — deletes + the oldest rotated files until at most `maxFiles` remain. Idempotent: + re-running with no surplus is a no-op. +- Counter increment per deletion with the canonical `sink="file"` + attribute set. +- Surfaces `AUDIT_FILE.RETENTION_FAILED` on a delete failure with the + offending path in `context.path` and the underlying `cause`. + +## Usage: Basic + +```ts +import { enforceRetention } from "@suaveplan/api-audit-file/retention"; + +await enforceRetention(fs, "/var/log/audit.log", 30, instruments); +``` + +## Usage: Advanced + +Call from a custom rotation cadence — e.g. an external cron that wants +to prune without rotating: + +```ts +import { enforceRetention } from "@suaveplan/api-audit-file/retention"; + +// Cron job: every hour, prune to a smaller retention than the sink's +// default to claw back disk during high-traffic windows. +setInterval(async () => { + await enforceRetention(fs, basePath, 10, instruments); +}, 60 * 60 * 1000); +``` + +## API Reference + +- `enforceRetention(fs: FsAdapter, basePath: string, maxFiles: number, instruments: AuditFileInstruments): Promise` + +## Implementation Notes + +`listRotatedFiles` returns paths sorted oldest-first by the embedded +ISO timestamp; we slice off the first `(count - maxFiles)` entries and +unlink them. Sorting is lexicographic on the ISO string, which is also +chronological for the `YYYY-MM-DDTHH-MM-SS.sssZ` shape — no extra +parsing required. If `unlink` fails midway, the previously-evicted +deletions are not undone; the throw surfaces the failure and the next +rotation re-attempts retention against whatever survived. diff --git a/docs/api-stack/api/api-audit-file/src/rotation/rotation.md b/docs/api-stack/api/api-audit-file/src/rotation/rotation.md new file mode 100644 index 0000000..2a063b5 --- /dev/null +++ b/docs/api-stack/api/api-audit-file/src/rotation/rotation.md @@ -0,0 +1,95 @@ +# `rotation` + + +_(no submodules)_ + + +## Purpose + +Resolves the rotation policy carried by every `createFileAuditSink` +instance and implements the rotation primitive itself — the +`rename(currentFile → currentFile..log)` step plus the +post-rotation state reset. The module owns both dimensions documented +in the spec: size-based (`maxSizeBytes`, default 100 MiB) and +time-based (`maxAgeMs`, default 24h). Either condition reaching its +limit triggers a rotation on the next write. + +Rotation lives in a separate module so the sink stays focused on +queueing + writing. The retention module reads the policy through the +same `RotationState` so the operator-facing knobs are documented in +exactly one place. + +## Features + +- `resolveRotationPolicy(input?)` — Zod-equivalent validator returning + a frozen `RotationPolicy`. Defaults filled from the design doc. +- `shouldRotate(state, nowMs)` — pure predicate; size OR age satisfies. +- `rotate(fs, basePath, state, clock)` — performs the rename, updates + state, returns the rotated path for retention to inspect. +- Raises `AUDIT_FILE.ROTATION_FAILED` on rename failure with full + `cause` for forensic logging. + +## Usage: Basic + +```ts +import { + resolveRotationPolicy, + rotate, + shouldRotate, +} from "@suaveplan/api-audit-file/rotation"; + +const policy = resolveRotationPolicy({ maxSizeBytes: 1024 * 1024 }); +const state = { openedAtMs: Date.now(), bytesWritten: 0, policy }; +if (shouldRotate(state, Date.now())) { + await rotate(fs, "/var/log/audit.log", state, () => Date.now()); +} +``` + +## Usage: Advanced + +Disable a dimension by setting it to `Number.POSITIVE_INFINITY` — +useful when an operator wants pure time rotation regardless of size: + +```ts +const policy = resolveRotationPolicy({ + maxSizeBytes: Number.POSITIVE_INFINITY, + maxAgeMs: 60 * 60 * 1000, // hourly +}); +``` + +In tests, drive rotation deterministically with a `FakeClock` from +`@suaveplan/testing`: + +```ts +import { FakeClock } from "@suaveplan/testing"; + +const clock = new FakeClock(0); +const state = { openedAtMs: 0, bytesWritten: 0, policy }; +clock.advance(61_000); +await rotate(fs, basePath, state, clock.read); +``` + +## API Reference + +- `interface RotationPolicy` + - `maxSizeBytes: number` — bytes before size rotation; default 100 MiB. + - `maxAgeMs: number` — ms before time rotation; default 24h. + - `maxFiles: number` — kept rotated files; default 30. +- `interface RotationState` + - `openedAtMs: number` — wall-clock open time of current segment. + - `bytesWritten: number` — running byte count. + - `policy: RotationPolicy` — frozen at construction. +- `resolveRotationPolicy(input?): RotationPolicy` +- `shouldRotate(state, nowMs): boolean` +- `rotate(fs, basePath, state, clock): Promise` — returns the + rotated file path. + +## Implementation Notes + +The rotated suffix replaces `:` with `-` so the resulting filename is +Windows-portable and grep-friendly across shells. State mutation +happens AFTER the rename succeeds — a failed rename leaves the original +state intact, so the next call retries against the same segment rather +than corrupting accounting. `bytesWritten` resets to 0 instead of +re-stat'ing the new empty file; the next successful append updates it +in lock-step with the on-disk length. diff --git a/docs/api-stack/api/api-audit-file/src/schema/schema.md b/docs/api-stack/api/api-audit-file/src/schema/schema.md new file mode 100644 index 0000000..d0f2ad4 --- /dev/null +++ b/docs/api-stack/api/api-audit-file/src/schema/schema.md @@ -0,0 +1,79 @@ +# `schema` + + +_(no submodules)_ + + +## Purpose + +Defines the Zod schema and canonical-bytes function that bracket every +audit record before it is signed and written. The schema mirrors the +`RequestAuditEnvelope` interface exported by +`@suaveplan/api-host/request-pipeline`; the canonical-bytes function +gives every other module a deterministic input for HMAC signing, +file-line construction, and signature verification. + +The package re-validates at the sink boundary even though the host +constructs envelopes from typed data — operators frequently hand-craft +audit records in tests, replay tooling, or migration scripts. The +boundary check makes corrupt records fail loudly with a typed +`AUDIT_FILE.INVALID_RECORD` instead of silently bypassing the HMAC. + +## Features + +- `AuditRecordSchema` — strict Zod object accepting only the + envelope's documented fields. Unknown keys reject. +- `AuditRecord` — `z.infer`; structurally + assignable to `RequestAuditEnvelope`. +- `canonicalise(record)` — UTF-8 bytes of the record JSON-stringified + with sorted top-level keys. +- `buildSignedLine(bytes, hmacHex)` — emits the on-disk JSON line + carrying the record + HMAC, with a trailing `\n`. + +## Usage: Basic + +```ts +import { + AuditRecordSchema, + buildSignedLine, + canonicalise, +} from "@suaveplan/api-audit-file/schema"; + +const record = AuditRecordSchema.parse(rawEnvelope); +const bytes = canonicalise(record); +const line = buildSignedLine(bytes, "deadbeef..."); +``` + +## Usage: Advanced + +Verify an on-disk line: + +```ts +import { hmac } from "@suaveplan/crypto-hash"; +import { AuditRecordSchema, canonicalise } from "@suaveplan/api-audit-file/schema"; + +const { record, hmac: hmacHex } = JSON.parse(lineFromDisk); +const parsed = AuditRecordSchema.parse(record); +const bytes = canonicalise(parsed); +const expected = Buffer.from(hmac("SHA-256", key, bytes)).toString("hex"); +if (expected !== hmacHex) { + throw new Error("hmac mismatch — record was tampered"); +} +``` + +## API Reference + +- `AuditRecordSchema: z.ZodObject` (strict) +- `type AuditRecord = z.infer` +- `canonicalise(record: AuditRecord): Uint8Array` +- `buildSignedLine(canonicalBytes: Uint8Array, hmacHex: string): string` + +## Implementation Notes + +The canonical bytes drop `undefined` values for the optional `cause` +slot so the absence of an error never affects the signature. Top-level +keys are sorted alphabetically to give every implementation (TypeScript, +Go log-reader, Python forensic tooling) the same input bytes for +verification regardless of construction order. `principal.scopes` is +preserved in array order — the order is semantically meaningful in the +pipeline so we do not collapse it. diff --git a/docs/api-stack/api/api-audit-file/src/sink/sink.md b/docs/api-stack/api/api-audit-file/src/sink/sink.md new file mode 100644 index 0000000..2eba6b8 --- /dev/null +++ b/docs/api-stack/api/api-audit-file/src/sink/sink.md @@ -0,0 +1,128 @@ +# `sink` + + +_(no submodules)_ + + +## Purpose + +The public entry point of `@suaveplan/api-audit-file`. The +`createFileAuditSink` factory composes the schema, hmac, rotation, +retention, instruments, and fs-helpers modules into a single object +that implements the `RequestAuditSink` contract from +`@suaveplan/api-host/request-pipeline`. The sink writes each accepted +record as one JSON line with an HMAC-SHA-256 signature, rolls the file +when size OR age limits are reached, and keeps at most `maxFiles` +rotated siblings. + +The sink is queue-buffered: callers `await emit()` and resolve as soon +as the record has been appended to disk. A bounded queue protects the +host from a stalled filesystem: records arriving while the queue is at +`maxQueueSize` are dropped with a typed `AUDIT_FILE.QUEUE_FULL` and an +`api.audit.dropped_total{sink="file"}` increment. `dispose()` flushes +the queue and is idempotent. + +## Features + +- `createFileAuditSink({ path, hmacKey, ... })` — async factory. + Returns a sink ready to `emit()`. +- Schema validation at the boundary: invalid records throw + `AUDIT_FILE.INVALID_RECORD` and increment `dropped_total`. +- `strict-sync` (default) and `append` modes for the durability / + throughput trade-off. +- Boot-time `mkdir -p` of the parent directory + `W_OK` probe; + unwriteable targets throw `AUDIT_FILE.PATH_NOT_WRITEABLE` from the + factory itself so misconfiguration is visible at host startup. +- Size + time rotation; `maxFiles` retention; per-eviction OTel counter. +- Idempotent `dispose()`; observable `queueDepth` getter for probes. + +## Usage: Basic + +```ts +import { createFileAuditSink } from "@suaveplan/api-audit-file/sink"; + +const sink = await createFileAuditSink({ + path: "/var/log/suaveplan/audit.log", + hmacKey: new TextEncoder().encode(process.env.AUDIT_HMAC_KEY ?? ""), +}); + +await sink.emit({ + at: new Date().toISOString(), + requestId: "r-1", + traceId: null, + route: "/admin/users", + plugin: "core-admin", + method: "POST", + principal: { id: "user-1", scopes: ["admin"] }, + tenantId: "tenant-a", + status: 200, + outcome: "success", +}); + +await sink.dispose(); +``` + +## Usage: Advanced + +Run with a custom rotation policy, `append` mode, real `MeterProvider`, +and an injected `FakeClock` for deterministic tests: + +```ts +import { FakeClock } from "@suaveplan/testing"; +import { + MeterProvider, + InMemoryMetricExporter, + PeriodicExportingMetricReader, +} from "@opentelemetry/sdk-metrics"; +import { createFileAuditSink } from "@suaveplan/api-audit-file/sink"; +import { createAuditFileInstruments } from "@suaveplan/api-audit-file/instruments"; + +const clock = new FakeClock(0); +const exporter = new InMemoryMetricExporter(0); +const reader = new PeriodicExportingMetricReader({ exporter }); +const meterProvider = new MeterProvider({ readers: [reader] }); + +const sink = await createFileAuditSink({ + path: "/tmp/audit.log", + hmacKey: new TextEncoder().encode("secret"), + clock: clock.read, + rotation: { maxSizeBytes: 1024, maxAgeMs: 60_000, maxFiles: 5 }, + appendMode: "append", + maxQueueSize: 256, + instruments: createAuditFileInstruments({ meterProvider }), +}); +``` + +## API Reference + +- `interface CreateFileAuditSinkOptions` + - `path: string` (required) + - `hmacKey: Uint8Array` (required, non-empty) + - `clock?: Clock` — default `() => Date.now()` + - `rotation?: Partial` + - `appendMode?: "strict-sync" | "append"` — default `"strict-sync"` + - `maxQueueSize?: number` — default 1024 + - `fs?: FsAdapter` — default `nodeFsAdapter` + - `logger?: LoggerLike` — default no-op + - `instruments?: AuditFileInstruments` — default global meter +- `interface FileAuditSink` + - `emit(record): Promise` + - `dispose(): Promise` + - `readonly queueDepth: number` +- `createFileAuditSink(options): Promise` + +## Implementation Notes + +The drain loop is mutex-style: a single in-flight drain promise covers +every concurrent `emit()` call so writes are serialised against the +file handle even when callers fan out. Backpressure is signalled +synchronously — `emit()` throws `QUEUE_FULL` before any await when the +bounded queue is at capacity, so the host can apply load shedding +without observing a write-latency spike. Rotation runs in the same +drain frame as the triggering write so the rename always happens +before the segment grows past the cap by one extra line. Retention +runs after rotation; a retention failure is logged but does not +propagate — the sink stays available even if `unlink` is transiently +denied. The on-disk format is intentionally trivial (`{ record, hmac }` +per line) so an operator with `jq` and `openssl dgst -sha256 -hmac` can +verify integrity without any Suaveplan tooling on hand. diff --git a/docs/api-stack/api/api-audit-stdout/README.md b/docs/api-stack/api/api-audit-stdout/README.md new file mode 100644 index 0000000..fe61204 --- /dev/null +++ b/docs/api-stack/api/api-audit-stdout/README.md @@ -0,0 +1,79 @@ +# @suaveplan/api-audit-stdout - Stdout `RequestAuditSink` for @suaveplan/api-host. Writes JSON-per-line audit records to a Writable (default process.stdout) with an HMAC-SHA-256 signature over canonical bytes. Implements the design-doc §12.5 audit-record shape, Zod-validated at the boundary, with bounded backpressure (maxQueueMs default 100ms), observable drop counter, and a once-per-minute warning throttle. OTel counters api.audit.records_total{sink=stdout,type,outcome} and api.audit.dropped_total{sink=stdout}. Server-tier — Bun + Node. + +Stdout audit sink for `@suaveplan/api-host`. Writes JSON-per-line +audit records to a `LineWriter` (default `process.stdout`) with an +HMAC-SHA-256 signature appended as a `_hmac` field. Implements +`RequestAuditSink` from `@suaveplan/api-host/request-pipeline`, so the +host's request pipeline accepts the instance directly via its `audit` +capability slot. + +The record shape is the design-doc §12.5 canonical wire format — +`ts`, `type`, `principal`, `tenant`, `request_id`, `trace_id`, +`subject`, `outcome`, and a conditional `cause`. Each record is +Zod-validated at the boundary before signing, so a malformed record +never reaches the log pipeline. + + +## Documentation tree + +- [error-codes](./src/error-codes/error-codes.md) — This module declares the four stable error codes the stdout audit sink exposes to consumers. Every failure path inside… + - [error-codes](./src/error-codes/error-codes.md) — This module declares the four stable error codes the stdout audit sink exposes to consumers. Every failure path inside… +- [hmac](./src/hmac/hmac.md) — This module produces the HMAC-SHA-256 tag attached to every audit line. Signing operates on a *canonical* byte represen… + - [hmac](./src/hmac/hmac.md) — This module produces the HMAC-SHA-256 tag attached to every audit line. Signing operates on a *canonical* byte represen… +- [instruments](./src/instruments/instruments.md) — This module owns the two counters the stdout sink emits at runtime, matching design doc §12.3's metric surface for the… + - [instruments](./src/instruments/instruments.md) — This module owns the two counters the stdout sink emits at runtime, matching design doc §12.3's metric surface for the… +- [options](./src/options/options.md) — This module owns the Zod schema and defaults for the scalar slice of `createStdoutAuditSink({...})`'s input. Validation… + - [options](./src/options/options.md) — This module owns the Zod schema and defaults for the scalar slice of `createStdoutAuditSink({...})`'s input. Validation… +- [schema](./src/schema/schema.md) — This module locks the wire shape of the JSON line the stdout sink writes. The shape is exactly what design doc §12.5 sp… + - [schema](./src/schema/schema.md) — This module locks the wire shape of the JSON line the stdout sink writes. The shape is exactly what design doc §12.5 sp… +- [sink](./src/sink/sink.md) — This module wires the schema, HMAC signer, instruments, and options into a `RequestAuditSink` implementation that write… + - [sink](./src/sink/sink.md) — This module wires the schema, HMAC signer, instruments, and options into a `RequestAuditSink` implementation that write… + + +## Modules + +- [`./sink`](./src/sink/sink.md) — `createStdoutAuditSink`, the + factory that ties everything together. +- [`./schema`](./src/schema/schema.md) — `AuditRecord` Zod schema and + boundary parser. +- [`./hmac`](./src/hmac/hmac.md) — canonical bytes and HMAC-SHA-256 + signer / verifier. +- [`./instruments`](./src/instruments/instruments.md) — OTel counters + (`api.audit.records_total`, `api.audit.dropped_total`). +- [`./options`](./src/options/options.md) — scalar option schema + + defaults (`maxQueueMs = 100`, `warnThrottleMs = 60_000`). +- [`./error-codes`](./src/error-codes/error-codes.md) — + `AUDIT_STDOUT.*` registry (`INVALID_RECORD`, `WRITER_FAILED`, + `QUEUE_FULL`, `INVALID_OPTIONS`). + +## Quick start + +```ts +import { createStdoutAuditSink } from "@suaveplan/api-audit-stdout"; + +const sink = createStdoutAuditSink({ + hmacKey: new TextEncoder().encode(process.env["AUDIT_HMAC_KEY"]!), +}); + +await sink.emit({ + at: "2026-05-26T10:00:00.000Z", + requestId: "req_1", + traceId: null, + route: "/admin/plugin", + plugin: "@core/admin", + method: "POST", + principal: { id: "u1", scopes: ["admin"] }, + tenantId: "t1", + status: 200, + outcome: "success", +}); +``` + +## Drop policy + +Backpressure is bounded by `maxQueueMs` (default 100ms). When the +queue wait exceeds the bound the record is dropped, the +`api.audit.dropped_total{sink,reason}` counter increments, and +(subject to a once-per-`warnThrottleMs` throttle) a single warning is +logged. Drops are NEVER silent. + diff --git a/docs/api-stack/api/api-audit-stdout/src/error-codes/error-codes.md b/docs/api-stack/api/api-audit-stdout/src/error-codes/error-codes.md new file mode 100644 index 0000000..a5d211e --- /dev/null +++ b/docs/api-stack/api/api-audit-stdout/src/error-codes/error-codes.md @@ -0,0 +1,87 @@ +# `error-codes` — `AUDIT_STDOUT_*` registry + + +_(no submodules)_ + + +## Purpose + +This module declares the four stable error codes the stdout audit sink +exposes to consumers. Every failure path inside `createStdoutAuditSink` +maps onto exactly one of them, so callers can branch on `error.code` +without parsing messages or stack traces. The registry uses +`@suaveplan/error`'s `defineCodes` so the union narrows under +`instanceof AuditStdoutError`. + +The codes capture the four observable failure modes of a write-only, +fire-and-forget audit pipeline: a record that fails its own Zod schema +(`INVALID_RECORD`), an option bag that fails the constructor schema +(`INVALID_OPTIONS`), a transport error from the supplied writer +(`WRITER_FAILED`), and the bounded-backpressure drop case +(`QUEUE_FULL`). The codes are surfaced through the +`AuditStdoutError` subclass, which carries a `code` property typed as +the literal union — `instanceof` narrowing flows through. + +## Features + +- Stable string codes via `defineCodes("AUDIT_STDOUT", [...])`. +- `AuditStdoutError` subclass with public constructor (lint rule + `check-error-subclass-constructors` enforced). +- Code union exported as `AuditStdoutErrorCode` for callers who want + to switch over every member. +- No runtime side effects — the registry is a frozen object literal. + +## Usage: Basic + +```ts +import { + AUDIT_STDOUT_CODES, + AuditStdoutError, +} from "@suaveplan/api-audit-stdout/error-codes"; + +throw new AuditStdoutError( + AUDIT_STDOUT_CODES.INVALID_RECORD, + "error.audit_stdout.invalid_record" +); +``` + +## Usage: Advanced + +```ts +import { + AUDIT_STDOUT_CODES, + AuditStdoutError, + type AuditStdoutErrorCode, +} from "@suaveplan/api-audit-stdout/error-codes"; + +function handle(err: unknown): "drop" | "rethrow" { + if (!(err instanceof AuditStdoutError)) return "rethrow"; + const code: AuditStdoutErrorCode = err.code; + switch (code) { + case AUDIT_STDOUT_CODES.QUEUE_FULL: + case AUDIT_STDOUT_CODES.WRITER_FAILED: + return "drop"; + case AUDIT_STDOUT_CODES.INVALID_RECORD: + case AUDIT_STDOUT_CODES.INVALID_OPTIONS: + return "rethrow"; + } +} +``` + +## API Reference + +- `AUDIT_STDOUT_CODES` — frozen `{ INVALID_RECORD, WRITER_FAILED, + QUEUE_FULL, INVALID_OPTIONS }` mapping to the corresponding + `"AUDIT_STDOUT.*"` literal. +- `AuditStdoutErrorCode` — union of the four literal strings. +- `AuditStdoutError` — `SuaveplanError` subclass + with a public constructor accepting `(code, message, options?)`. + +## Implementation Notes + +`defineCodes` returns a frozen object — adding a new code requires an +OpenSpec change. The subclass declares its own public constructor so +`new AuditStdoutError(...)` is callable from outside the module (the +base class is abstract with a protected constructor). The +`auditStdoutCode` field is a typed alias of `code` for callers who +want a non-generic accessor. diff --git a/docs/api-stack/api/api-audit-stdout/src/hmac/hmac.md b/docs/api-stack/api/api-audit-stdout/src/hmac/hmac.md new file mode 100644 index 0000000..b0e9963 --- /dev/null +++ b/docs/api-stack/api/api-audit-stdout/src/hmac/hmac.md @@ -0,0 +1,82 @@ +# `hmac` — canonical bytes + HMAC-SHA-256 signing + + +_(no submodules)_ + + +## Purpose + +This module produces the HMAC-SHA-256 tag attached to every audit +line. Signing operates on a *canonical* byte representation of the +record (keys serialised in a fixed order, `cause` omitted when +absent) so the same logical record always produces the same MAC under +the same key, regardless of how the source object was constructed. +Verification recomputes the MAC and constant-time-compares to the +hex-decoded signature. + +The point isn't to encrypt the record — the line is plaintext JSON +written to stdout. The HMAC catches tampering downstream: a log +collector or storage tier that re-writes a field to mask an audited +action invalidates the MAC, and the auditor's verifier flags the +discrepancy. The key never leaves the host; rotation is the caller's +concern. + +## Features + +- `canonicalBytes(record)` — UTF-8 bytes of JSON with top-level keys + in design-doc §12.5 order and `cause` omitted when absent. +- `signRecord(record, key)` — lowercase hex HMAC-SHA-256, computed + via `@suaveplan/crypto-hash`'s `hmac("SHA-256", …)` primitive. +- `verifyRecord(record, key, signatureHex)` — constant-time match; + rejects bad-length, non-hex, and tampered inputs. +- `HMAC_FIELD` — the `"_hmac"` field name the sink appends to the + JSON line. + +## Usage: Basic + +```ts +import { signRecord, verifyRecord } from "@suaveplan/api-audit-stdout/hmac"; + +const key = new Uint8Array(32); +const tag = signRecord(record, key); +const ok = verifyRecord(record, key, tag); +``` + +## Usage: Advanced + +```ts +import { + canonicalBytes, + HMAC_FIELD, + signRecord, +} from "@suaveplan/api-audit-stdout/hmac"; + +function emit(record: AuditRecord, key: Uint8Array): string { + // Equivalent to what the sink does internally, but caller-managed. + const line = JSON.parse( + new TextDecoder().decode(canonicalBytes(record)) + ) as Record; + line[HMAC_FIELD] = signRecord(record, key); + return JSON.stringify(line); +} +``` + +## API Reference + +- `canonicalBytes(record: AuditRecord): Uint8Array` +- `signRecord(record: AuditRecord, key: Uint8Array): string` — hex. +- `verifyRecord(record: AuditRecord, key: Uint8Array, sig: string): boolean` +- `HMAC_FIELD: "_hmac"` + +## Implementation Notes + +The canonical encoder lists top-level keys explicitly rather than +sorting alphabetically — the design doc fixes the order so callers +reading raw lines see fields in the documented sequence. Nested +objects use natural insertion order; their shape is locked by the +Zod schema so the JSON.stringify output is deterministic. `cause` is +omitted (not serialised as `null`) when absent so a `success` record +without `cause` and a `success` record with `cause: undefined` +produce the same MAC. Hex was chosen over base64 because hex is +case-insensitive trivially and stays ASCII-safe through every common +log pipeline. diff --git a/docs/api-stack/api/api-audit-stdout/src/instruments/instruments.md b/docs/api-stack/api/api-audit-stdout/src/instruments/instruments.md new file mode 100644 index 0000000..0e89482 --- /dev/null +++ b/docs/api-stack/api/api-audit-stdout/src/instruments/instruments.md @@ -0,0 +1,70 @@ +# `instruments` — OTel counters for the stdout audit sink + + +_(no submodules)_ + + +## Purpose + +This module owns the two counters the stdout sink emits at runtime, +matching design doc §12.3's metric surface for the audit pipeline. +Operators wire the `MeterProvider` once at process boot; the sink +picks up the configured provider through this factory. When no SDK +is installed, the OTel global resolves to a no-op meter so the sink +runs cleanly in tests without any ceremony. + +The factory returns a frozen bundle so the sink does zero meter +lookups on the hot path — both counters are constructed once and the +record's `type` / `outcome` labels are attached at observation time. + +## Features + +- `api.audit.records_total{sink, type, outcome}` — successful write + counter. +- `api.audit.dropped_total{sink, reason}` — drop counter for + queue-full and writer-failed paths. +- Default meter provider falls back to the OTel global. +- Frozen bundle — references stable for the sink's lifetime. + +## Usage: Basic + +```ts +import { createStdoutAuditInstruments } from "@suaveplan/api-audit-stdout/instruments"; + +const instruments = createStdoutAuditInstruments(); +instruments.recordsTotal.add(1, { + sink: "stdout", + type: "request.success", + outcome: "success", +}); +``` + +## Usage: Advanced + +```ts +import { MeterProvider } from "@opentelemetry/sdk-metrics"; +import { createStdoutAuditInstruments } from "@suaveplan/api-audit-stdout/instruments"; + +const meterProvider = new MeterProvider(); +const instruments = createStdoutAuditInstruments({ meterProvider }); + +// Hand them into createStdoutAuditSink so the sink emits through the +// SDK-installed provider rather than the global no-op. +``` + +## API Reference + +- `createStdoutAuditInstruments(config?)` + - `meterProvider?: MeterProvider` — defaults to + `metrics.getMeterProvider()`. + - Returns `StdoutAuditInstruments` with `meter`, `recordsTotal`, + `droppedTotal`. + +## Implementation Notes + +Counters are constructed eagerly so the first write does zero +allocations beyond the attribute object. The bundle is frozen to +prevent accidental shadowing. The `sink="stdout"` attribute is +attached at observation time by the sink so the same provider can +serve multiple sink implementations side by side (file, vault, etc.) +without conflict on the metric name. diff --git a/docs/api-stack/api/api-audit-stdout/src/options/options.md b/docs/api-stack/api/api-audit-stdout/src/options/options.md new file mode 100644 index 0000000..bc8e287 --- /dev/null +++ b/docs/api-stack/api/api-audit-stdout/src/options/options.md @@ -0,0 +1,75 @@ +# `options` — constructor option schema and defaults + + +_(no submodules)_ + + +## Purpose + +This module owns the Zod schema and defaults for the scalar slice of +`createStdoutAuditSink({...})`'s input. Validation happens at the +boundary — a typo on `maxQueueMs` raises +`AUDIT_STDOUT.INVALID_OPTIONS` rather than silently being ignored. +The schema is `.strict()` so unknown keys are rejected (same rationale +as the `AuditRecord` schema). + +The non-scalar slots — writer, clock, timers, logger, instruments, +hmacKey — bypass Zod and are checked structurally by the sink itself +at construction. Mixing the two validation styles keeps the typed +surface narrow while still rejecting obvious typos. + +## Features + +- Strict Zod schema for scalar option keys. +- Defaults: `maxQueueMs = 100`, `warnThrottleMs = 60_000`, + `sinkLabel = "stdout"`. +- Resolver wraps any `ZodError` as `AUDIT_STDOUT.INVALID_OPTIONS`. +- Constants exported so callers can reference them when computing + test throughput budgets. + +## Usage: Basic + +```ts +import { resolveStdoutAuditScalarOptions } from "@suaveplan/api-audit-stdout/options"; + +const resolved = resolveStdoutAuditScalarOptions({ maxQueueMs: 250 }); +// resolved.warnThrottleMs === 60_000 (default) +``` + +## Usage: Advanced + +```ts +import { + DEFAULT_MAX_QUEUE_MS, + resolveStdoutAuditScalarOptions, + type StdoutAuditScalarOptions, +} from "@suaveplan/api-audit-stdout/options"; + +function tightenedForTests(): StdoutAuditScalarOptions { + return { + maxQueueMs: Math.max(1, DEFAULT_MAX_QUEUE_MS / 10), + warnThrottleMs: 1_000, + }; +} + +const resolved = resolveStdoutAuditScalarOptions(tightenedForTests()); +``` + +## API Reference + +- `stdoutAuditScalarOptionsSchema` — strict Zod object. +- `StdoutAuditScalarOptions` — inferred type. +- `ResolvedStdoutAuditScalarOptions` — defaults-applied shape. +- `resolveStdoutAuditScalarOptions(raw)` — boundary parser. +- `DEFAULT_MAX_QUEUE_MS`, `DEFAULT_WARN_THROTTLE_MS` — constants. + +## Implementation Notes + +`maxQueueMs` is bounded to positive integers because a value of 0 +would mean "never queue" — that's a different semantics (synchronous +backpressure) and would need its own option. `warnThrottleMs` +governs the once-per-window log; tests use a `FakeClock` plus a +short throttle to exercise the throttle without sleeping. The +`sinkLabel` exists so a future spinoff (e.g. journald) can reuse +this module while still attaching a distinct `sink="…"` label to its +counters. diff --git a/docs/api-stack/api/api-audit-stdout/src/schema/schema.md b/docs/api-stack/api/api-audit-stdout/src/schema/schema.md new file mode 100644 index 0000000..ce50bc2 --- /dev/null +++ b/docs/api-stack/api/api-audit-stdout/src/schema/schema.md @@ -0,0 +1,95 @@ +# `schema` — `AuditRecord` Zod schema (design doc §12.5) + + +_(no submodules)_ + + +## Purpose + +This module locks the wire shape of the JSON line the stdout sink +writes. The shape is exactly what design doc §12.5 specifies for the +admin / audit pipeline: `ts`, `type`, `principal`, `tenant`, +`request_id`, `trace_id`, `subject`, `outcome`, and a conditional +`cause`. Every write goes through `parseAuditRecord(...)` so a +malformed record raises `AUDIT_STDOUT.INVALID_RECORD` *before* a line +is written — log pipelines downstream never see a half-finished +record. + +The schema is `.strict()` (unknown top-level fields are rejected) and +carries a `refine` enforcing the §12.5 invariant that `cause` is +REQUIRED when `outcome === "failure"`. Optional fields surface via +`exactOptionalPropertyTypes` parity so a missing `cause` on a +`success` record is distinct from `cause: undefined` on a `failure` +record. The principal slice is its own sub-schema so the same shape +can be reused by other audit sinks that target the same wire format. + +## Features + +- Strict shape — extra keys rejected. +- `outcome === "failure"` requires `cause` (refine rule). +- Sub-schemas for `cause`, `principal`, and `outcome` so consumers can + type their own DTOs against the same atoms. +- `parseAuditRecord(input)` returns the validated record or throws + `AUDIT_STDOUT.INVALID_RECORD` wrapping the underlying `ZodError`. +- All types are `z.infer<...>` — no hand-written interfaces drift. + +## Usage: Basic + +```ts +import { parseAuditRecord } from "@suaveplan/api-audit-stdout/schema"; + +const record = parseAuditRecord({ + ts: "2026-05-26T10:00:00.000Z", + type: "admin.plugin.disabled", + principal: { id: "user_1", scopes: ["admin"] }, + tenant: "tenant_a", + request_id: "req_1", + trace_id: null, + subject: "plugin.exports", + outcome: "success", +}); +``` + +## Usage: Advanced + +```ts +import { + auditRecordSchema, + type AuditRecord, +} from "@suaveplan/api-audit-stdout/schema"; + +function adapt(envelope: HostEnvelope): AuditRecord { + return auditRecordSchema.parse({ + ts: envelope.at, + type: `request.${envelope.outcome}`, + principal: envelope.principal, + tenant: envelope.tenantId, + request_id: envelope.requestId, + trace_id: envelope.traceId, + subject: `${envelope.method} ${envelope.route}`, + outcome: envelope.outcome, + ...(envelope.cause !== undefined ? { cause: envelope.cause } : {}), + }); +} +``` + +## API Reference + +- `auditRecordSchema` — strict Zod object with the §12.5 invariant + refined. +- `auditCauseSchema`, `auditPrincipalSchema`, `auditOutcomeSchema` — + sub-schemas reused by consumers. +- `AuditRecord`, `AuditCause`, `AuditPrincipal`, `AuditOutcome` — + inferred types. +- `parseAuditRecord(input: unknown): AuditRecord` — boundary parser + that throws `AuditStdoutError(AUDIT_STDOUT.INVALID_RECORD, …)` on + failure. + +## Implementation Notes + +`.strict()` blocks unknown fields at the boundary — if a future +design-doc revision adds fields, this schema must be updated in the +same OpenSpec change as the spec. The `outcome === "failure"` / +`cause` refine is enforced as a Zod `.refine` rather than a +discriminated union so the failure path returns a `ZodError` with a +single readable `path: ["cause"]` issue. diff --git a/docs/api-stack/api/api-audit-stdout/src/sink/sink.md b/docs/api-stack/api/api-audit-stdout/src/sink/sink.md new file mode 100644 index 0000000..7db2fb4 --- /dev/null +++ b/docs/api-stack/api/api-audit-stdout/src/sink/sink.md @@ -0,0 +1,108 @@ +# `sink` — `createStdoutAuditSink` + + +_(no submodules)_ + + +## Purpose + +This module wires the schema, HMAC signer, instruments, and options +into a `RequestAuditSink` implementation that writes JSON-per-line +audit records to a `LineWriter` (default `process.stdout`). It is the +default audit sink shipped with `@suaveplan/api-host`: container +runtimes already redirect stdout into a log pipeline, so operators +inherit the records without touching host configuration. + +The sink is single-flight: at most one write is on the wire at any +time. Subsequent records wait for the slot, but only up to +`maxQueueMs` (default 100ms) before being dropped. Drops are NEVER +silent — every drop increments `api.audit.dropped_total{sink,reason}` +and (subject to the once-per-`warnThrottleMs` throttle) emits a +single warning log. Validation, HMAC signing, and serialisation +happen on the calling side of the queue so a malformed record is +rejected synchronously without consuming the slot. + +## Features + +- Implements `RequestAuditSink` (`emit(envelope)`) from + `@suaveplan/api-host/request-pipeline` — host accepts the instance + directly. +- `write(record: AuditRecord)` overload for admin paths that already + hold a canonical record. +- Boundary Zod validation — `AUDIT_STDOUT.INVALID_RECORD` on a bad + record. +- Bounded queue — `AUDIT_STDOUT.QUEUE_FULL` on timeout, drop counter + + throttled warning. +- HMAC-SHA-256 over canonical bytes appended as `_hmac` field. +- `dispose()` drains the in-flight write and rejects subsequent + writes as `closed` drops. +- Pluggable `clock`, `timers`, `logger`, `writer`, `instruments`. + +## Usage: Basic + +```ts +import { createStdoutAuditSink } from "@suaveplan/api-audit-stdout/sink"; + +const sink = createStdoutAuditSink({ + hmacKey: new TextEncoder().encode(process.env["AUDIT_HMAC_KEY"]!), +}); +await sink.write({ + ts: new Date().toISOString(), + type: "admin.plugin.disabled", + principal: { id: "user_1", scopes: ["admin"] }, + tenant: "tenant_a", + request_id: "req_1", + trace_id: null, + subject: "plugin.exports", + outcome: "success", +}); +``` + +## Usage: Advanced + +```ts +import { createStdoutAuditSink } from "@suaveplan/api-audit-stdout/sink"; +import { createStdoutAuditInstruments } from "@suaveplan/api-audit-stdout/instruments"; +import { MeterProvider } from "@opentelemetry/sdk-metrics"; + +const meterProvider = new MeterProvider({ readers: [...] }); +const sink = createStdoutAuditSink({ + hmacKey, + writer: { + async write(line) { + await myStream.write(line); + }, + }, + maxQueueMs: 250, + warnThrottleMs: 30_000, + instruments: createStdoutAuditInstruments({ meterProvider }), + logger: myLogger, +}); +// Hand into createHost({ audit: sink }) per host wiring. +await sink.emit(envelope); +await sink.dispose(); +``` + +## API Reference + +- `createStdoutAuditSink(options)` → `StdoutAuditSink`. +- `StdoutAuditSinkOptions` — `{ hmacKey, writer?, clock?, timers?, + logger?, instruments?, maxQueueMs?, warnThrottleMs?, sinkLabel? }`. +- `StdoutAuditSink` — extends `RequestAuditSink`; adds `write(record)` + and `dispose()`. +- `LineWriter` — `{ write(line: string): void | Promise }`. +- `adaptEnvelope(envelope)` — exposed for tests and bespoke + re-emission flows. + +## Implementation Notes + +The slot reservation uses an in-flight `Promise` rather than a +queue + worker so cancellation flows trivially through GC — there's +no worker loop to shut down. `acquireSlot` races the in-flight write +against the `timers.setTimer` callback; whichever wins clears the +loser. The `closed` flag is checked before validation so a disposed +sink rejects fast without spending CPU on schema work. +`adaptEnvelope` is the only place the host's camelCase envelope +shape meets the canonical snake_case record — keeping that mapping +isolated lets the design-doc wire shape evolve without rippling +through unrelated callers. diff --git a/docs/api-stack/api/api-auth-anonymous/README.md b/docs/api-stack/api/api-auth-anonymous/README.md new file mode 100644 index 0000000..3316dc8 --- /dev/null +++ b/docs/api-stack/api/api-auth-anonymous/README.md @@ -0,0 +1,60 @@ +# @suaveplan/api-auth-anonymous — trivial session resolver for @suaveplan/api: always returns null Principal. Used as the tail of resolver chains for fully public APIs and as the foundation conformance seed for every other session-resolver in the stack. + +Stage-4 trivial session resolver for `@suaveplan/api`. +Always returns `null` for every request. Use this as the tail of resolver +chains for public endpoints, and as the canonical adapter for fully public +APIs. The package also serves as the foundation conformance seed exercised by +every other concrete session-resolver in Stages 4 / 6 / 8. + + +## Documentation tree + +- [adapter](./src/adapter/adapter.md) — Canonical `AuthAdapter` for fully public APIs. Pairs the trivial anonymous resolver with the minimal adapter metadata t… + - [adapter](./src/adapter/adapter.md) — Canonical `AuthAdapter` for fully public APIs. Pairs the trivial anonymous resolver with the minimal adapter metadata t… +- [error-codes](./src/error-codes/error-codes.md) — Stable error-code registry for `@suaveplan/api-auth-anonymous`. The anonymous resolver has no per-request failure modes… + - [error-codes](./src/error-codes/error-codes.md) — Stable error-code registry for `@suaveplan/api-auth-anonymous`. The anonymous resolver has no per-request failure modes… +- [resolver](./src/resolver/resolver.md) — Factory for the trivial `SessionResolver` that always returns `null`. This is the canonical tail-of-chain resolver ever… + - [resolver](./src/resolver/resolver.md) — Factory for the trivial `SessionResolver` that always returns `null`. This is the canonical tail-of-chain resolver ever… + + +## Why does "no auth" need its own package? + +Per the API foundation design doc §2.3, every host configures a session +resolver — even fully public APIs. Configuring `ANONYMOUS_AUTH_ADAPTER` +explicitly makes the "no auth" choice visible in `host.json` and lets the rest +of the host (RBAC gate, error envelope, OpenAPI emission) operate uniformly: +the principal is simply `null`, never `undefined`. + +## Surface + +| Subpath | Export | +|----------------|---------------------------------------------------| +| `./resolver` | `createAnonymousResolver(opts?): SessionResolver` | +| `./adapter` | `ANONYMOUS_AUTH_ADAPTER: AuthAdapter` | +| `./error-codes`| `AUTH_ANON_CODES`, `AuthAnonError` | + +## Usage + +```ts +import { ANONYMOUS_AUTH_ADAPTER } from "@suaveplan/api-auth-anonymous/adapter"; + +host.registerAuth(ANONYMOUS_AUTH_ADAPTER); +// every request now produces `principal: null`; public routes proceed, +// non-public routes 401 via the host's `publicRoutes` decision. +``` + +For mixed chains, see `createAnonymousResolver()` + `SessionResolverChain` +in `@suaveplan/api-auth/chain`. + +## Conformance + +The resolver passes `runAuthSessionConformance` (null-only mode) from +`@suaveplan/api-auth/testing`. See +`src/resolver/resolver.test.ts`. + +## Errors + +`AUTH_ANON.INVALID_OPTIONS` — thrown only when the factory is handed a +non-object or unknown-key options bag. No per-request error paths exist by +design. + diff --git a/docs/api-stack/api/api-auth-anonymous/src/adapter/adapter.md b/docs/api-stack/api/api-auth-anonymous/src/adapter/adapter.md new file mode 100644 index 0000000..b81c96f --- /dev/null +++ b/docs/api-stack/api/api-auth-anonymous/src/adapter/adapter.md @@ -0,0 +1,72 @@ +# `adapter` — `ANONYMOUS_AUTH_ADAPTER` + + +_(no submodules)_ + + +## Purpose + +Canonical `AuthAdapter` for fully public APIs. Pairs the trivial anonymous +resolver with the minimal adapter metadata the host needs to wire it into the +per-request pipeline. The adapter omits `securityScheme` on purpose: +`validateAuthAdapter` permits a missing scheme for the anonymous topology so +the emitted OpenAPI document contains no `security` entry on routes — the +correct shape for "no authentication required". + +## Features + +- Stateless singleton — safe to import once per host process. +- `csrf: false` baked in: anonymous traffic has no session to protect; the + generic CSRF middleware in `@suaveplan/api-auth/csrf-policy` skips routes + whose adapter pins `csrf: false`. +- Validates cleanly against `validateAuthAdapter` — no runtime error at host + registration time despite the omitted security scheme. + +## Usage: Basic + +```ts +import { ANONYMOUS_AUTH_ADAPTER } from "@suaveplan/api-auth-anonymous/adapter"; +import { validateAuthAdapter } from "@suaveplan/api-auth"; + +const adapter = validateAuthAdapter(ANONYMOUS_AUTH_ADAPTER); +host.registerAuth(adapter); +``` + +## Usage: Advanced + +For a chain that mixes typed resolvers with the anonymous tail, do not use +`ANONYMOUS_AUTH_ADAPTER` directly — assemble a `SessionResolverChain` so the +typed resolvers fire first: + +```ts +import { SessionResolverChain } from "@suaveplan/api-auth"; +import { createAnonymousResolver } from "@suaveplan/api-auth-anonymous/resolver"; + +const chain = new SessionResolverChain([ + jwtResolver, + createAnonymousResolver(), +]); +const adapter = { + resolver: chain, + securityScheme: jwtSecurityScheme, // the typed resolver still emits its scheme +} as const; +``` + +## API Reference + +| Symbol | Kind | Description | +|------------------------------|----------|------------------------------------------------| +| `ANONYMOUS_AUTH_ADAPTER` | const | `AuthAdapter` with anonymous resolver, no scheme, `csrf: false`. | + +## Implementation Notes + +- The constant is constructed once at module load and reused across requests + — the resolver itself is documented stateless, so a single instance is safe + to fan out across concurrent requests. +- `csrf: false` is deliberate. Anonymous requests carry no session cookie, so + applying CSRF defence would reject legitimate public traffic. Hosts that + want to additionally rate-limit anonymous traffic should layer + `api-rate-limit` (Stage 8) on top — that is not this package's concern. +- Test coverage exercises (a) `validateAuthAdapter(ANONYMOUS_AUTH_ADAPTER)` + returns the adapter unchanged, (b) the embedded resolver still resolves + null, and (c) the singleton survives repeated import without re-allocation. diff --git a/docs/api-stack/api/api-auth-anonymous/src/error-codes/error-codes.md b/docs/api-stack/api/api-auth-anonymous/src/error-codes/error-codes.md new file mode 100644 index 0000000..9967991 --- /dev/null +++ b/docs/api-stack/api/api-auth-anonymous/src/error-codes/error-codes.md @@ -0,0 +1,77 @@ +# `error-codes` — `AUTH_ANON.*` registry + + +_(no submodules)_ + + +## Purpose + +Stable error-code registry for `@suaveplan/api-auth-anonymous`. The anonymous +resolver has no per-request failure modes — every request resolves to `null` by +construction. The single `AUTH_ANON.INVALID_OPTIONS` code covers the only thing +that can fail, which is rejecting malformed options handed to +`createAnonymousResolver(opts)` at construction time. Keeping a dedicated +code-namespace per package (rather than re-using `AUTH.*`) means consumers can +disambiguate anonymous-side problems from general session-resolver issues when +multiple resolvers are mounted on the same chain. + +## Features + +- Defined via `defineCodes("AUTH_ANON", [...])` from `@suaveplan/error` so the + literal value is always `"AUTH_ANON.INVALID_OPTIONS"`. +- `AuthAnonError extends SuaveplanError` — instance checks + narrow `error.code` to the registry type at the type level. +- Carries `authAnonCode` as a non-discriminating mirror so adapter code can + branch on `err.authAnonCode === AUTH_ANON_CODES.INVALID_OPTIONS` without + re-typing the parent class. + +## Usage: Basic + +```ts +import { AUTH_ANON_CODES, AuthAnonError } from "@suaveplan/api-auth-anonymous/error-codes"; + +throw new AuthAnonError( + AUTH_ANON_CODES.INVALID_OPTIONS, + "createAnonymousResolver: options is not an object" +); +``` + +## Usage: Advanced + +Wrap a parser failure (e.g. zod) and forward its details into the +`context.issues` slot so observability pipelines can render the schema diff: + +```ts +import { AUTH_ANON_CODES, AuthAnonError } from "@suaveplan/api-auth-anonymous/error-codes"; +import z from "zod"; + +const OptionsSchema = z.object({}).strict(); + +export function parseOptions(input: unknown): Record { + const out = OptionsSchema.safeParse(input); + if (!out.success) { + throw new AuthAnonError( + AUTH_ANON_CODES.INVALID_OPTIONS, + "Anonymous resolver options failed schema validation", + { context: { issues: out.error.issues } } + ); + } + return out.data; +} +``` + +## API Reference + +| Symbol | Kind | Description | +|----------------------|----------|------------------------------------------------------------| +| `AUTH_ANON_CODES` | const | `{ INVALID_OPTIONS: "AUTH_ANON.INVALID_OPTIONS" }` | +| `AuthAnonErrorCode` | type | Union of values in `AUTH_ANON_CODES`. | +| `AuthAnonError` | class | `extends SuaveplanError`. | + +## Implementation Notes + +- The single code is deliberate. The resolver is documented to never reject a + request; adding speculative codes for "unrecognised credential" or + "principal lookup failed" would be lying about a contract that the + implementation cannot break by construction. +- Tested in `error-codes.test.ts` for both string value and instance shape. diff --git a/docs/api-stack/api/api-auth-anonymous/src/resolver/resolver.md b/docs/api-stack/api/api-auth-anonymous/src/resolver/resolver.md new file mode 100644 index 0000000..8efe1dd --- /dev/null +++ b/docs/api-stack/api/api-auth-anonymous/src/resolver/resolver.md @@ -0,0 +1,79 @@ +# `resolver` — `createAnonymousResolver` + + +_(no submodules)_ + + +## Purpose + +Factory for the trivial `SessionResolver` that always returns `null`. This is +the canonical tail-of-chain resolver every public-API host configures: it +makes the "no auth" choice explicit in `host.json` and lets the rest of the +host (RBAC gate, error envelope, OpenAPI emission) operate uniformly because +`principal` is `null` not `undefined`. The factory shape exists — rather than +exposing a constant — so future option flags (e.g. `logAnonymousAccess`) can +be threaded in without a breaking surface change. + +## Features + +- Always resolves `null` — no header inspection, no network I/O, no state. +- Idempotent `dispose()` no-op (resolver holds no resources). +- Strict zod options schema rejects non-object input and unknown keys with + `AUTH_ANON.INVALID_OPTIONS`. +- Returned type is `SessionResolver` from `@suaveplan/api-auth/resolver` so + it composes directly into `SessionResolverChain`. + +## Usage: Basic + +```ts +import { createAnonymousResolver } from "@suaveplan/api-auth-anonymous/resolver"; + +const resolver = createAnonymousResolver(); +// Inside a request pipeline: +const principal = await resolver.resolve(request); // → null +await resolver.dispose(); // safe to call again +``` + +## Usage: Advanced + +Compose as the tail of a resolver chain so a JWT-typed resolver runs first +and the anonymous resolver supplies the `null` short-circuit for unrecognised +requests on public routes: + +```ts +import { SessionResolverChain } from "@suaveplan/api-auth"; +import { createAnonymousResolver } from "@suaveplan/api-auth-anonymous/resolver"; + +const chain = new SessionResolverChain([ + jwtResolver, // recognises Bearer tokens, else returns null + apiKeyResolver, // recognises x-api-key, else returns null + createAnonymousResolver(), // tail: always null +]); + +const principal = await chain.resolve(request); +// principal is now `Principal | null`. The host applies its `publicRoutes` +// decision: a non-public route 401s; a public route proceeds with null. +``` + +## API Reference + +| Symbol | Kind | Description | +|------------------------------|----------|-------------------------------------------------------| +| `createAnonymousResolver` | function | `(opts?: AnonymousResolverOptions) => SessionResolver`. | +| `AnonymousResolverOptions` | type | Reserved-for-future-flags options bag. | + +## Implementation Notes + +- The resolver returns `Promise` literally rather than the wider + `Promise` so type narrowing in tests can use + `expectTypeOf<...>().toEqualTypeOf>()`. The chain widens it + back to `Principal | null` at the boundary. +- `dispose()` is a `Promise` not just any promise — the conformance + harness asserts the resolved value is `undefined` so this is load-bearing. +- The factory is the public surface (not a const) because future flags must + be addable without a breaking change to call sites. Even today, passing + `{}` is the canonical call. +- No OTel instrumentation is emitted from this resolver. Anonymous-access + observability lives at the host layer (per-request span tag) — adding + counters here would force a foundation-tier package to depend on + `@suaveplan/opentelemetry`, which is undesirable for a hot path. diff --git a/docs/api-stack/api/api-auth-bearer-static/README.md b/docs/api-stack/api/api-auth-bearer-static/README.md new file mode 100644 index 0000000..2027748 --- /dev/null +++ b/docs/api-stack/api/api-auth-bearer-static/README.md @@ -0,0 +1,155 @@ +# @suaveplan/api-auth-bearer-static — SessionResolver adapter for service-to-service static bearer tokens. Matches Authorization: Bearer against a fixed token→Principal table using constant-time comparison from @suaveplan/crypto-utils; unknown tokens defer to the next chain entry. Supports an optional per-token mutual-TLS gate that rejects when the host did not surface request.tls.peerCertificate. Ships both a direct surface (createBearerStaticResolver) and a worker-proxy surface (createBearerStaticResolverWorkerProxy) over @suaveplan/api-worker-rpc; both pass runAuthSessionConformance from @suaveplan/api-auth/testing. OpenAPI security-scheme contribution (HTTP Bearer). Zod-validated options, AUTH_BEARER_STATIC.* error codes, OTel match counter partitioned by outcome. + +Stage-4 service-to-service `SessionResolver` adapter for the +`@suaveplan/api` plugin system. Matches an inbound `Authorization: +Bearer ` header against a fixed `token → Principal` table using +constant-time comparison from `@suaveplan/crypto-utils`. Unknown tokens +return `null` so the host's `SessionResolverChain` falls through to the +next adapter (typically `api-auth-jwt` for user sessions). + +Ships both the direct surface (`createBearerStaticResolver`) and the +worker-proxy surface (`createBearerStaticResolverWorkerProxy` + +`serveBearerStaticResolverOnPort`) over `@suaveplan/api-worker-rpc`; both +pass `runAuthSessionConformance` from `@suaveplan/api-auth/testing`. + + +## Documentation tree + +- [constant-time](./src/constant-time/token-match.md) — `findTokenIndex` performs a constant-time lookup of a presented bearer token against a fixed table, returning the match… + - [token-match](./src/constant-time/token-match.md) — `findTokenIndex` performs a constant-time lookup of a presented bearer token against a fixed table, returning the match… +- [error-codes](./src/error-codes/error-codes.md) — The error-codes module defines the stable `AUTH_BEARER_STATIC.*` namespace that every public failure path in this packa… + - [error-codes](./src/error-codes/error-codes.md) — The error-codes module defines the stable `AUTH_BEARER_STATIC.*` namespace that every public failure path in this packa… +- [factory](./src/factory/create-bearer-static-resolver.md) — `createBearerStaticResolver` is the direct-surface entry point of the package. It accepts validated `BearerStaticResolv… + - [create-bearer-static-resolver](./src/factory/create-bearer-static-resolver.md) — `createBearerStaticResolver` is the direct-surface entry point of the package. It accepts validated `BearerStaticResolv… +- [mtls](./src/mtls/mtls-gate.md) — The mTLS gate enforces an optional second factor on individual token table entries. When operators mark an entry with `… + - [mtls-gate](./src/mtls/mtls-gate.md) — The mTLS gate enforces an optional second factor on individual token table entries. When operators mark an entry with `… +- [options](./src/options/bearer-static-resolver-options.md) — The options module owns the public construction surface of every resolver in this package. It defines the `BearerStatic… + - [bearer-static-resolver-options](./src/options/bearer-static-resolver-options.md) — The options module owns the public construction surface of every resolver in this package. It defines the `BearerStatic… +- [proxy](./src/proxy/create-bearer-static-resolver-worker-proxy.md) — The worker-proxy surface is the second of the two Stage-4 surfaces this adapter ships (`§5.2a`). It lets the host insta… + - [create-bearer-static-resolver-worker-proxy](./src/proxy/create-bearer-static-resolver-worker-proxy.md) — The worker-proxy surface is the second of the two Stage-4 surfaces this adapter ships (`§5.2a`). It lets the host insta… +- [security-scheme](./src/security-scheme/security-scheme-contribution.md) — This module builds the OpenAPI 3.1 `components.securitySchemes` contribution the adapter publishes to the host's `AuthA… + - [security-scheme-contribution](./src/security-scheme/security-scheme-contribution.md) — This module builds the OpenAPI 3.1 `components.securitySchemes` contribution the adapter publishes to the host's `AuthA… +- [telemetry](./src/telemetry/instruments.md) — The telemetry module owns the single OpenTelemetry counter this package emits — `api.auth.bearer_static_match_total` —… + - [instruments](./src/telemetry/instruments.md) — The telemetry module owns the single OpenTelemetry counter this package emits — `api.auth.bearer_static_match_total` —… + + +## Install + +```sh +bun add @suaveplan/api-auth-bearer-static +``` + +## Direct surface + +```ts +import { createBearerStaticResolver } from "@suaveplan/api-auth-bearer-static"; +import { SessionResolverChain } from "@suaveplan/api-auth"; + +const serviceAuth = createBearerStaticResolver({ + tokens: [ + { + token: process.env.CRON_TOKEN, + principal: { + id: "svc_cron", + scopes: ["jobs:run"], + claims: { kind: "service" }, + }, + }, + { + token: process.env.ADMIN_TOKEN, + principal: { + id: "svc_admin", + scopes: ["admin:*"], + claims: { kind: "admin" }, + }, + mtlsRequired: true, + }, + ], +}); + +// Chained — service tokens first, JWT users fall through. +const chain = new SessionResolverChain([serviceAuth, jwtResolver]); +``` + +## Chained-resolver pattern with `api-auth-jwt` + +The intended deployment topology pairs this adapter with +`@suaveplan/api-auth-jwt` for user sessions. Static-token callers match +first; everything else flows to JWT. The chain's `first-match-wins` +semantics means unknown tokens never throw — they simply move on. + +```ts +import { SessionResolverChain } from "@suaveplan/api-auth"; +import { createBearerStaticResolver } from "@suaveplan/api-auth-bearer-static"; +import { createJwtSessionResolver } from "@suaveplan/api-auth-jwt"; // future sibling + +const chain = new SessionResolverChain([ + createBearerStaticResolver({ + tokens: [/* service callers */], + }), + createJwtSessionResolver({ + issuer: "https://idp.example", + audience: "suaveplan", + }), +]); +``` + +## Worker-proxy surface + +Use the worker-proxy variant when the host process should not hold the +real token table — e.g. an isolated auth worker serving multiple host +workers. The host imports `createBearerStaticResolverWorkerProxy(port)`; +the worker imports `serveBearerStaticResolverOnPort(port, options)`. The +proxy transparently passes `runAuthSessionConformance`, so plugin code +treats it identically to the direct surface. + +```ts +// host.ts +const proxy = createBearerStaticResolverWorkerProxy(port); +const chain = new SessionResolverChain([proxy, jwtResolver]); +``` + +```ts +// worker.ts +serveBearerStaticResolverOnPort(port, { + tokens: [/* real table — never crosses to the host */], +}); +``` + +## Optional mutual-TLS gate + +Token entries MAY carry `mtlsRequired: true`. When set, the resolver +requires the host listener to surface a verified peer certificate via +`request.tls.peerCertificate`; absent → returns `null` (outcome: +`mtls-required`). The adapter does NOT establish TLS — that is the host +listener's responsibility (Bun TLS, Node `https`, Cloudflare Worker TLS +terminator, etc.). + +## Token rotation + +This adapter is intentionally static — rotate tokens by reloading host +config. There is no DB-backed lookup, no JWKS, no refresh loop. If +you need rotation without restarts, use `api-auth-better-auth` or a +future `api-auth-token-table` adapter; this one is the simplest possible +thing that resolves a fixed table against constant-time match. + +## Errors + +The package exposes the `AUTH_BEARER_STATIC.*` code namespace via +`AUTH_BEARER_STATIC_CODES`. Only `INVALID_OPTIONS` is thrown +(synchronously, at factory construction); `NO_TOKEN`, `UNKNOWN_TOKEN`, +and `MTLS_REQUIRED` are surfaced via the OTel match counter's `outcome` +label. + +## Telemetry + +One counter — `api.auth.bearer_static_match_total{outcome=match|no-token|unknown-token|mtls-required}` +— increments exactly once per `resolve()` call. + +## Conformance + +Both surfaces pass `runAuthSessionConformance` from +`@suaveplan/api-auth`. Spec-conformance tests live alongside the source +under `src/factory/*.spec-conformance.test.ts` and +`src/proxy/*.spec-conformance.test.ts`. + diff --git a/docs/api-stack/api/api-auth-bearer-static/src/constant-time/token-match.md b/docs/api-stack/api/api-auth-bearer-static/src/constant-time/token-match.md new file mode 100644 index 0000000..7d25b20 --- /dev/null +++ b/docs/api-stack/api/api-auth-bearer-static/src/constant-time/token-match.md @@ -0,0 +1,82 @@ +# Token match — `@suaveplan/api-auth-bearer-static` + + +_(no submodules)_ + + +## Purpose + +`findTokenIndex` performs a constant-time lookup of a presented bearer +token against a fixed table, returning the matching entry's index or `-1` +if no entry matches. The function is the security boundary of the package: +every other code path in the resolver assumes the match is timing-safe so +an attacker cannot binary-search the token table by measuring response +latency. + +The implementation walks every entry, calling `constantTimeEqual` from +`@suaveplan/crypto-utils` once per row. The match-tracking variable is +written only on the first match; subsequent matches are ignored. Crucially +the loop does not break on first match — exiting early would leak the +position of the matching token via wall-clock timing. + +## Features + +- Wraps `@suaveplan/crypto-utils` `constantTimeEqual` over UTF-8 byte + views. +- Iterates the full table for every call — no early exit, no short-circuit + on `presented === entry.token`. +- Returns the first matching index or `-1`. +- Handles `undefined` entries (defensive guard for sparse arrays). + +## Usage: Basic + +```ts +import { findTokenIndex } from "@suaveplan/api-auth-bearer-static/constant-time"; + +const table = [ + { token: "T1" }, + { token: "T2" }, +]; + +const index = findTokenIndex("T2", table); +// index === 1 +``` + +## Usage: Advanced + +```ts +import { findTokenIndex } from "@suaveplan/api-auth-bearer-static/constant-time"; + +interface TokenEntry { + readonly token: string; + readonly principalId: string; +} + +const table: ReadonlyArray = [ + { token: "service-cron", principalId: "p1" }, + { token: "service-admin", principalId: "p2" }, +]; + +function lookup(presented: string): TokenEntry | null { + const idx = findTokenIndex(presented, table); + return idx === -1 ? null : (table[idx] ?? null); +} +``` + +## API Reference + +- `findTokenIndex(presented: string, table: ReadonlyArray<{ token: string }>): number` + — returns the index of the first entry whose `token` matches + `presented`, or `-1` if no entry matches. + +## Implementation Notes + +`constantTimeEqual` from `@suaveplan/crypto-utils` walks every byte of the +two `Uint8Array` views and accumulates differences into an integer via +bitwise OR; the function returns whether the accumulator stayed zero. The +length-mismatch fast path is documented as not secret (token lengths are +not secret in this adapter's threat model — the table is operator-supplied +config). The `TextEncoder` round-trip ensures we compare bytes, not +surrogate-pair code units; otherwise an attacker could compare a multi- +byte presented token against a single-byte entry and learn from the +length-mismatch shortcut whether their candidate had the right length. diff --git a/docs/api-stack/api/api-auth-bearer-static/src/error-codes/error-codes.md b/docs/api-stack/api/api-auth-bearer-static/src/error-codes/error-codes.md new file mode 100644 index 0000000..d535c65 --- /dev/null +++ b/docs/api-stack/api/api-auth-bearer-static/src/error-codes/error-codes.md @@ -0,0 +1,94 @@ +# Error codes — `@suaveplan/api-auth-bearer-static` + + +_(no submodules)_ + + +## Purpose + +The error-codes module defines the stable `AUTH_BEARER_STATIC.*` namespace +that every public failure path in this package surfaces. Codes are produced +by `defineCodes` from `@suaveplan/error` so the registry yields a frozen +record of fully-qualified strings (`AUTH_BEARER_STATIC.NO_TOKEN`, +`AUTH_BEARER_STATIC.UNKNOWN_TOKEN`, `AUTH_BEARER_STATIC.MTLS_REQUIRED`, +`AUTH_BEARER_STATIC.INVALID_OPTIONS`) along with a `BearerStaticAuthError` +subclass that lifts each code into a real `Error` instance. + +This module is the contract a caller branches on. Catching a generic +`SuaveplanError` and reading `.code` is the supported failure-handling +pattern; the concrete subclass exists to make `instanceof` narrow the code +union for downstream code that needs the stronger typing. + +## Features + +- Frozen four-entry code registry keyed by reason name. +- `BearerStaticAuthError` extends `SuaveplanError` + — `instanceof` narrows `.code`. +- Stable namespace string (`AUTH_BEARER_STATIC`) safe to log and persist. +- Every code exercised by at least one production code path (registry-vs- + source conformance is asserted by the spec-conformance test). + +## Usage: Basic + +```ts +import { + AUTH_BEARER_STATIC_CODES, + BearerStaticAuthError, +} from "@suaveplan/api-auth-bearer-static/error-codes"; + +try { + // factory call that may throw on bad options + throw new BearerStaticAuthError( + AUTH_BEARER_STATIC_CODES.INVALID_OPTIONS, + "tokens table is empty" + ); +} catch (e) { + if (e instanceof BearerStaticAuthError) { + // e.code narrows to BearerStaticAuthErrorCode + console.error(e.code, e.message); + } +} +``` + +## Usage: Advanced + +```ts +import { + AUTH_BEARER_STATIC_CODES, + BearerStaticAuthError, +} from "@suaveplan/api-auth-bearer-static/error-codes"; + +function isInvalidOptions(err: unknown): err is BearerStaticAuthError { + return ( + err instanceof BearerStaticAuthError && + err.code === AUTH_BEARER_STATIC_CODES.INVALID_OPTIONS + ); +} + +// Treat invalid options as a fatal config error; bubble everything else. +try { + // build resolver +} catch (e) { + if (isInvalidOptions(e)) { + process.exit(78); // EX_CONFIG + } + throw e; +} +``` + +## API Reference + +- `AUTH_BEARER_STATIC_CODES` — `Readonly">>`. Frozen at module load. +- `BearerStaticAuthErrorCode` — string-literal union of every value. +- `class BearerStaticAuthError extends SuaveplanError` + — constructor `(code, messageKey, options?)` matches the + `SuaveplanError` shape. + +## Implementation Notes + +The registry is constructed with `defineCodes("AUTH_BEARER_STATIC", [...])`. +`defineCodes` returns a `Readonly` record whose key set is the reason names +and whose values are the fully-qualified `"AUTH_BEARER_STATIC."` +strings — referenced via `AUTH_BEARER_STATIC_CODES.NO_TOKEN` rather than the +raw string literal so a typo at the call site fails type-check. diff --git a/docs/api-stack/api/api-auth-bearer-static/src/factory/create-bearer-static-resolver.md b/docs/api-stack/api/api-auth-bearer-static/src/factory/create-bearer-static-resolver.md new file mode 100644 index 0000000..5ea2098 --- /dev/null +++ b/docs/api-stack/api/api-auth-bearer-static/src/factory/create-bearer-static-resolver.md @@ -0,0 +1,106 @@ +# Direct factory — `@suaveplan/api-auth-bearer-static` + + +_(no submodules)_ + + +## Purpose + +`createBearerStaticResolver` is the direct-surface entry point of the +package. It accepts validated `BearerStaticResolverOptions`, builds a +`SessionResolver` over the fixed token table, and returns a resolver +implementation suitable for placing inside a `SessionResolverChain` from +`@suaveplan/api-auth`. The resolver matches the documented chain +semantics: an unknown token, missing header, or tripped mTLS gate all +return `null` so the chain advances to the next entry. + +The resolver is stateless beyond the disposed flag — there is no DB +connection, no JWKS cache, no refresh loop. Disposal flips the flag and +subsequent calls return `null` rather than throwing. + +## Features + +- Stateless per-request resolution; safe under concurrent fanout. +- Constant-time token match via `findTokenIndex`. +- Optional per-entry mTLS gate via `checkMtlsGate`. +- Configurable `headerName` and prefix (`Bearer` by default). +- Case-insensitive scheme match per RFC 7235. +- OTel counter emission for every of the four outcomes. + +## Usage: Basic + +```ts +import { createBearerStaticResolver } from "@suaveplan/api-auth-bearer-static"; + +const resolver = createBearerStaticResolver({ + tokens: [ + { + token: "service-cron-2026", + principal: { + id: "svc_cron", + scopes: ["jobs:run"], + claims: { kind: "service" }, + }, + }, + ], +}); + +const req = new Request("https://api/x", { + headers: { Authorization: "Bearer service-cron-2026" }, +}); +const principal = await resolver.resolve(req); +// principal.id === "svc_cron" +``` + +## Usage: Advanced + +```ts +import { createBearerStaticResolver } from "@suaveplan/api-auth-bearer-static"; +import { SessionResolverChain } from "@suaveplan/api-auth"; +import { createJwtResolver } from "@suaveplan/api-auth-jwt"; // hypothetical sibling + +// Chained — service tokens checked first, JWT users fall through after. +const chain = new SessionResolverChain([ + createBearerStaticResolver({ + tokens: [ + { + token: "admin-2026", + principal: { + id: "svc_admin", + scopes: ["admin:*"], + claims: {}, + }, + mtlsRequired: true, + }, + ], + headerName: "X-Service-Auth", + prefix: "Token", + }), + createJwtResolver({ issuer: "https://idp/..." }), +]); + +const result = await chain.resolve(request); +``` + +## API Reference + +- `createBearerStaticResolver(options: BearerStaticResolverOptions): SessionResolver` + +Returned resolver: + +- `resolve(request: Request): Promise` +- `dispose(): Promise` — idempotent. + +## Implementation Notes + +`extractToken` accepts the header value, trims, splits on the first space, +and lower-cases the scheme for the prefix comparison. Empty credentials +after the prefix are rejected. The implementation reads the configured +header by exact name (the Web `Headers` API normalises case on lookup, so +`Authorization` and `authorization` both work). When the table contains +the same token twice with conflicting principals, `findTokenIndex` returns +the first index — operator misconfiguration the schema cannot prevent. +TypeScript cannot narrow `table[idx]` to non-undefined even though +`findTokenIndex` only ever returns `-1` or a valid in-range index; a type +assertion encodes that contract at the call site without adding a runtime +guard the test would have to exercise. diff --git a/docs/api-stack/api/api-auth-bearer-static/src/mtls/mtls-gate.md b/docs/api-stack/api/api-auth-bearer-static/src/mtls/mtls-gate.md new file mode 100644 index 0000000..f57e4dd --- /dev/null +++ b/docs/api-stack/api/api-auth-bearer-static/src/mtls/mtls-gate.md @@ -0,0 +1,79 @@ +# mTLS gate — `@suaveplan/api-auth-bearer-static` + + +_(no submodules)_ + + +## Purpose + +The mTLS gate enforces an optional second factor on individual token table +entries. When operators mark an entry with `mtlsRequired: true`, the +resolver MUST refuse to surface the entry's Principal unless the host +listener attached a verified peer certificate to the inbound request via +`request.tls.peerCertificate`. This guards the highest-privilege service +tokens (e.g. internal admin API) against credential leakage — the bearer +token alone is necessary but no longer sufficient. + +The adapter does NOT establish TLS itself. The host listener (Bun's +TLS-enabled server, Node's `https`, a Cloudflare-Worker TLS terminator +ahead of the worker, etc.) is responsible for completing the TLS handshake +and surfacing the verified subject as `request.tls.peerCertificate`. This +module just inspects what was attached. + +## Features + +- Pure function — no I/O, no state. +- Defensive — accepts any `Request`-shaped input even when the `tls` field + was not attached (returns `undefined`). +- Treats `peerCertificate: null` identically to absent. +- `mtlsRequired === false` short-circuits without inspecting the request. + +## Usage: Basic + +```ts +import { checkMtlsGate } from "@suaveplan/api-auth-bearer-static/mtls"; + +const request = new Request("https://example/test"); +const allowed = checkMtlsGate(request, true); +// allowed === false — no peerCertificate attached +``` + +## Usage: Advanced + +```ts +import { + checkMtlsGate, + extractPeerCertificate, +} from "@suaveplan/api-auth-bearer-static/mtls"; + +// Host listener pattern — wrap the inbound request before handing off to +// the auth chain. +const withTls = Object.assign(request, { + tls: { peerCertificate: parsedX509Subject }, +}); + +const cert = extractPeerCertificate(withTls); +// cert === parsedX509Subject + +const allowed = checkMtlsGate(withTls, true); +// allowed === true +``` + +## API Reference + +- `interface RequestTlsInfo { peerCertificate?: unknown }` +- `extractPeerCertificate(request: Request): unknown | undefined` +- `checkMtlsGate(request: Request, mtlsRequired: boolean): boolean` + +## Implementation Notes + +The `Request` Web type has no standardised `tls` field. Both Node's +undici-based `Request` and Bun's polyfill ignore unknown properties on +construction, so the host pattern is to attach `tls` as a plain property +after the Request is built (or to wrap it in a Proxy / subclass). The +extractor reads through that property with a single defensive type cast +and returns `undefined` for any shape that does not satisfy the +`{ peerCertificate: }` invariant. The opaque certificate itself +is not parsed here — that is the host's job, and a future +`api-auth-mtls` adapter (out of scope for Stage 4) will own subject +extraction. diff --git a/docs/api-stack/api/api-auth-bearer-static/src/options/bearer-static-resolver-options.md b/docs/api-stack/api/api-auth-bearer-static/src/options/bearer-static-resolver-options.md new file mode 100644 index 0000000..d2e22b7 --- /dev/null +++ b/docs/api-stack/api/api-auth-bearer-static/src/options/bearer-static-resolver-options.md @@ -0,0 +1,96 @@ +# Options — `@suaveplan/api-auth-bearer-static` + + +_(no submodules)_ + + +## Purpose + +The options module owns the public construction surface of every resolver +in this package. It defines the `BearerStaticResolverOptions` interface +(plus its row type `BearerStaticTokenEntry`), the Zod schema that mirrors +the interface, and a thin parser that turns operator-supplied input into a +validated value or throws `AUTH_BEARER_STATIC.INVALID_OPTIONS`. + +Validation runs once at factory construction. Hot-path resolve calls never +re-validate — by then the table is structurally trusted. Token rotation is +intentionally out of scope: operators rotate by reloading host config, +which re-runs the factory and re-runs validation. + +## Features + +- `tokens` is required and non-empty (`.min(1)`). +- Every entry validates token (non-empty string), `principal` shape (id + + scopes + claims, optional tenantId), and optional `mtlsRequired` flag. +- `headerName` and `prefix` are optional with documented defaults + (`Authorization` / `Bearer`). +- Failure surfaces a typed `BearerStaticAuthError` carrying the original + `ZodError` as `cause` — full diagnostic trail is preserved. + +## Usage: Basic + +```ts +import { parseBearerStaticResolverOptions } from "@suaveplan/api-auth-bearer-static/options"; + +const opts = parseBearerStaticResolverOptions({ + tokens: [ + { + token: "service-cron-2026", + principal: { + id: "svc_cron", + scopes: ["jobs:run"], + claims: { kind: "service" }, + }, + }, + ], +}); +``` + +## Usage: Advanced + +```ts +import { + parseBearerStaticResolverOptions, + bearerStaticResolverOptionsSchema, +} from "@suaveplan/api-auth-bearer-static/options"; +import { AUTH_BEARER_STATIC_CODES } from "@suaveplan/api-auth-bearer-static/error-codes"; + +// Validate without constructing — useful for config UIs that show errors +// inline before committing changes. +const result = bearerStaticResolverOptionsSchema.safeParse(userInput); +if (!result.success) { + renderInlineErrors(result.error); +} + +// Or rely on the throwing parser when integrated into a startup pipeline: +try { + const opts = parseBearerStaticResolverOptions(userInput); + return opts; +} catch (e) { + if ( + e && + typeof e === "object" && + "code" in e && + e.code === AUTH_BEARER_STATIC_CODES.INVALID_OPTIONS + ) { + crashWithConfigExitCode(); + } + throw e; +} +``` + +## API Reference + +- `interface BearerStaticTokenEntry { token: string; principal: Principal; mtlsRequired?: boolean }` +- `interface BearerStaticResolverOptions { tokens: ReadonlyArray; headerName?: string; prefix?: string }` +- `bearerStaticResolverOptionsSchema: z.ZodType` +- `parseBearerStaticResolverOptions(raw: unknown): BearerStaticResolverOptions` + +## Implementation Notes + +The schema's `principal` block deliberately accepts strings rather than +`PrincipalId` / `Scope` brands. Brands are erased at runtime and the host +trusts operator-supplied config to be well-formed; rejecting strings that +look fine at runtime would be developer-hostile noise. Downstream code +treats the returned shape as a `Principal` because the structural fields +match. diff --git a/docs/api-stack/api/api-auth-bearer-static/src/proxy/create-bearer-static-resolver-worker-proxy.md b/docs/api-stack/api/api-auth-bearer-static/src/proxy/create-bearer-static-resolver-worker-proxy.md new file mode 100644 index 0000000..5f995bc --- /dev/null +++ b/docs/api-stack/api/api-auth-bearer-static/src/proxy/create-bearer-static-resolver-worker-proxy.md @@ -0,0 +1,110 @@ +# Worker-proxy factory — `@suaveplan/api-auth-bearer-static` + + +_(no submodules)_ + + +## Purpose + +The worker-proxy surface is the second of the two Stage-4 surfaces this +adapter ships (`§5.2a`). It lets the host install the bearer-static +resolver in the main process while the actual token table lives inside an +isolated worker. The host's `SessionResolverChain` calls +`resolve(request)` exactly as for the direct surface; under the hood, the +proxy marshals the request across a `MessagePort` using +`@suaveplan/api-worker-rpc`, the worker's resolver runs, and the +`Principal | null` decision is returned to the host. + +The proxy intentionally keeps the token table out of the host's address +space — useful when the host is sandboxed and the worker holds privileged +credentials, or when operators want a single auth daemon serving multiple +host workers. + +## Features + +- Bidirectional RPC over a `MessagePort` (or any `PortLike`) — no + process / address-space assumptions. +- Idempotent `dispose()` — coalesces multiple calls and closes the + underlying RPC client exactly once. +- Header set, request method, URL, and (optional) `peerCertificate` cross + the boundary; opaque body and abort signal are out of scope (resolution + does not need them). +- Server-side mount via `serveBearerStaticResolverOnPort` — owns the real + resolver and the token table. +- Passes the same `runAuthSessionConformance` harness as the direct + surface. + +## Usage: Basic + +```ts +import { + createBearerStaticResolverWorkerProxy, + serveBearerStaticResolverOnPort, +} from "@suaveplan/api-auth-bearer-static/proxy"; +import { createInProcessPortPair } from "@suaveplan/api-worker-rpc"; + +const { clientPort, serverPort } = createInProcessPortPair(); + +// Worker side — owns the real table. +const server = serveBearerStaticResolverOnPort(serverPort, { + tokens: [ + { + token: "T1", + principal: { id: "svc", scopes: [], claims: {} }, + }, + ], +}); + +// Host side — sees only a proxy. +const proxy = createBearerStaticResolverWorkerProxy(clientPort); + +const request = new Request("https://api/x", { + headers: { Authorization: "Bearer T1" }, +}); +const principal = await proxy.resolve(request); + +await proxy.dispose(); +server.close("done"); +``` + +## Usage: Advanced + +```ts +import { Worker, MessageChannel } from "node:worker_threads"; +import { + createBearerStaticResolverWorkerProxy, +} from "@suaveplan/api-auth-bearer-static/proxy"; + +// Real Node worker boundary. The worker script imports +// `serveBearerStaticResolverOnPort` and calls it against its own port. +const { port1, port2 } = new MessageChannel(); +const worker = new Worker("./auth-worker.mjs", { transferList: [port2] }); + +const resolver = createBearerStaticResolverWorkerProxy(port1 as never); + +// Place in chain alongside direct adapters — host treats both uniformly. +import { SessionResolverChain } from "@suaveplan/api-auth"; +const chain = new SessionResolverChain([resolver]); +``` + +## API Reference + +- `serveBearerStaticResolverOnPort(port: PortLike, options: BearerStaticResolverOptions): { close(reason?: string): void }` + — mount the server-side handlers. +- `createBearerStaticResolverWorkerProxy(port: PortLike): SessionResolver` + — host-side proxy. + +## Implementation Notes + +The marshalled envelope is `{url, method, headers, peerCertificate?}` — +the minimal subset of `Request` that the bearer-static decision actually +needs. `peerCertificate` is structured-clone-friendly because the host +attaches whatever shape the listener surfaced; tests pass plain objects. +The proxy never sends the request body, because token resolution does not +consult it. Errors thrown by the server-side resolver (e.g. an unexpected +runtime fault) propagate as the standard `WORKER_RPC` error envelope and +surface in the host as a thrown `WorkerRpcError` — the host's resolver +chain treats this as a fail-closed `RESOLVER_THREW` per the documented +`api-auth` chain semantics. `dispose()` calls the remote `dispose` first +to drain the server-side state, then closes the local client so the +underlying port can be garbage-collected. diff --git a/docs/api-stack/api/api-auth-bearer-static/src/security-scheme/security-scheme-contribution.md b/docs/api-stack/api/api-auth-bearer-static/src/security-scheme/security-scheme-contribution.md new file mode 100644 index 0000000..2af3c67 --- /dev/null +++ b/docs/api-stack/api/api-auth-bearer-static/src/security-scheme/security-scheme-contribution.md @@ -0,0 +1,71 @@ +# Security scheme contribution — `@suaveplan/api-auth-bearer-static` + + +_(no submodules)_ + + +## Purpose + +This module builds the OpenAPI 3.1 `components.securitySchemes` +contribution the adapter publishes to the host's `AuthAdapter` registry. +The generated entry declares an `http` / `bearer` scheme so OpenAPI tooling +(Stoplight, ReadMe, Postman import, etc.) and the host's emitter render +the canonical "Authorize" affordance. + +The contribution is content-only: it does NOT register routes, mount +middleware, or affect runtime behaviour. It exists solely so the OpenAPI +document the host emits is correct and discoverable. + +## Features + +- OAS 3.1 compliant — emits the `http` discriminator with `scheme: bearer`. +- `name` defaults to `bearerStaticAuth` and is overridable at construction. +- Optional `bearerFormat` and `description` fields pass through verbatim. +- Validated against the `OpenApiSecuritySchemeSchema` Zod schema published + by `@suaveplan/api-auth/security-scheme` — if this module ever drifts, + the conformance tests in `api-auth` fail. + +## Usage: Basic + +```ts +import { securitySchemeContribution } from "@suaveplan/api-auth-bearer-static/security-scheme"; + +const contrib = securitySchemeContribution(); +// { name: "bearerStaticAuth", +// scheme: { type: "http", scheme: "bearer" } } +``` + +## Usage: Advanced + +```ts +import { securitySchemeContribution } from "@suaveplan/api-auth-bearer-static/security-scheme"; +import { validateSecurityScheme } from "@suaveplan/api-auth"; + +// Custom name + bearerFormat for an admin-only deployment that publishes +// two static-token adapters (cron + admin) side by side under distinct +// scheme keys. +const adminScheme = securitySchemeContribution({ + name: "bearerStaticAdminAuth", + description: "Static admin token. mTLS-gated. Rotate via host config reload.", + bearerFormat: "opaque", +}); + +// Defensive — confirm the contribution still passes the api-auth schema. +validateSecurityScheme(adminScheme); +``` + +## API Reference + +- `interface SecuritySchemeContributionOptions { name?: string; description?: string; bearerFormat?: string }` +- `securitySchemeContribution(options?: SecuritySchemeContributionOptions): SecuritySchemeContribution` + — pure factory; the result is structurally a + `SecuritySchemeContribution` from `@suaveplan/api-auth`. + +## Implementation Notes + +`bearerFormat` is purely informational per OAS — values like `JWT`, +`opaque`, or vendor-specific strings appear in some doc tooling but never +affect runtime validation. The contribution intentionally omits the +optional fields when undefined rather than emitting `undefined` values, +which would round-trip through `JSON.stringify` as missing keys but +trigger noisy diffs in machine-comparison tooling. diff --git a/docs/api-stack/api/api-auth-bearer-static/src/telemetry/instruments.md b/docs/api-stack/api/api-auth-bearer-static/src/telemetry/instruments.md new file mode 100644 index 0000000..5b59c05 --- /dev/null +++ b/docs/api-stack/api/api-auth-bearer-static/src/telemetry/instruments.md @@ -0,0 +1,76 @@ +# OTel instruments — `@suaveplan/api-auth-bearer-static` + + +_(no submodules)_ + + +## Purpose + +The telemetry module owns the single OpenTelemetry counter this package +emits — `api.auth.bearer_static_match_total` — partitioned by the +documented `outcome` attribute. Every call to a resolver's `resolve()` +method increments this counter exactly once with one of four label values. + +The instrument is bound lazily against `metrics.getMeter(...)` so the +package is safe to import on the cold path before the host installs a +`MeterProvider`. Resetting the cached bundle (via +`resetBearerStaticInstruments`) is required in test setup to bind against +a freshly-installed in-memory exporter. + +## Features + +- Single counter — `api.auth.bearer_static_match_total`. +- Four `outcome` label values: `match`, `no-token`, `unknown-token`, + `mtls-required`. +- Lazy meter resolution — module load does not trigger an OTel side + effect. +- Idempotent reset hook for test isolation. + +## Usage: Basic + +```ts +import { recordMatchOutcome } from "@suaveplan/api-auth-bearer-static/src/telemetry"; + +// Inside a resolver's resolve() body: +recordMatchOutcome("unknown-token"); +``` + +## Usage: Advanced + +```ts +import { + getBearerStaticInstruments, + resetBearerStaticInstruments, +} from "@suaveplan/api-auth-bearer-static/src/telemetry"; + +// In a vitest setup file that has installed an in-memory MeterProvider +// upstream: +beforeEach(() => { + resetBearerStaticInstruments(); +}); + +it("emits the outcome attribute we expect", async () => { + const inst = getBearerStaticInstruments(); + inst.matchTotal.add(1, { outcome: "match" }); + // ...then flush + assert on the exporter +}); +``` + +## API Reference + +- `interface BearerStaticInstruments { matchTotal: Counter }` +- `type BearerStaticMatchOutcome = "match" | "no-token" | "unknown-token" | "mtls-required"` +- `getBearerStaticInstruments(): BearerStaticInstruments` +- `resetBearerStaticInstruments(): void` +- `recordMatchOutcome(outcome: BearerStaticMatchOutcome): void` + +## Implementation Notes + +The instrument name uses dotted notation per OpenTelemetry semantic +conventions; the attribute key is `outcome` rather than the host-wide +`auth.outcome` since this counter is adapter-scoped and dashboards aggregate +across adapters by metric name, not attribute. The `description` field is +human-readable only — OTel collectors do not interpret it. The cached bundle +exists per process and is intentionally global; resolvers do not own +instruments because every concrete resolver in a chain would otherwise +double-publish the same counter under the same scope. diff --git a/docs/api-stack/api/api-auth-better-auth/README.md b/docs/api-stack/api/api-auth-better-auth/README.md new file mode 100644 index 0000000..7ec7c52 --- /dev/null +++ b/docs/api-stack/api/api-auth-better-auth/README.md @@ -0,0 +1,172 @@ +# @suaveplan/api-auth-better-auth — Better-Auth adapter for the @suaveplan/api foundation. Ships two independently-wireable factories implementing the auth.session and auth.provider capability contracts against a Better-Auth instance backed by its own Postgres connection. Maps Better-Auth user+session onto the @suaveplan/api Principal contract, mounts canonical PROVIDER_ROUTE_SURFACE routes (translating Better-Auth's /sign-up etc. idiom), exposes a GitHub OAuth flow via Better-Auth's genericOAuth plugin (so the mock OAuth IdP can be wired end-to-end), guards route-prefix collisions against @suaveplan/api-host's reserved-prefix contract, and emits OTel sessions/oauth/mapping instruments. The ./testing subpath re-exports both conformance suites bound to Postgres-backed factories. + +Stage-6 Better-Auth adapter for `@suaveplan/api`. Ships two +**independently-wireable** capability surfaces — `createBetterAuthSession` +(implements `auth.session` from `@suaveplan/api-auth`) and +`createBetterAuthProvider` (implements `auth.provider` from +`@suaveplan/api-auth-provider`). Operators MAY wire either side in +isolation OR both together; sharing one options bag between the two +factories shares the underlying Better-Auth instance + DB pool. + +> **Two capability surfaces, wire independently.** The session adapter +> reads cookies + bearer tokens; the provider adapter mounts the canonical +> `PROVIDER_ROUTE_SURFACE` (9 routes) under a configurable prefix. They +> share no required code path — wiring only one side does NOT install the +> other side's surface. + + +## Documentation tree + +- [db](./src/db/database.md) — Lazy holder for the underlying Better-Auth instance plus a helper that projects {@link BetterAuthOptions} onto the loos… + - [database](./src/db/database.md) — Lazy holder for the underlying Better-Auth instance plus a helper that projects {@link BetterAuthOptions} onto the loos… +- [error-codes](./src/error-codes/error-codes.md) — Stable, tracked error-code registry for `@suaveplan/api-auth-better-auth`. Every fault path inside the adapter… + - [error-codes](./src/error-codes/error-codes.md) — Stable, tracked error-code registry for `@suaveplan/api-auth-better-auth`. Every fault path inside the adapter… +- [independence](./src/independence/session-without-provider.md) — Pin the design invariant from the Stage-6 spec change: the Better-Auth adapter ships two factories — `createBetterA… + - [session-without-provider](./src/independence/session-without-provider.md) — Pin the design invariant from the Stage-6 spec change: the Better-Auth adapter ships two factories — `createBetterA… +- [instruments](./src/instruments/instruments.md) — Lazily-bound OpenTelemetry instrument bundle for the Better-Auth adapter. Built once per process against the current gl… + - [instruments](./src/instruments/instruments.md) — Lazily-bound OpenTelemetry instrument bundle for the Better-Auth adapter. Built once per process against the current gl… +- [default-factory](./src/oauth/default-factory.md) — Default `betterAuthFactory` used when an operator does not supply one via `BetterAuthOptions.betterAuthFactory`. Dynami… +- [github](./src/oauth/github.md) — Project Suaveplan's {@link BetterAuthOauthProvider} entries onto the `genericOAuth` plugin config Better-Auth consumes.… +- [options](./src/options/options.md) — Zod-validated boundary for the Better-Auth adapter's configuration bag. Both `createBetterAuthSession` and `createBette… + - [options](./src/options/options.md) — Zod-validated boundary for the Better-Auth adapter's configuration bag. Both `createBetterAuthSession` and `createBette… +- [principal](./src/principal/map-user-to-principal.md) — Default Better-Auth `(user, session)` → `Principal` mapping consumed by both `createBetterAuthSession` and `createBette… + - [map-user-to-principal](./src/principal/map-user-to-principal.md) — Default Better-Auth `(user, session)` → `Principal` mapping consumed by both `createBetterAuthSession` and `createBette… +- [create-provider](./src/provider/create-provider.md) — Factory for the `auth.provider` half of the Stage-6 split. Returns an `AuthProviderAdapter` (per `@suaveplan/api-auth-p… +- [route-translation](./src/provider/route-translation.md) — Translation table mapping every entry in `PROVIDER_ROUTE_SURFACE` (the canonical 9-route foundation surface) to the mat… +- [route-prefix](./src/route-prefix/route-prefix.md) — Resolve an operator-supplied `routePrefix` against the host's reserved-prefix contract from `@suaveplan/api-host/reserv… + - [route-prefix](./src/route-prefix/route-prefix.md) — Resolve an operator-supplied `routePrefix` against the host's reserved-prefix contract from `@suaveplan/api-host/reserv… +- [session](./src/session/create-session.md) — Factory for the `auth.session` half of the Stage-6 split. Returns a `SessionResolver` that asks Better-Auth's `auth.api… + - [create-session](./src/session/create-session.md) — Factory for the `auth.session` half of the Stage-6 split. Returns a `SessionResolver` that asks Better-Auth's `auth.api… +- [testing](./src/testing/testing.md) — `@suaveplan/api-auth-better-auth/testing` is the subpath downstream packages import when they want to assert their own… + - [testing](./src/testing/testing.md) — `@suaveplan/api-auth-better-auth/testing` is the subpath downstream packages import when they want to assert their own… + + +## Modules + +- **`error-codes/`** — 10-code `AUTH_BA.*` registry + `BetterAuthError`. +- **`options/`** — Zod-validated `BetterAuthOptions` boundary + canonical + defaults. +- **`db/`** — `LazyBetterAuth` (lazy + cached + concurrency-safe) + + `buildBetterAuthFactoryArgs` (outer-options → Better-Auth-args + projection). +- **`principal/`** — default Better-Auth `(user, session)` → `Principal` + mapping; replaceable via `BetterAuthOptions.principalMapping`. +- **`session/`** — `createBetterAuthSession(opts)` factory implementing + the `SessionResolver` contract. +- **`provider/`** — `createBetterAuthProvider(opts)` factory implementing + the `AuthProviderAdapter` contract; mounts canonical routes that rewrite + onto Better-Auth's native sub-paths. +- **`route-prefix/`** — `assertRoutePrefixAvailable` collision check + against `@suaveplan/api-host/reserved-prefix`. +- **`oauth/`** — `genericOAuth` plugin config builder + default + `betterAuth(...)` factory that dynamically loads the plugin when OAuth + providers are configured. The GitHub OAuth flow is the canonical + reference; the implementation works against the real GitHub IdP in + production and the mock IdP from + `@suaveplan/testing-integration-oauth-mock` in tests because we use + `genericOAuth` (which accepts the full URL triple) rather than the + hard-coded `github` social-provider. +- **`instruments/`** — OTel counters + histograms per the spec's metrics + contract. +- **`independence/`** — invariant pin: session-only / provider-only wiring + exposes nothing from the other side. +- **`testing/`** — `./testing` subpath re-exporting both conformance + harnesses bound to Better-Auth factories. + +## Usage + +```ts +import { Pool } from "pg"; +import { + createBetterAuthProvider, + createBetterAuthSession, +} from "@suaveplan/api-auth-better-auth"; + +const pool = new Pool({ connectionString: process.env.BETTER_AUTH_DB_URL! }); +const opts = { + database: pool, + baseUrl: "https://api.example.com", + secret: process.env.BETTER_AUTH_SECRET!, + routePrefix: "/auth", + oauth: { + providers: { + github: { + providerId: "github", + clientId: process.env.GITHUB_CLIENT_ID!, + clientSecret: process.env.GITHUB_CLIENT_SECRET!, + authorizationUrl: "https://github.com/login/oauth/authorize", + tokenUrl: "https://github.com/login/oauth/access_token", + userInfoUrl: "https://api.github.com/user", + }, + }, + }, +}; + +// Wire both sides — they share one Better-Auth instance via per-options WeakMap: +host.registerAuth({ + resolver: createBetterAuthSession(opts), + csrf: true, +}); +host.registerAuthProvider(createBetterAuthProvider(opts)); +``` + +## Error codes + +| Code | Surface | When thrown | +| --- | --- | --- | +| `AUTH_BA.INVALID_SESSION` | session | unexpected `getSession` failure | +| `AUTH_BA.DB_UNREACHABLE` | db | `betterAuth({...})` construction threw | +| `AUTH_BA.OAUTH_PROVIDER_REJECTED` | oauth | provider returned 403 | +| `AUTH_BA.OAUTH_STATE_MISMATCH` | oauth | state cookie did not match | +| `AUTH_BA.USER_NOT_FOUND` | mapping | custom mapper signalled missing user | +| `AUTH_BA.EMAIL_NOT_VERIFIED` | session | session present but email unverified | +| `AUTH_BA.RATE_LIMITED` | provider | Better-Auth rate-limiter blocked | +| `AUTH_BA.INVALID_REDIRECT` | oauth | redirect URI outside allow-list | +| `AUTH_BA.PRINCIPAL_MAPPING_FAILED` | mapping | mapper threw | +| `AUTH_BA.ROUTE_PREFIX_COLLISION` | mount | prefix collides with host-reserved | + +## Conformance + +Conformance tests live at: + +- `src/session/create-session.spec-conformance.test.ts` — drives + `runAuthSessionConformance` against a Postgres-shaped stubbed + `BetterAuthLike` (the contract asserts the abstract `SessionResolver` + invariants; DB backing is orthogonal). +- `src/provider/create-provider.spec-conformance.test.ts` — drives + `runAuthProviderConformance` against `createBetterAuthProvider` with the + same stubbing topology. +- `tests/integration/postgres-better-auth.test.ts` — real Postgres + container + real Better-Auth + register/login/resolve. Gracefully skips + with a logged reason when Docker / `pg` / schema bootstrap is unavailable + in the runner environment. + +## Architecture + +``` + host config + │ + ▼ + ┌─────────────────────────────┐ + │ BetterAuthOptions (Zod) │ parseBetterAuthOptions(...) + └──────────────┬──────────────┘ + │ + per-opts WeakMap + │ + ▼ + ┌──────────────┐ + │ LazyBetterAuth│ ── betterAuth({ ...args, plugins: [genericOAuth(...)] }) + └─────┬────────┘ + │ shared (single connection pool) + ┌───────┴────────┐ + ▼ ▼ +createBetterAuthSession createBetterAuthProvider + (SessionResolver) (AuthProviderAdapter) + │ │ + │ ├── mounts /register, /login, /logout, /refresh, + │ │ /oauth/:provider/start, /oauth/:provider/callback, + │ │ /verify-email/:token, /forgot-password, /reset-password + ▼ ▼ + Principal auth.handler(rewrittenRequest) +``` + diff --git a/docs/api-stack/api/api-auth-better-auth/src/db/database.md b/docs/api-stack/api/api-auth-better-auth/src/db/database.md new file mode 100644 index 0000000..89f92fd --- /dev/null +++ b/docs/api-stack/api/api-auth-better-auth/src/db/database.md @@ -0,0 +1,83 @@ +# `database` + + +_(no submodules)_ + + +## Purpose + +Lazy holder for the underlying Better-Auth instance plus a helper that +projects {@link BetterAuthOptions} onto the loosely-typed argument bag +`betterAuth(...)` accepts. The lazy pattern matters because Better-Auth's +constructor opens its own DB connection pool — we MUST NOT open it twice +when both the session and provider factories are wired against the same +options, and we MUST NOT do it eagerly at module import time because that +would make `import "@suaveplan/api-auth-better-auth"` block on a network +round-trip. + +## Features + +- `LazyBetterAuth.get()` builds the Better-Auth instance on first call, + caches it, and serves concurrent callers from the same in-flight promise. +- `LazyBetterAuth.reset()` drops the cache (tests only). +- Factory failures wrapped in `BetterAuthError(AUTH_BA.DB_UNREACHABLE)` with + the underlying error as `cause`. +- In-flight slot is cleared on failure so a transient outage doesn't + permanently poison the cache. +- `buildBetterAuthFactoryArgs(opts)` maps our outer options onto + Better-Auth's shape so the wrapper isn't sprinkled with shape translation. + +## Usage: Basic + +```ts +import { LazyBetterAuth } from "@suaveplan/api-auth-better-auth"; +import { betterAuth } from "better-auth"; + +const lazy = new LazyBetterAuth(opts, (args) => betterAuth(args)); +const auth = await lazy.get(); +const response = await auth.handler(request); +``` + +## Usage: Advanced + +```ts +import { LazyBetterAuth, buildBetterAuthFactoryArgs } from "@suaveplan/api-auth-better-auth"; +import { betterAuth } from "better-auth"; + +// Tests can swap in a stubbed factory that records the args + returns a +// stubbed BetterAuthLike. The wrapper's behaviour is exercised without +// standing up a real database. +const captured: Record[] = []; +const lazy = new LazyBetterAuth(opts, (args) => { + captured.push(args); + return { handler: async () => new Response("ok"), api: { getSession: async () => null } }; +}); + +// Inspect the args the wrapper would have sent to `betterAuth(...)`: +expect(buildBetterAuthFactoryArgs(opts)).toMatchObject({ + database: opts.database, + baseURL: opts.baseUrl, +}); +``` + +## API Reference + +| Export | Shape | Purpose | +| ------ | ----- | ------- | +| `LazyBetterAuth` | class | One instance per options bag; lazy + cached | +| `buildBetterAuthFactoryArgs(opts)` | `(BetterAuthOptions) => Record` | Outer-options → Better-Auth-args projection | + +## Implementation Notes + +The `inflight` slot is the linchpin of the concurrency guarantee — the +first caller to enter `get()` writes a single promise; every subsequent +caller observes that same promise via the second `if`. On rejection the +`finally` clears `inflight` so the next call can retry; on resolution +`this.cached` is set, and the `inflight` clear is harmless. The +session-vs-advanced split in `buildBetterAuthFactoryArgs` mirrors +Better-Auth 1.4's option topology — `session.cookieName` is configured under +`session`, but `sameSite` / `secure` live under +`advanced.defaultCookieAttributes`. Operators wanting the full Better-Auth +option surface (passkeys, magic links, organisation plugin) supply their own +`betterAuthFactory` and call `betterAuth({ ...buildBetterAuthFactoryArgs(opts), plugins: [...] })` +themselves. diff --git a/docs/api-stack/api/api-auth-better-auth/src/error-codes/error-codes.md b/docs/api-stack/api/api-auth-better-auth/src/error-codes/error-codes.md new file mode 100644 index 0000000..56f337e --- /dev/null +++ b/docs/api-stack/api/api-auth-better-auth/src/error-codes/error-codes.md @@ -0,0 +1,88 @@ +# `error-codes` + + +_(no submodules)_ + + +## Purpose + +Stable, OpenSpec-tracked error-code registry for `@suaveplan/api-auth-better-auth`. +Every fault path inside the adapter — session resolution, database access, +OAuth handshake, principal mapping, route-prefix collision detection — terminates +in a {@link BetterAuthError} carrying one of the ten codes defined here. Codes +are namespaced under `AUTH_BA.*` via the package's `defineCodes` helper so the +full literal value never collides with sibling adapters and consumers can branch +on a single discriminated value. + +## Features + +- 10 namespaced codes covering session, database, OAuth, mapping and mount-time + failure surfaces. +- `BetterAuthErrorCode` literal-union derived from the code bag — narrows + exhaustively in `switch`. +- `BetterAuthError` class extending `SuaveplanError` so `instanceof` and + structural matching (`err.betterAuthCode`) both work. + +## Usage: Basic + +```ts +import { + AUTH_BA_CODES, + BetterAuthError, +} from "@suaveplan/api-auth-better-auth/error-codes"; + +if (!session) { + throw new BetterAuthError( + AUTH_BA_CODES.INVALID_SESSION, + "session resolver returned no principal" + ); +} +``` + +## Usage: Advanced + +```ts +import { + AUTH_BA_CODES, + BetterAuthError, + type BetterAuthErrorCode, +} from "@suaveplan/api-auth-better-auth/error-codes"; + +function describe(code: BetterAuthErrorCode): string { + switch (code) { + case AUTH_BA_CODES.OAUTH_STATE_MISMATCH: + return "Tampered or stale state parameter — restart the flow"; + case AUTH_BA_CODES.OAUTH_PROVIDER_REJECTED: + return "The upstream IdP rejected our token request"; + default: + return "Unhandled Better-Auth adapter failure"; + } +} + +try { + await router.handle(request); +} catch (err) { + if (err instanceof BetterAuthError) { + logger.warn(describe(err.betterAuthCode), { code: err.code, cause: err.cause }); + } + throw err; +} +``` + +## API Reference + +| Export | Shape | Purpose | +| ------ | ----- | ------- | +| `AUTH_BA_CODES` | `Readonly>` | Frozen bag of every documented code | +| `BetterAuthErrorCode` | string-literal union | The exact set of values `code` may take | +| `BetterAuthError` | class extending `SuaveplanError` | Throwable carrying a `BetterAuthErrorCode` | + +## Implementation Notes + +`defineCodes("AUTH_BA", [...])` from `@suaveplan/error` is the only way to mint +codes — it freezes the bag and produces the string-literal type. Adding a new +code requires (1) an OpenSpec change against the `api-auth-better-auth` +capability so the spec delta lists the new code, (2) editing the tuple here, +and (3) editing every consumer `switch` block. The redundant +`betterAuthCode` field mirrors `code` so transport boundaries that drop the +prototype chain (worker, IPC) can still match structurally. diff --git a/docs/api-stack/api/api-auth-better-auth/src/independence/session-without-provider.md b/docs/api-stack/api/api-auth-better-auth/src/independence/session-without-provider.md new file mode 100644 index 0000000..f1db813 --- /dev/null +++ b/docs/api-stack/api/api-auth-better-auth/src/independence/session-without-provider.md @@ -0,0 +1,77 @@ +# `session-without-provider` + + +_(no submodules)_ + + +## Purpose + +Pin the design invariant from The spec change: the Better-Auth +adapter ships two factories — `createBetterAuthSession` and +`createBetterAuthProvider` — and operators MUST be able to wire either side +without dragging in the other. Wiring only the session adapter (keeping +account-lifecycle elsewhere — e.g. Clerk or a custom rolled provider) is the +"hosted IdP for accounts, Better-Auth for session reads against a shared +cookie" topology the design doc §2.3 calls out. Wiring only the provider +adapter (no Better-Auth session resolution) is rarer but legal — the host +fills the `auth.session` slot with whatever other resolver is configured. + +## Features + +- Sibling test file pins the invariant by: + - Asserting `createBetterAuthSession(opts)` returns a `SessionResolver` + with no `routes` / `pathPrefix` field. + - Asserting `createBetterAuthProvider(opts)` returns an + `AuthProviderAdapter` with no `resolve` / `dispose` field. + - Walking the recorded route list when `routes(...)` IS invoked to verify + every canonical name lands. +- `betterAuthFactories` constant re-exports both factories as a single bag + so consumer documentation can name the pair without repeating imports. + +## Usage: Basic + +```ts +import { betterAuthFactories } from "@suaveplan/api-auth-better-auth"; + +const resolver = betterAuthFactories.session(opts); +const provider = betterAuthFactories.provider(opts); +``` + +## Usage: Advanced + +```ts +import { createBetterAuthSession } from "@suaveplan/api-auth-better-auth"; +import { ClerkSessionResolver } from "third-party/clerk-suaveplan-adapter"; + +// Topology: Clerk owns sign-up / sign-in routes; Better-Auth reads the +// shared session cookie via createBetterAuthSession against a shadow +// Better-Auth DB that mirrors the Clerk user store. Provider side NOT wired. +host.registerAuth({ + resolver: new SessionResolverChain({ + resolvers: [ + createBetterAuthSession({ database: pool, baseUrl, secret }), + new ClerkSessionResolver({ clerkApiKey: process.env.CLERK_KEY! }), + ], + }), +}); +``` + +## API Reference + +| Export | Shape | Purpose | +| ------ | ----- | ------- | +| `betterAuthFactories` | `Readonly<{ session, provider }>` | Convenience bag pairing both factories | + +## Implementation Notes + +The module is intentionally near-empty — the invariant lives in the test +file. The thin re-export bag is the only runtime contribution because the +OpenSpec scaffolding rule requires every implementation file to have a +sibling `.md` AND a paired test file. The independence is enforced +structurally by TypeScript anyway — `SessionResolver` and +`AuthProviderAdapter` have disjoint shapes — but the test pin guards against +a refactor that accidentally adds an `if-not-mounted-mount-the-other-side` +side effect inside either factory. The OpenSpec spec delta lists this file +as the verification for the "session-only / provider-only wiring exposes +nothing from the other side" scenario, so the test names match the spec +exactly. diff --git a/docs/api-stack/api/api-auth-better-auth/src/instruments/instruments.md b/docs/api-stack/api/api-auth-better-auth/src/instruments/instruments.md new file mode 100644 index 0000000..2d4b497 --- /dev/null +++ b/docs/api-stack/api/api-auth-better-auth/src/instruments/instruments.md @@ -0,0 +1,83 @@ +# `instruments` + + +_(no submodules)_ + + +## Purpose + +Lazily-bound OpenTelemetry instrument bundle for the Better-Auth adapter. +Built once per process against the current global `MeterProvider` and cached. +Tests call {@link resetBetterAuthInstruments} after installing a fresh +`MeterProvider` so assertions only see the instruments emitted by the unit +under test. + +## Features + +- Four canonical instruments matching the spec's OTel surface contract: + `auth.better_auth.sessions_resolved_total`, + `auth.better_auth.session_resolve_duration_ms`, + `auth.better_auth.oauth_flows_total`, + `auth.better_auth.principal_mapping_errors_total`. +- Singleton-per-process pattern so consumers can call + `getBetterAuthInstruments()` from anywhere without worrying about meter + proliferation. +- Reset helper for test isolation. + +## Usage: Basic + +```ts +import { getBetterAuthInstruments } from "@suaveplan/api-auth-better-auth/instruments"; + +const ins = getBetterAuthInstruments(); +ins.sessionsResolvedTotal.add(1, { outcome: "resolved" }); +ins.sessionResolveDurationMs.record(elapsedMs, { outcome: "resolved" }); +``` + +## Usage: Advanced + +```ts +import { + getBetterAuthInstruments, + resetBetterAuthInstruments, +} from "@suaveplan/api-auth-better-auth/instruments"; +import { metrics } from "@opentelemetry/api"; +import { MeterProvider } from "@opentelemetry/sdk-metrics"; + +// In test setup +const provider = new MeterProvider({ /* reader, ... */ }); +metrics.setGlobalMeterProvider(provider); +resetBetterAuthInstruments(); // force the cache to rebind to the new provider + +// In test +const ins = getBetterAuthInstruments(); +ins.oauthFlowsTotal.add(1, { provider: "github", outcome: "state_mismatch" }); +``` + +## API Reference + +| Export | Shape | Purpose | +| ------ | ----- | ------- | +| `BetterAuthInstruments` | interface | Bundle of `Counter` / `Histogram` instances | +| `getBetterAuthInstruments()` | `() => BetterAuthInstruments` | Lazy cached accessor | +| `resetBetterAuthInstruments()` | `() => void` | Drop the cache (tests only) | + +Instrument labels: + +| Instrument | Labels | Semantics | +| --- | --- | --- | +| `auth.better_auth.sessions_resolved_total` | `outcome ∈ "resolved" \| "null" \| "error"` | Session-resolver call count | +| `auth.better_auth.session_resolve_duration_ms` | `outcome` (same) | Duration histogram | +| `auth.better_auth.oauth_flows_total` | `provider`, `outcome ∈ "success" \| "state_mismatch" \| "provider_rejected"` | OAuth flow conclusion count | +| `auth.better_auth.principal_mapping_errors_total` | none | Mapper-threw count | + +## Implementation Notes + +The meter is acquired via `metrics.getMeter("@suaveplan/api-auth-better-auth")` +to match the OpenTelemetry naming convention (instrument scope = package +name). Caching is critical — calling `meter.createCounter(name, ...)` more +than once for the same `name` produces a stable instrument under the OTel +spec, but the SDK MAY emit a warning, and re-binding the cached objects on +every `add()` call would generate measurable overhead. The reset helper +exists purely for tests because the global `MeterProvider` IS the cache key +that decides whether the cached instruments still point at the live provider. diff --git a/docs/api-stack/api/api-auth-better-auth/src/oauth/default-factory.md b/docs/api-stack/api/api-auth-better-auth/src/oauth/default-factory.md new file mode 100644 index 0000000..a6214d3 --- /dev/null +++ b/docs/api-stack/api/api-auth-better-auth/src/oauth/default-factory.md @@ -0,0 +1,78 @@ +# `default-factory` + +## Purpose + +Default `betterAuthFactory` used when an operator does not supply one via +`BetterAuthOptions.betterAuthFactory`. Dynamically imports `better-auth` +AND (when OAuth providers are configured) the `genericOAuth` plugin, then +calls `betterAuth({...})` with the assembled args. The dynamic imports +mean module-load of `@suaveplan/api-auth-better-auth` never blocks on +`better-auth` — operators that ship a stubbed factory (unit tests, custom +adapter shells) avoid the upstream package altogether. + +## Features + +- Dynamic `import("better-auth")` keeps cold-start fast for stub-only + consumers. +- Dynamic `import("better-auth/plugins/generic-oauth")` only fires when the + options actually configure OAuth providers. +- The Suaveplan-private `__suaveplan_generic_oauth` sentinel key from + `buildBetterAuthFactoryArgs` is stripped before forwarding so the upstream + package never sees our internal fields. +- Pre-existing `plugins` arrays the operator may pass through their own + factory are preserved (the genericOAuth plugin is appended, not assigned). + +## Usage: Basic + +```ts +// Production wiring — pass options without a betterAuthFactory and the +// default fires implicitly: +const provider = createBetterAuthProvider({ + database: pool, + baseUrl: "https://api.example.com", + secret: process.env.BETTER_AUTH_SECRET!, +}); +``` + +## Usage: Advanced + +```ts +import { defaultBetterAuthFactory } from "@suaveplan/api-auth-better-auth"; + +// Operator-supplied factory that wraps the default to inject the +// `organization` Better-Auth plugin on top of whatever the wrapper itself +// already configures: +const customFactory = async (args: Record) => { + const auth = await defaultBetterAuthFactory(args); + return auth; +}; + +const provider = createBetterAuthProvider({ + database: pool, + baseUrl, + secret, + betterAuthFactory: customFactory, +}); +``` + +## API Reference + +| Export | Shape | Purpose | +| ------ | ----- | ------- | +| `defaultBetterAuthFactory(args)` | `(Record) => Promise` | Dynamic loader + plugin assembler | + +## Implementation Notes + +The sentinel-key pattern (`__suaveplan_generic_oauth`) is the trade-off +between (a) keeping `buildBetterAuthFactoryArgs` synchronous and pure, and +(b) actually loading the upstream plugin module. The args bag is built +synchronously so callers and tests can inspect it; the plugin module is +loaded lazily inside this factory. Stripping the sentinel keeps the +boundary clean — Better-Auth's option validator complains about unknown +top-level keys. + +The `plugins` array preservation matters because operators MAY supply a +custom factory that adds Better-Auth's own plugins (organisation, passkeys, +2FA, magic-link) on top of the OAuth config the wrapper itself injects. By +appending we ensure a stub operator factory + the wrapper's genericOAuth +config coexist correctly. diff --git a/docs/api-stack/api/api-auth-better-auth/src/oauth/github.md b/docs/api-stack/api/api-auth-better-auth/src/oauth/github.md new file mode 100644 index 0000000..c13c66b --- /dev/null +++ b/docs/api-stack/api/api-auth-better-auth/src/oauth/github.md @@ -0,0 +1,81 @@ +# `github` + +## Purpose + +Project Suaveplan's {@link BetterAuthOauthProvider} entries onto the +`genericOAuth` plugin config Better-Auth consumes. We use `genericOAuth` +(not the bundled `github` social-provider) for a deliberate reason: the +social-provider hard-codes GitHub's production token endpoint URL, which +cannot be redirected onto a mock IdP — `@suaveplan/testing-integration-oauth-mock`'s +`createMockOauthIdp({ userShape: "github" })` exposes a real-HTTP server +shaped like GitHub, but the social-provider would still hit GitHub.com. +`genericOAuth` accepts the full URL triple (`authorizationUrl`, `tokenUrl`, +`userInfoUrl`) so the same wrapper code drives both production GitHub and +the mock fixture — the only difference is the URL set the operator +configures. + +## Features + +- Default scope sets: `read:user user:email` for `providerId: "github"`, + `openid email profile` for any other provider. +- Operator-supplied `scopes` always wins. +- `providerName` plumbed onto Better-Auth's `name` field when set; omitted + otherwise. +- Returns `undefined` from `buildGenericOauthPluginArgs` when no providers + are configured so the caller skips wiring the plugin entirely. + +## Usage: Basic + +```ts +import { buildGenericOauthPluginArgs } from "@suaveplan/api-auth-better-auth"; + +const pluginArgs = buildGenericOauthPluginArgs({ + github: { + providerId: "github", + clientId: process.env.GITHUB_CLIENT_ID!, + clientSecret: process.env.GITHUB_CLIENT_SECRET!, + authorizationUrl: "https://github.com/login/oauth/authorize", + tokenUrl: "https://github.com/login/oauth/access_token", + userInfoUrl: "https://api.github.com/user", + }, +}); +``` + +## Usage: Advanced + +```ts +import { buildGenericOauthProviderConfig } from "@suaveplan/api-auth-better-auth"; +import { createMockOauthIdp } from "@suaveplan/testing-integration-oauth-mock"; + +// Integration test: same provider shape, mock URLs. +const idp = await createMockOauthIdp({ userShape: "github" }); +const cfg = buildGenericOauthProviderConfig({ + providerId: "github", + clientId: "test-cid", + clientSecret: "test-csec", + authorizationUrl: `${idp.url}/authorize`, + tokenUrl: `${idp.url}/token`, + userInfoUrl: `${idp.url}/userinfo`, +}); +``` + +## API Reference + +| Export | Shape | Purpose | +| ------ | ----- | ------- | +| `buildGenericOauthProviderConfig(p)` | `(BetterAuthOauthProvider) => Record` | Single provider → genericOAuth config entry | +| `buildGenericOauthPluginArgs(providers)` | `(Record \| undefined) => Record \| undefined` | Full bag → `{ config: [...] }` | + +## Implementation Notes + +The default GitHub scopes mirror the upstream `github` social-provider's +defaults — `read:user` for the `/user` endpoint, `user:email` for +`/user/emails` (Better-Auth's `genericOAuth` plugin only hits the +configured `userInfoUrl`, but real GitHub still expects the broader scope +set when the operator later switches to the native provider). The +OIDC-compliant default (`openid email profile`) covers Google, Okta, Keycloak +and most other discovery-doc-flavoured IdPs and was the safest "I don't +know which provider, give me an email and a stable id" fallback. The +`providerId` field is the discriminant the upstream plugin matches against +the URL params — `:provider` in `/oauth/:provider/start` MUST match an +entry's `providerId` for the route to resolve. diff --git a/docs/api-stack/api/api-auth-better-auth/src/options/options.md b/docs/api-stack/api/api-auth-better-auth/src/options/options.md new file mode 100644 index 0000000..14ce34f --- /dev/null +++ b/docs/api-stack/api/api-auth-better-auth/src/options/options.md @@ -0,0 +1,105 @@ +# `options` + + +_(no submodules)_ + + +## Purpose + +Zod-validated boundary for the Better-Auth adapter's configuration bag. Both +`createBetterAuthSession` and `createBetterAuthProvider` accept the same +{@link BetterAuthOptions} shape so a single options object can be threaded +through host configuration even when the operator wires only one side of the +auth split. Validation fires at factory-construction time so misconfiguration +fails fast at boot instead of surfacing as a confusing runtime error on the +first inbound request. + +## Features + +- Required fields — `database` (opaque pass-through to Better-Auth), + `baseUrl` (URL-validated), `secret` (>= 16 chars). +- Optional fields — `routePrefix` (`/auth` by default, must start with `/`), + `oauth.providers` (per-provider URL-validated client config), + `session` (cookie tuning), `principalMapping` (pluggable user → Principal). +- Test hook — `betterAuthFactory` lets unit tests stub the underlying + `betterAuth(...)` call without standing up a real database. + +## Usage: Basic + +```ts +import { parseBetterAuthOptions } from "@suaveplan/api-auth-better-auth/options"; + +const opts = parseBetterAuthOptions({ + database: pool, // Better-Auth-shaped value (pg.Pool, Kysely dialect, …) + baseUrl: "https://api.example.com", + secret: process.env.BETTER_AUTH_SECRET!, +}); +``` + +## Usage: Advanced + +```ts +import { parseBetterAuthOptions } from "@suaveplan/api-auth-better-auth/options"; +import type { Principal } from "@suaveplan/api-types/principal"; + +const opts = parseBetterAuthOptions({ + database: pool, + baseUrl: "https://api.example.com", + routePrefix: "/api/auth", + secret: process.env.BETTER_AUTH_SECRET!, + oauth: { + providers: { + github: { + providerId: "github", + clientId: process.env.GITHUB_CLIENT_ID!, + clientSecret: process.env.GITHUB_CLIENT_SECRET!, + scopes: ["read:user", "user:email"], + authorizationUrl: "https://github.com/login/oauth/authorize", + tokenUrl: "https://github.com/login/oauth/access_token", + userInfoUrl: "https://api.github.com/user", + }, + }, + }, + session: { cookieName: "ba.session", cookieSameSite: "lax", cookieSecure: true }, + principalMapping: ({ user }): Principal => ({ + id: user.id as never, + scopes: (user.roles ?? []) as never[], + claims: { email: user.email }, + }), +}); +``` + +## API Reference + +| Export | Shape | Purpose | +| ------ | ----- | ------- | +| `BetterAuthOptionsSchema` | Zod schema | Validates the full options object | +| `parseBetterAuthOptions(raw)` | `(unknown) => BetterAuthOptions` | Parse + throw on failure | +| `DEFAULT_ROUTE_PREFIX` | `"/auth"` | Default mount prefix | +| `DEFAULT_COOKIE_NAME` | `"better-auth.session"` | Default cookie name | +| `BetterAuthOptions` | interface | Outer options shape | +| `BetterAuthOauthProvider` | interface | Per-provider OAuth config | +| `BetterAuthSessionOptions` | interface | Cookie tuning bag | +| `BetterAuthUserView` / `BetterAuthSessionRecord` / `BetterAuthSessionView` | interfaces | Mapper input shape | +| `BetterAuthLike` | interface | Structural slice of `better-auth`'s `Auth` | +| `PrincipalMapping` | function type | `(view) => Principal` | + +## Implementation Notes + +`database` is intentionally typed as `unknown` and the schema only checks +non-null/non-undefined — Better-Auth itself supports `pg.Pool`, Kysely +`Dialect`, `D1Database`, `DBAdapterInstance` and several other shapes; the +wrapper never inspects this value beyond passing it through to +`betterAuth({ database })`. This keeps the wrapper one-driver-agnostic and +lets operators bring their own connection topology (transaction-pool, single +client, serverless adapter, …) without the wrapper opinionating on it. + +`secret` enforces a 16-character floor because Better-Auth uses it for cookie +signing and shorter secrets are trivially brute-forced. The exact constant is +informational — Better-Auth itself would still accept shorter strings — so +the strict check here is a defence-in-depth guard at the wrapper boundary. + +`betterAuthFactory` is the only sanctioned way to inject a stubbed +Better-Auth instance into the adapter. Production callers MUST omit it so the +real `betterAuth(...)` import drives the runtime; tests use it to swap in a +synchronous in-memory stub conforming to {@link BetterAuthLike}. diff --git a/docs/api-stack/api/api-auth-better-auth/src/principal/map-user-to-principal.md b/docs/api-stack/api/api-auth-better-auth/src/principal/map-user-to-principal.md new file mode 100644 index 0000000..c2e819b --- /dev/null +++ b/docs/api-stack/api/api-auth-better-auth/src/principal/map-user-to-principal.md @@ -0,0 +1,77 @@ +# `map-user-to-principal` + + +_(no submodules)_ + + +## Purpose + +Default Better-Auth `(user, session)` → `Principal` mapping consumed by both +`createBetterAuthSession` and `createBetterAuthProvider`. Pure function; given +the same view it always returns the same `Principal`. Operators MAY supply a +custom `principalMapping` in `BetterAuthOptions` to project Better-Auth's +user row onto a custom claims topology, but the default is good enough for +most deployments — it drops sensitive fields, brands `id` and `scopes`, and +prefers `session.activeOrganizationId` over `user.tenantId` so the +organisation plugin's tenant scoping wins automatically when wired. + +## Features + +- `id` ← `user.id` branded as `PrincipalId`. +- `scopes` ← `user.roles` branded as `Scope[]` (empty array when absent). +- `tenantId` ← `session.activeOrganizationId` → `user.tenantId` fallback. +- `claims` ← rest of `user` minus sensitive fields; `session_id` appended. +- Throws `BetterAuthError(AUTH_BA.PRINCIPAL_MAPPING_FAILED)` on missing id. +- Returned `Principal` and its `claims` are frozen. + +## Usage: Basic + +```ts +import { mapBetterAuthUserToPrincipal } from "@suaveplan/api-auth-better-auth/principal"; + +const principal = mapBetterAuthUserToPrincipal({ + user: { id: "u_1", email: "a@b.c", roles: ["admin"] }, + session: { id: "s_1" }, +}); +// → { id: "u_1", scopes: ["admin"], claims: { id, email, roles, session_id } } +``` + +## Usage: Advanced + +```ts +import type { Principal } from "@suaveplan/api-types/principal"; +import type { PrincipalMapping } from "@suaveplan/api-auth-better-auth/options"; + +const customMapping: PrincipalMapping = ({ user, session }): Principal => ({ + id: `tenant_${session.activeOrganizationId}_${user.id}` as never, + scopes: ((user.roles ?? []) as readonly string[]).flatMap((role) => + role === "admin" + ? ["billing:write", "billing:read", "users:write"] + : [role] + ) as never[], + claims: { email: user.email, source: "better-auth" }, +}); + +// Hand the custom mapping through BetterAuthOptions: +// { ..., principalMapping: customMapping } +``` + +## API Reference + +| Export | Shape | Purpose | +| ------ | ----- | ------- | +| `mapBetterAuthUserToPrincipal(view)` | `PrincipalMapping` | Default mapping consumed by both factories | + +## Implementation Notes + +The frozen-object return shape (`Object.freeze` on both the `Principal` and +its `claims` bag) defends against handlers downstream mutating a single +returned principal and observing the mutation on later requests — the same +hardening applied by `@suaveplan/api-auth-static-principal`. The sensitive +field list (`password`, `passwordHash`, `salt`, `twoFactorSecret`, +`magicLinkToken`, `resetPasswordToken`) covers Better-Auth's stock plugin +set; operators who define additional sensitive fields via a custom +Better-Auth plugin SHOULD supply a custom `principalMapping` to drop those +too. The mapping deliberately does NOT translate roles into a stable +scope vocabulary — that's a deployment concern; the default is identity so +the topology stays predictable. diff --git a/docs/api-stack/api/api-auth-better-auth/src/provider/create-provider.md b/docs/api-stack/api/api-auth-better-auth/src/provider/create-provider.md new file mode 100644 index 0000000..78013fd --- /dev/null +++ b/docs/api-stack/api/api-auth-better-auth/src/provider/create-provider.md @@ -0,0 +1,110 @@ +# `create-provider` + +## Purpose + +Factory for the `auth.provider` half of The split. Returns an +`AuthProviderAdapter` (per `@suaveplan/api-auth-provider`) that mounts the +canonical `PROVIDER_ROUTE_SURFACE` (9 routes) under `routePrefix` (default +`/auth`). Each handler internally rewrites the incoming `Request` onto the +Better-Auth-native sub-path via `ROUTE_TRANSLATION` and delegates to +`auth.handler(...)`. This indirection means downstream consumers of the +provider see the canonical foundation surface — never Better-Auth's idioms — +while Better-Auth still owns the precise wire response (cookies, 302 +redirects, error envelopes). + +## Features + +- `id: "better-auth"`; `pathPrefix` validated as `AuthPathPrefix`. +- All 9 canonical route names registered: + - `POST /register` → `POST /sign-up/email` + - `POST /login` → `POST /sign-in/email` + - `POST /logout` → `POST /sign-out` + - `POST /refresh` → `GET /get-session` + - `GET /oauth/:provider/start` → `POST /oauth2/sign-in/:provider` + - `GET /oauth/:provider/callback` → `GET /oauth2/callback/:provider` + - `GET /verify-email/:token` → `GET /verify-email` + - `POST /forgot-password` → `POST /forget-password` + - `POST /reset-password` → `POST /reset-password` +- `routePrefix` collision-checked against + `@suaveplan/api-host/reserved-prefix` — refused with + `AUTH_BA.ROUTE_PREFIX_COLLISION` on collision. +- Better-Auth instance materialised during `lifecycle.install` so DB + unreachable errors fail before traffic. +- OAuth flow conclusions emit `oauth_flows_total{provider,outcome}`. +- Per-options `WeakMap` so the same Better-Auth instance is shared with + `createBetterAuthSession(opts)` when wired with the same options object. + +## Usage: Basic + +```ts +import { createBetterAuthProvider } from "@suaveplan/api-auth-better-auth"; + +const provider = createBetterAuthProvider({ + database: pool, + baseUrl: "https://api.example.com", + secret: process.env.BETTER_AUTH_SECRET!, +}); + +// Mount via the host's plugin lifecycle: +host.registerAuthProvider(provider); +``` + +## Usage: Advanced + +```ts +import { createBetterAuthProvider } from "@suaveplan/api-auth-better-auth"; +import { createBetterAuthSession } from "@suaveplan/api-auth-better-auth"; + +// Operators MUST share the SAME options bag between the two factories to +// share the Better-Auth instance (and thus the DB pool): +const opts = { + database: pool, + baseUrl: "https://api.example.com", + secret: process.env.BETTER_AUTH_SECRET!, + routePrefix: "/api/auth", + oauth: { + providers: { + github: { + providerId: "github", + clientId: process.env.GITHUB_CLIENT_ID!, + clientSecret: process.env.GITHUB_CLIENT_SECRET!, + scopes: ["read:user", "user:email"], + authorizationUrl: "https://github.com/login/oauth/authorize", + tokenUrl: "https://github.com/login/oauth/access_token", + userInfoUrl: "https://api.github.com/user", + }, + }, + }, +}; + +host.registerAuth({ + resolver: createBetterAuthSession(opts), + csrf: true, +}); +host.registerAuthProvider(createBetterAuthProvider(opts)); +``` + +## API Reference + +| Export | Shape | Purpose | +| ------ | ----- | ------- | +| `createBetterAuthProvider(opts)` | `(BetterAuthOptions) => AuthProviderAdapter` | Build the provider | +| `ROUTE_TRANSLATION` | `Record` | Re-exported for callers wanting to introspect the mapping | +| `buildNativeUrl(args)` | function | Re-exported for advanced wrappers | + +## Implementation Notes + +The provider's `routes(router, ctx)` mounts every canonical entry from +`PROVIDER_ROUTE_SURFACE` with `auth: null` because the routes are mounted +INSIDE the auth provider's own prefix and the routes themselves are the +authentication flow — they MUST be reachable unauthenticated. The handler's +inner rewrite reads `(ctx as { params })` because the abstract +`RequestContext` doesn't declare `params`, but the request pipeline driver +(`@suaveplan/api-host/request-pipeline-driver.ts`) attaches them at runtime. +The cast is documented inline. The OAuth outcome heuristic maps status codes +to labels — 2xx/3xx → `success`, 403 → `provider_rejected`, anything else +→ `state_mismatch`. The semantic split between "state_mismatch" and +"provider_rejected" is intentional even though a single 400 covers both +wire-wise: the conformance suite distinguishes the two via the underlying +mock IdP's `primeError` API. The per-options `WeakMap` is keyed by object +identity, not deep equality — sharing requires literal same-object reuse. diff --git a/docs/api-stack/api/api-auth-better-auth/src/provider/route-translation.md b/docs/api-stack/api/api-auth-better-auth/src/provider/route-translation.md new file mode 100644 index 0000000..7a065d3 --- /dev/null +++ b/docs/api-stack/api/api-auth-better-auth/src/provider/route-translation.md @@ -0,0 +1,75 @@ +# `route-translation` + +## Purpose + +Translation table mapping every entry in `PROVIDER_ROUTE_SURFACE` (the +canonical 9-route foundation surface) to the matching Better-Auth-native +sub-path. The wrapper presents the canonical names outward while Better-Auth +still drives the heavy lifting at its idiomatic paths +(`/sign-up/email`, `/sign-in/email`, `/oauth2/sign-in/:providerId`, ...). +Without this translation a host built on the foundation contracts would +need to know Better-Auth-specific URLs — which would defeat the purpose of +the abstract `auth.provider` capability. + +## Features + +- Single immutable map keyed by `ProviderRouteName`. +- Carries both `nativePath` and `nativeMethod` so the wrapper can rewrite + the request method too (some translations flip GET → POST). +- `buildNativeUrl` helper rewrites the canonical request URL onto + Better-Auth's base URL, resolving `:provider` / `:token` params and + preserving the query string. + +## Usage: Basic + +```ts +import { ROUTE_TRANSLATION, buildNativeUrl } from "@suaveplan/api-auth-better-auth"; + +const target = ROUTE_TRANSLATION.login; +// → { nativePath: "/sign-in/email", nativeMethod: "POST" } + +const url = buildNativeUrl({ + baseUrl: "https://api.example.com", + nativePath: target.nativePath, + params: {}, + search: "redirect=/home", +}); +// → URL { https://api.example.com/sign-in/email?redirect=/home } +``` + +## Usage: Advanced + +```ts +import { buildNativeUrl, ROUTE_TRANSLATION } from "@suaveplan/api-auth-better-auth"; + +// OAuth callback — the canonical `/oauth/:provider/callback?code=xxx&state=yyy` +// is rewritten to Better-Auth's `/oauth2/callback/:provider?...` surface. +const target = ROUTE_TRANSLATION["oauth.callback"]; +const native = buildNativeUrl({ + baseUrl: "https://api.example.com", + nativePath: target.nativePath, + params: { provider: "github" }, + search: "code=xxx&state=yyy", +}); +// → URL { https://api.example.com/oauth2/callback/github?code=xxx&state=yyy } +``` + +## API Reference + +| Export | Shape | Purpose | +| ------ | ----- | ------- | +| `NativeRoute` | interface | `{ nativePath, nativeMethod }` | +| `ROUTE_TRANSLATION` | `Readonly>` | Canonical → native map | +| `buildNativeUrl(args)` | function | Rewrite the canonical URL onto Better-Auth's base URL | + +## Implementation Notes + +`Object.freeze` on the outer record + a `Readonly<...>` cast — but not on +the inner entries because each entry is already a frozen literal authored +inline. Decided against `as const` on the outer block so the indexed key +narrowing stays type-friendly under `noPropertyAccessFromIndexSignature`. +`buildNativeUrl` runs `:param` substitution before constructing the URL so +malformed param values can't break out of the path; `encodeURIComponent` +defends against `/` injection in the `:provider` slot. Query string +preservation is critical for OAuth — the entire upstream callback payload +(`code`, `state`, `scope`, …) needs to land on Better-Auth's handler verbatim. diff --git a/docs/api-stack/api/api-auth-better-auth/src/route-prefix/route-prefix.md b/docs/api-stack/api/api-auth-better-auth/src/route-prefix/route-prefix.md new file mode 100644 index 0000000..8d31e71 --- /dev/null +++ b/docs/api-stack/api/api-auth-better-auth/src/route-prefix/route-prefix.md @@ -0,0 +1,79 @@ +# `route-prefix` + + +_(no submodules)_ + + +## Purpose + +Resolve an operator-supplied `routePrefix` against the host's reserved-prefix +contract from `@suaveplan/api-host/reserved-prefix`. This guard ensures the +Better-Auth provider cannot accidentally mount its account-lifecycle routes +inside paths the host (or another first-party engine) reserves for itself — +`/_host` (admin sub-router) and `/internal` (livez/readyz/metrics) today, +plus whatever future entries land in `HOST_RESERVED_PREFIXES`. The check is +performed at provider construction time so misconfiguration fails before the +process is accepting traffic. + +## Features + +- Normalised prefix returned on success (lowercase, leading slash, no + trailing slash) so downstream code can use it without re-normalising. +- Collision detection covers both exact matches (`/internal`) and child + paths (`/internal/livez`). +- Reserved list NOT hard-coded — sourced from `@suaveplan/api-host` so the + wrapper inherits future additions for free. +- Throws `BetterAuthError(AUTH_BA.ROUTE_PREFIX_COLLISION)` with the + normalised collision string in `context.prefix`. + +## Usage: Basic + +```ts +import { assertRoutePrefixAvailable } from "@suaveplan/api-auth-better-auth"; + +const prefix = assertRoutePrefixAvailable("/auth"); // → "/auth" +``` + +## Usage: Advanced + +```ts +import { assertRoutePrefixAvailable } from "@suaveplan/api-auth-better-auth"; +import { BetterAuthError, AUTH_BA_CODES } from "@suaveplan/api-auth-better-auth/error-codes"; + +try { + const prefix = assertRoutePrefixAvailable(operatorConfig.routePrefix); + return mountProvider({ prefix }); +} catch (err) { + if ( + err instanceof BetterAuthError && + err.code === AUTH_BA_CODES.ROUTE_PREFIX_COLLISION + ) { + // The deploy script can report the collision back to the operator + // before traffic is accepted. + reportFatalConfigError({ requested: operatorConfig.routePrefix, code: err.code }); + } + throw err; +} +``` + +## API Reference + +| Export | Shape | Purpose | +| ------ | ----- | ------- | +| `assertRoutePrefixAvailable(prefix)` | `(string) => string` | Validates + returns normalised prefix | + +The function throws `BetterAuthError(AUTH_BA.ROUTE_PREFIX_COLLISION)` when +the prefix collides with `HOST_RESERVED_PREFIXES` from +`@suaveplan/api-host/reserved-prefix`. + +## Implementation Notes + +The lazy `codeFactory` callback pattern from `@suaveplan/api-host`'s +`assertPrefixAvailable` API is critical here — the factory is only invoked on +collision, so the `BetterAuthError` allocation (with its stack trace and +context bag) is skipped on the happy path. The reserved-prefix module also +exports `normalisePrefix` separately; this wrapper calls it to compute the +returned canonical form because `assertPrefixAvailable` returns `void`. This +matches the pattern in `@suaveplan/api-plugin-rbac` and other adapter +packages that need both the throw-on-collision behaviour and the normalised +output value at the call site. diff --git a/docs/api-stack/api/api-auth-better-auth/src/session/create-session.md b/docs/api-stack/api/api-auth-better-auth/src/session/create-session.md new file mode 100644 index 0000000..e3ec65e --- /dev/null +++ b/docs/api-stack/api/api-auth-better-auth/src/session/create-session.md @@ -0,0 +1,94 @@ +# `create-session` + + +_(no submodules)_ + + +## Purpose + +Factory for the `auth.session` half of The split. Returns a +`SessionResolver` that asks Better-Auth's `auth.api.getSession({ headers })` +to materialise the current session and then maps the resulting `(user, +session)` tuple onto a `Principal` per `@suaveplan/api-types`. Returns `null` +when Better-Auth reports no session — the host's resolver chain advances to +the next adapter (typically `api-auth-anonymous`). + +## Features + +- Implements the `SessionResolver` contract from `@suaveplan/api-auth`. +- Pluggable `principalMapping` via `BetterAuthOptions.principalMapping`; + default `mapBetterAuthUserToPrincipal`. +- Lazy + cached Better-Auth instance — shared with + `createBetterAuthProvider` when both factories receive the same options + object (per-`opts` WeakMap). +- OTel instruments emitted on every resolve: `sessions_resolved_total{outcome}`, + `session_resolve_duration_ms{outcome}`, + `principal_mapping_errors_total`. +- Stable failure modes: `INVALID_SESSION`, `DB_UNREACHABLE`, + `PRINCIPAL_MAPPING_FAILED`. +- Disposable — `dispose()` is idempotent and turns subsequent `resolve()` + calls into `null` returns. + +## Usage: Basic + +```ts +import { createBetterAuthSession } from "@suaveplan/api-auth-better-auth"; + +const resolver = createBetterAuthSession({ + database: pool, + baseUrl: "https://api.example.com", + secret: process.env.BETTER_AUTH_SECRET!, +}); + +// Inside the host's resolver chain: +const principal = await resolver.resolve(request); +``` + +## Usage: Advanced + +```ts +import { createBetterAuthSession } from "@suaveplan/api-auth-better-auth"; +import { SessionResolverChain } from "@suaveplan/api-auth/chain"; +import { createAnonymousResolver } from "@suaveplan/api-auth-anonymous"; + +const resolver = new SessionResolverChain({ + resolvers: [ + createBetterAuthSession(opts), + createAnonymousResolver(), + ], +}); + +// The Better-Auth resolver fires first; if it returns `null`, the +// anonymous tail takes over and the host's `publicRoutes` policy applies. +``` + +## API Reference + +| Export | Shape | Purpose | +| ------ | ----- | ------- | +| `createBetterAuthSession(opts)` | `(BetterAuthOptions) => SessionResolver` | Build the resolver | + +The resolver throws `BetterAuthError` with one of: + +- `AUTH_BA.INVALID_SESSION` — unexpected upstream error from Better-Auth's + `getSession`. +- `AUTH_BA.DB_UNREACHABLE` — first-resolve build failed (wraps the + underlying connection error as `cause`). +- `AUTH_BA.PRINCIPAL_MAPPING_FAILED` — `principalMapping` threw; a partial + principal is never returned. + +## Implementation Notes + +`getSession` is consumed via the structural `BetterAuthLike` view declared +in `../options/options.types.ts`. That view is intentionally narrow — only +`handler` and `api.getSession` are referenced — so the unit tests can stub +Better-Auth without touching the real runtime. The per-options WeakMap +(`lazyByOptions`) is the linchpin of the "share an instance between session +and provider" guarantee: passing the same `opts` object to both factories +threads through the same `LazyBetterAuth`. The OTel `finally` block runs on +every code path so the counters reflect every attempt, including failures +that propagate as `BetterAuthError`. `dispose()` resets the cached +Better-Auth instance via `lazy.reset()` and flips a disposed flag that +neutralises any subsequent `resolve()` call. The default Better-Auth factory +dynamically imports `better-auth` so consumers wiring a `betterAuthFactory` +override avoid the cost of loading the upstream package altogether. diff --git a/docs/api-stack/api/api-auth-better-auth/src/testing/testing.md b/docs/api-stack/api/api-auth-better-auth/src/testing/testing.md new file mode 100644 index 0000000..113efb7 --- /dev/null +++ b/docs/api-stack/api/api-auth-better-auth/src/testing/testing.md @@ -0,0 +1,90 @@ +# `testing` + + +_(no submodules)_ + + +## Purpose + +`@suaveplan/api-auth-better-auth/testing` is the subpath downstream packages +import when they want to assert their own wiring layer still meets the +abstract `auth.session` and `auth.provider` contracts on top of this +adapter. It re-exports both conformance harnesses +(`runAuthSessionConformance` from `@suaveplan/api-auth` and +`runAuthProviderConformance` from `@suaveplan/api-auth-provider`) alongside +the two Better-Auth factories from this package, so a single import gets +the consumer everything they need. + +## Features + +- Re-exports `runAuthSessionConformance` + `runAuthProviderConformance` from + the contract packages so consumers don't have to add those packages to + their own dependency closure. +- Re-exports `createBetterAuthSession` + `createBetterAuthProvider` + so the conformance call sites can drop the factory inline. +- `AuthSessionConformanceFactory` / `AuthProviderConformanceFactory` / + `AuthProviderConformanceOptions` type aliases for explicit typing. + +## Usage: Basic + +```ts +import { + createBetterAuthProvider, + runAuthProviderConformance, +} from "@suaveplan/api-auth-better-auth/testing"; + +const results = runAuthProviderConformance({ + label: "my-host's Better-Auth wiring", + factory: () => createBetterAuthProvider(myOptions), +}); +for (const scenario of results) { + it(`${scenario.category} :: ${scenario.name}`, () => { + expect(scenario.passed).toBe(true); + }); +} +``` + +## Usage: Advanced + +```ts +import { + createBetterAuthSession, + runAuthSessionConformance, + type AuthSessionConformanceFactory, +} from "@suaveplan/api-auth-better-auth/testing"; + +const spec: AuthSessionConformanceFactory = { + label: "Postgres-backed Better-Auth + my custom mapping", + factory: () => createBetterAuthSession(myOptionsWithCustomMapping), + seedNull: () => new Request("https://api.example.com/anon"), + seedPrincipal: () => ({ + request: new Request("https://api.example.com/me", { + headers: { cookie: "better-auth.session=valid" }, + }), + expected: knownPrincipal, + }), +}; +runAuthSessionConformance(spec); +``` + +## API Reference + +| Export | Source | Purpose | +| ------ | ------ | ------- | +| `runAuthSessionConformance` | `@suaveplan/api-auth` | Session contract harness | +| `runAuthProviderConformance` | `@suaveplan/api-auth-provider` | Provider contract harness | +| `createBetterAuthSession` | this package | Session factory under test | +| `createBetterAuthProvider` | this package | Provider factory under test | +| `AuthSessionConformanceFactory` | type | Spec passed to session harness | +| `AuthProviderConformanceFactory` | type | Factory signature for provider harness | +| `AuthProviderConformanceOptions` | type | Options for provider harness | + +## Implementation Notes + +The subpath is intentionally light — most of the value is just having one +import path consumers can pull from. The conformance harnesses themselves +live in the contract packages because that's where the abstract invariants +are authored; this package's contribution to "passing conformance" is the +factory pair. Consumers test their own wiring layer (custom middleware, +host configuration, plugin order) by invoking the harnesses with their +own options bag and asserting every `ConformanceScenarioResult.passed`. diff --git a/docs/api-stack/api/api-auth-jwt/README.md b/docs/api-stack/api/api-auth-jwt/README.md new file mode 100644 index 0000000..edf0298 --- /dev/null +++ b/docs/api-stack/api/api-auth-jwt/README.md @@ -0,0 +1,135 @@ +# @suaveplan/api-auth-jwt — concrete JWT session resolver for @suaveplan/api-auth. Verifies a JWT presented on the Authorization header (or a configurable cookie) using @suaveplan/jws against either a JWKS endpoint (TTL + negative-cache + in-flight dedup) or a single static JsonWebKey; projects validated claims onto a Principal via an overridable mapper. Returns null on parse/verify failure (chain semantics) and contributes a Bearer JWT OpenAPI security scheme. + +Stage-4 concrete `SessionResolver` for the +[`@suaveplan/api`](../api/README.md) plugin system. Verifies a JWT +presented on the `Authorization: Bearer ` header (or a configured +cookie) against either a remote JWKS endpoint or a single static JWK, +then projects the validated claims onto the foundation's `Principal` +contract via an overridable mapper. + +This is the adapter you pair with hosted identity providers (Clerk, +Auth0, Cognito, Stytch, custom Keycloak deployments) or with any +self-hosted JWT-issuing provider. It is **session-resolver only** — +login / register / refresh routes are the responsibility of an `auth` +provider, not this package. + + +## Documentation tree + +- [claims-mapper](./src/claims-mapper/claims-mapper.md) — Default and runtime helpers for converting a verified JWT payload (`Claims`) into a `Principal` from `@suaveplan/api-ty… + - [claims-mapper](./src/claims-mapper/claims-mapper.md) — Default and runtime helpers for converting a verified JWT payload (`Claims`) into a `Principal` from `@suaveplan/api-ty… +- [error-codes](./src/error-codes/error-codes.md) — Stable error-code registry for `@suaveplan/api-auth-jwt`, exposing the `AUTH_JWT.*` namespace via `defineCodes` from `@… + - [error-codes](./src/error-codes/error-codes.md) — Stable error-code registry for `@suaveplan/api-auth-jwt`, exposing the `AUTH_JWT.*` namespace via `defineCodes` from `@… +- [jwks-cache](./src/jwks-cache/jwks-cache.md) — In-process JWKS cache for `@suaveplan/api-auth-jwt`. Fetches a JWKS document from a remote endpoint, holds it under a p… + - [jwks-cache](./src/jwks-cache/jwks-cache.md) — In-process JWKS cache for `@suaveplan/api-auth-jwt`. Fetches a JWKS document from a remote endpoint, holds it under a p… +- [options](./src/options/options.md) — Defines the Zod-validated boundary for `createJwtSessionResolver` and the companion `validateOptions` helper. The bound… + - [options](./src/options/options.md) — Defines the Zod-validated boundary for `createJwtSessionResolver` and the companion `validateOptions` helper. The bound… +- [resolver](./src/resolver/resolver.md) — Stage-4 concrete `SessionResolver` factory for the API plugin system. Reads a JWT from the request (Authorization h… + - [resolver](./src/resolver/resolver.md) — Stage-4 concrete `SessionResolver` factory for the API plugin system. Reads a JWT from the request (Authorization h… +- [security-scheme](./src/security-scheme/security-scheme.md) — Builds the `SecuritySchemeContribution` this adapter contributes to the generated OpenAPI document. The shape is the ca… + - [security-scheme](./src/security-scheme/security-scheme.md) — Builds the `SecuritySchemeContribution` this adapter contributes to the generated OpenAPI document. The shape is the ca… + + +## Surface + +- [`./resolver`](src/resolver/resolver.md) — `createJwtSessionResolver(opts)`. +- [`./jwks-cache`](src/jwks-cache/jwks-cache.md) — `JwksCache` with TTL, + negative cache, in-flight dedup, `kid`-miss refresh. +- [`./claims-mapper`](src/claims-mapper/claims-mapper.md) — + `defaultClaimsToPrincipal` + `runClaimsMapper` helpers. +- [`./security-scheme`](src/security-scheme/security-scheme.md) — + `JWT_BEARER_SCHEME` and `createJwtBearerSecurityScheme(name)` for + OpenAPI emission. +- [`./error-codes`](src/error-codes/error-codes.md) — `AUTH_JWT_*` codes + + `AuthJwtError` class. +- [`./options`](src/options/options.md) — Zod-validated options + boundary. + +## Quick start + +```ts +import { createJwtSessionResolver } from "@suaveplan/api-auth-jwt/resolver"; +import { JWT_BEARER_SCHEME } from "@suaveplan/api-auth-jwt/security-scheme"; + +const resolver = createJwtSessionResolver({ + jwksUrl: "https://idp.example/.well-known/jwks.json", + issuer: "https://idp.example", + audience: "https://api.example", + algorithms: ["RS256"], +}); + +// Use in an api-host AuthAdapter: +const adapter = { + resolver, + securityScheme: JWT_BEARER_SCHEME, +}; +``` + +## Pairing with hosted IdPs + +The package is designed to be paired with an external identity provider +that already issues JWTs. The recipe is the same for every provider — +plug in the provider's JWKS URL, issuer, and audience, then add a custom +`claimsToPrincipal` when the provider uses non-standard claim names. + +### Clerk + +```ts +createJwtSessionResolver({ + jwksUrl: "https://your-instance.clerk.accounts.dev/.well-known/jwks.json", + issuer: "https://your-instance.clerk.accounts.dev", + audience: "your-frontend-api", + algorithms: ["RS256"], + claimsToPrincipal: (claims) => { + const sub = claims["sub"]; + if (typeof sub !== "string") return null; + return { + id: sub as never, + scopes: [] as never[], + tenantId: typeof claims["org_id"] === "string" + ? (claims["org_id"] as never) + : undefined, + claims, + }; + }, +}); +``` + +### Auth0 + +```ts +createJwtSessionResolver({ + jwksUrl: "https://your-tenant.auth0.com/.well-known/jwks.json", + issuer: "https://your-tenant.auth0.com/", + audience: "https://api.example.com", + algorithms: ["RS256"], +}); +``` + +### Cognito + +```ts +createJwtSessionResolver({ + jwksUrl: "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXXX/.well-known/jwks.json", + issuer: "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXXX", + audience: "your-cognito-app-client-id", + algorithms: ["RS256"], +}); +``` + +## Semantics + +`resolve()` returns `null` on any per-request soft failure (missing +token, malformed token, bad signature, wrong issuer, wrong audience, +expired, not-yet-valid, no matching JWKS key). That collapse lets the +upstream `SessionResolverChain` fall through to the next adapter +(anonymous, static-bearer, etc.). It throws only on infrastructure +failures — `AUTH_JWT.JWKS_FETCH_FAILED` when the JWKS endpoint is +unreachable, `AUTH_JWT.INVALID_KEY_FORMAT` for a malformed static key, +`AUTH_JWT.INVALID_CLAIMS_MAPPER` when the caller's mapper throws or +returns a non-Principal value. + +## License + +MIT — see the repository. + diff --git a/docs/api-stack/api/api-auth-jwt/src/claims-mapper/claims-mapper.md b/docs/api-stack/api/api-auth-jwt/src/claims-mapper/claims-mapper.md new file mode 100644 index 0000000..f65eb11 --- /dev/null +++ b/docs/api-stack/api/api-auth-jwt/src/claims-mapper/claims-mapper.md @@ -0,0 +1,84 @@ +# `claims-mapper` — `Claims → Principal` projection + + +_(no submodules)_ + + +## Purpose + +Default and runtime helpers for converting a verified JWT payload +(`Claims`) into a `Principal` from `@suaveplan/api-types`. The default +projection follows OAuth 2 / OIDC conventions: `sub` for subject, +space-delimited `scope` (or array-form `scopes`) for authorisation +scopes, and `tenant_id` / `tid` for the tenant. Callers can override +the projection entirely to read non-standard claims (e.g. Clerk's +`org_id`) or to enforce additional invariants — return `null` to defer +to the next resolver in the chain. + +## Features + +- `defaultClaimsToPrincipal` — drop-in OAuth 2 / OIDC projection. +- `runClaimsMapper` — wraps a caller-supplied mapper; catches throws, + rejects non-Principal returns, surfaces both as + `AUTH_JWT.INVALID_CLAIMS_MAPPER`. +- Returns `null` when the token has no `sub` — that is the documented + "not a user identity" path and lets the chain move on. +- Brands `PrincipalId`, `Scope`, and `TenantId` via type assertion at + the trust boundary; downstream consumers see opaque branded strings. +- Passes the full claims record through as `principal.claims` so + downstream tenant resolvers / authorisation rules can read raw values + without a second token parse. + +## Usage: Basic + +```ts +import { defaultClaimsToPrincipal } from "@suaveplan/api-auth-jwt/claims-mapper"; + +const principal = defaultClaimsToPrincipal({ + sub: "user_123", + scope: "billing:read profile:read", + tenant_id: "acme", +}); +// → { id: "user_123", scopes: ["billing:read", "profile:read"], tenantId: "acme", claims: {...} } +``` + +## Usage: Advanced + +Override the projection to read Clerk-style `org_id` and enforce a +non-empty scopes list: + +```ts +import type { ClaimsToPrincipal } from "@suaveplan/api-auth-jwt/claims-mapper"; + +const clerkMapper: ClaimsToPrincipal = (claims) => { + const sub = claims["sub"]; + const scope = claims["scope"]; + const org = claims["org_id"]; + if (typeof sub !== "string" || typeof scope !== "string") return null; + return { + id: sub as never, + scopes: scope.split(" ") as never[], + tenantId: typeof org === "string" ? (org as never) : undefined, + claims, + }; +}; +``` + +## API Reference + +- `ClaimsToPrincipal` — `(claims) => Principal | null`. +- `defaultClaimsToPrincipal: ClaimsToPrincipal` — the built-in projection. +- `runClaimsMapper(mapper, claims): Principal | null` — invoke a mapper + with structured error reporting. + +## Implementation Notes + +The default mapper deliberately tolerates either string-form (`"a b c"`) +or array-form (`["a", "b", "c"]`) scopes — RFC 6749 §3.3 uses the +former, while several IdPs (Auth0, Cognito) emit the latter. Empty +strings are filtered out so a stray double-space does not produce a +zero-length scope token. Tenant extraction prefers `tenant_id` (the +Suaveplan-canonical name) over `tid` (the Microsoft / OIDC name) but +accepts both. A mapper that throws is treated as an operator bug, not a +caller error — surfacing it as a `null` would silently mask broken +configuration. diff --git a/docs/api-stack/api/api-auth-jwt/src/error-codes/error-codes.md b/docs/api-stack/api/api-auth-jwt/src/error-codes/error-codes.md new file mode 100644 index 0000000..2835acc --- /dev/null +++ b/docs/api-stack/api/api-auth-jwt/src/error-codes/error-codes.md @@ -0,0 +1,76 @@ +# `error-codes` — `AUTH_JWT_*` stable codes + + +_(no submodules)_ + + +## Purpose + +Stable error-code registry for `@suaveplan/api-auth-jwt`, exposing the +`AUTH_JWT.*` namespace via `defineCodes` from `@suaveplan/error` and a +matching `AuthJwtError` subclass of `SuaveplanError`. The registry lists +only the codes the package throws — namely the infrastructure failures an +operator must act on. Per-request soft failures (bad token, expired +signature, wrong audience, etc.) deliberately do not get codes; they +collapse to `null` so that the upstream `SessionResolverChain` can move on +to the next resolver, which is the documented chain semantic. + +## Features + +- `AUTH_JWT_CODES.JWKS_FETCH_FAILED` — JWKS endpoint unreachable or + returned a non-2xx after the configured retries, and there is no cached + set old enough to use. Operators see this in logs / metrics; callers + see a 401. +- `AUTH_JWT_CODES.INVALID_KEY_FORMAT` — `options.staticKey` failed JWK + schema validation at construction time. +- `AUTH_JWT_CODES.INVALID_CLAIMS_MAPPER` — `options.claimsToPrincipal` + threw or returned a value that is not a `Principal` or `null`. +- `AuthJwtError` carries the matching `AuthJwtErrorCode`, integrates with + the `SuaveplanError` cause-chain, redaction, and OTel span-event + adapters from `@suaveplan/error`. + +## Usage: Basic + +```ts +import { AUTH_JWT_CODES, AuthJwtError } from "@suaveplan/api-auth-jwt/error-codes"; + +try { + // ... resolver internals ... +} catch (cause) { + throw new AuthJwtError( + AUTH_JWT_CODES.JWKS_FETCH_FAILED, + "JWKS endpoint unreachable", + { cause } + ); +} +``` + +## Usage: Advanced + +Branch on the code at the boundary to map infrastructure failures to +operator alerts rather than user-facing 401s: + +```ts +import { AUTH_JWT_CODES, AuthJwtError } from "@suaveplan/api-auth-jwt/error-codes"; + +function isOperatorActionable(err: unknown): err is AuthJwtError { + if (!(err instanceof AuthJwtError)) return false; + return err.code === AUTH_JWT_CODES.JWKS_FETCH_FAILED; +} +``` + +## API Reference + +- `AUTH_JWT_CODES` — frozen record produced by `defineCodes("AUTH_JWT", [...])`. +- `AuthJwtErrorCode` — union of the three string literals. +- `AuthJwtError extends SuaveplanError` — `jwtCode` + mirrors `code` for ergonomic `instanceof` narrowing. + +## Implementation Notes + +The three-code registry is intentionally small. Adding "soft" failure +codes here would tempt consumers to branch on them, defeating the chain +semantic that `null` means "not my caller". If a richer breakdown is +needed downstream, emit it on the failure counter (`reason` attribute) +rather than as a separate `AUTH_JWT.*` code. Registry membership is the +public contract; only add codes through an OpenSpec change. diff --git a/docs/api-stack/api/api-auth-jwt/src/jwks-cache/jwks-cache.md b/docs/api-stack/api/api-auth-jwt/src/jwks-cache/jwks-cache.md new file mode 100644 index 0000000..d32ecb7 --- /dev/null +++ b/docs/api-stack/api/api-auth-jwt/src/jwks-cache/jwks-cache.md @@ -0,0 +1,91 @@ +# `jwks-cache` — TTL-bounded JWKS resolution + + +_(no submodules)_ + + +## Purpose + +In-process JWKS cache for `@suaveplan/api-auth-jwt`. Fetches a JWKS +document from a remote endpoint, holds it under a positive TTL, +negative-caches transient failures, dedupes concurrent fetches into a +single network request, and supports forced refresh on a `kid` miss +(the standard "the IdP rotated keys" recovery path). Throws +`AUTH_JWT.JWKS_FETCH_FAILED` only when neither a fresh fetch nor a stale +cached document is available — under partial outages we prefer +stale-but-valid keys to a 401 storm. + +## Features + +- Positive TTL (default 10 minutes) with monotonic clock injection. +- Negative cache window (default 30 seconds) on fetch failure — within + the window callers see the stale document if any, otherwise the + error. +- In-flight dedup: concurrent `getKeyForKid` callers share a single + network round-trip. +- `forceRefresh()` for operator-triggered rotation. +- `kid` miss against a cached document triggers exactly one refresh. +- JSON shape validation (`{ keys: object[] }`) at the boundary. + +## Usage: Basic + +```ts +import { JwksCache } from "@suaveplan/api-auth-jwt/jwks-cache"; + +const cache = new JwksCache({ + url: "https://idp.example/.well-known/jwks.json", + ttlMs: 10 * 60 * 1000, + negativeMs: 30 * 1000, + clock: { nowMs: () => Date.now() }, + fetchImpl: fetch, +}); + +const jwk = await cache.getKeyForKid("kid-2024-01"); +``` + +## Usage: Advanced + +Inject a fake clock and a controllable fetch impl for tests of the +expiry and dedup behaviours: + +```ts +let now = 0; +const calls: number[] = []; +const cache = new JwksCache({ + url: "https://idp.example/.well-known/jwks.json", + ttlMs: 1000, + negativeMs: 100, + clock: { nowMs: () => now }, + fetchImpl: async () => { + calls.push(now); + return new Response(JSON.stringify({ keys: [{ kid: "a", kty: "RSA", n: "...", e: "AQAB" }] }), { + status: 200, + headers: { "content-type": "application/json" }, + }); + }, +}); +await cache.getKeyForKid("a"); +now = 500; +await cache.getKeyForKid("a"); // cache hit, no second fetch +``` + +## API Reference + +- `class JwksCache` — constructor takes `{ url, ttlMs, negativeMs, clock, + fetchImpl }`. +- `getKeyForKid(kid?: string): Promise | undefined>` + — fetch-as-needed, returns `undefined` when no key matches. +- `forceRefresh(): Promise` — clear cache and refetch. +- `JwksDocument` — `{ keys: ReadonlyArray> }`. + +## Implementation Notes + +When the token carries no `kid`, the cache only returns a key when the +JWKS contains exactly one entry — ambiguous lookups must be a 401, not +a guess. The negative cache window is short by design (30s default); +longer windows accumulate authentication outages, shorter windows +hammer the IdP. The in-flight dedup uses a single `Promise` field +rather than a queue — the second concurrent caller awaits the same +promise as the first. The "kid miss after a just-fetched document" +guard prevents infinite refresh loops when the IdP legitimately does +not have a matching key. diff --git a/docs/api-stack/api/api-auth-jwt/src/options/options.md b/docs/api-stack/api/api-auth-jwt/src/options/options.md new file mode 100644 index 0000000..616714c --- /dev/null +++ b/docs/api-stack/api/api-auth-jwt/src/options/options.md @@ -0,0 +1,82 @@ +# `options` — `JwtSessionResolverOptions` boundary + + +_(no submodules)_ + + +## Purpose + +Defines the Zod-validated boundary for `createJwtSessionResolver` and the +companion `validateOptions` helper. The boundary enforces every static +contract the runtime depends on: exactly one of `jwksUrl` or `staticKey`, +non-empty `algorithms` allowlist, mandatory `issuer` and `audience`, a +positive cache TTL, and a non-negative negative-cache window. Anything +the schema cannot encode (injectable clock, fetch impl, claims mapper +function) is part of the wider `JwtSessionResolverOptions` TypeScript +type but is not Zod-validated — those are dev-time contracts. + +## Features + +- Strict-mode object schema rejects unknown keys at construction. +- Mutual exclusion check for `jwksUrl` / `staticKey` — both supplied or + neither supplied throws `AUTH_JWT.INVALID_KEY_FORMAT`. +- Sensible defaults: header name `authorization`, JWKS TTL 10 min, + negative cache 30s, clock tolerance 0. +- Accepts `issuer` and `audience` as either a single string or a + non-empty list of strings — JWS verify enforces membership. + +## Usage: Basic + +```ts +import { validateOptions } from "@suaveplan/api-auth-jwt/options"; + +const opts = validateOptions({ + jwksUrl: "https://idp.example/.well-known/jwks.json", + issuer: "https://idp.example", + audience: "https://api.example", + algorithms: ["RS256"], +}); +``` + +## Usage: Advanced + +Custom header, cookie fallback, tighter cache TTL, and a custom claims +mapper: + +```ts +import { validateOptions } from "@suaveplan/api-auth-jwt/options"; + +const opts = validateOptions({ + staticKey: { kty: "oct", k: "..." }, + issuer: ["https://idp1.example", "https://idp2.example"], + audience: "https://api.example", + algorithms: ["HS256"], + headerName: "x-api-token", + cookieName: "sp_session", + clockToleranceSec: 5, + jwksCacheTtlMs: 60_000, + jwksNegativeCacheMs: 5_000, +}); +``` + +## API Reference + +- `JwtSessionResolverOptionsSchema` — Zod object schema. +- `JwtSessionResolverOptions` — public surface (includes non-serialisable + fields like `clock`, `fetchImpl`, `claimsToPrincipal`). +- `ValidatedJwtSessionResolverOptions` — inferred shape after defaults + are applied. +- `validateOptions(raw)` — synchronous validator; throws `AuthJwtError` + with code `AUTH_JWT.INVALID_KEY_FORMAT` on any boundary failure. + +## Implementation Notes + +The schema is intentionally `.strict()` so a typo in a key name fails +loudly at construction rather than silently activating defaults. `iss` +and `aud` are both required because token-level `iss` / `aud` confusion +is a documented attack vector — every Stage-4 deployment is expected to +pin both. `algorithms` is also mandatory and non-empty — `@suaveplan/jws` +already refuses to verify without an allowlist, but we re-enforce it at +the API boundary so the error surface is consistent. The mutual +exclusion check after parsing matches what the spec calls out: a single +key source is the only way to reason about JWKS cache invalidation. diff --git a/docs/api-stack/api/api-auth-jwt/src/resolver/resolver.md b/docs/api-stack/api/api-auth-jwt/src/resolver/resolver.md new file mode 100644 index 0000000..316ad15 --- /dev/null +++ b/docs/api-stack/api/api-auth-jwt/src/resolver/resolver.md @@ -0,0 +1,108 @@ +# `resolver` — `createJwtSessionResolver` + + +_(no submodules)_ + + +## Purpose + +Stage-4 concrete `SessionResolver` factory for the API plugin +foundation. Reads a JWT from the request (Authorization header or +configurable cookie), verifies it via `@suaveplan/jws` against either a +JWKS endpoint (cached and refreshed on `kid` miss) or a single static +JWK, validates `iss`, `aud`, `exp`, `nbf` against the configured policy, +and projects the validated claims onto a `Principal` via an overridable +mapper. The factory is the only public entry point — internals +(`JwksCache`, claims mapper, error registry) are surface-exported for +testability but most consumers use `createJwtSessionResolver(opts)` alone. + +## Features + +- `Authorization: Bearer ` header extraction with case-insensitive + scheme match; configurable header name accepts a raw token form for + non-standard headers (e.g. `x-api-token: `). +- Cookie fallback when `cookieName` is supplied; header still wins when + both are present. +- JWKS resolution via `JwksCache` with positive TTL, negative cache, + in-flight dedup, and `kid`-miss refresh. +- Static-key path for HS-family symmetric tokens or single-key + deployments. +- Mandatory `iss` and `aud` enforcement (single string or list); `exp` + and `nbf` enforced when present with configurable `clockToleranceSec`. +- Per-request soft failures collapse to `null` so the upstream + `SessionResolverChain` can fall through to the next adapter; operator + failures (JWKS unreachable, malformed mapper, malformed static key) + surface as `AuthJwtError` with the documented codes. +- Idempotent `dispose()` flips an internal flag so subsequent + `resolve()` calls return `null` rather than emitting late traffic on + a torn-down resolver. + +## Usage: Basic + +```ts +import { createJwtSessionResolver } from "@suaveplan/api-auth-jwt/resolver"; + +const resolver = createJwtSessionResolver({ + jwksUrl: "https://idp.example/.well-known/jwks.json", + issuer: "https://idp.example", + audience: "https://api.example", + algorithms: ["RS256"], +}); + +const req = new Request("https://api.example/users", { + headers: { authorization: "Bearer eyJ..." }, +}); +const principal = await resolver.resolve(req); +``` + +## Usage: Advanced + +Static HS256 key, cookie fallback, custom claims mapper, and an +injectable clock for deterministic temporal-claim tests: + +```ts +import { createJwtSessionResolver } from "@suaveplan/api-auth-jwt/resolver"; + +const resolver = createJwtSessionResolver({ + staticKey: { kty: "oct", k: "" }, + issuer: ["https://idp1.example", "https://idp2.example"], + audience: "https://api.example", + algorithms: ["HS256"], + cookieName: "sp_session", + clockToleranceSec: 5, + clock: { nowMs: () => 1_700_000_000_000 }, + claimsToPrincipal: (claims) => { + const sub = claims["sub"]; + if (typeof sub !== "string") return null; + return { + id: sub as never, + scopes: [] as never[], + tenantId: typeof claims["org_id"] === "string" + ? (claims["org_id"] as never) + : undefined, + claims, + }; + }, +}); +``` + +## API Reference + +- `createJwtSessionResolver(opts: JwtSessionResolverOptions): SessionResolver` + — returns the `@suaveplan/api-auth` `SessionResolver` shape (`resolve` + + idempotent `dispose`). + +## Implementation Notes + +The resolver deliberately separates "this is not my caller" (chain +falls through, returns `null`) from "the host is mis-configured" +(throws `AuthJwtError`). Verification failures inside `@suaveplan/jws` +return `null` so a stray Bearer header from an unrelated IdP cannot +401-storm the API — the chain's next adapter (anonymous, static key, +etc.) still gets its turn. The temporal-claim check uses a single +clock reading per request to avoid TOCTOU between the `exp` and `nbf` +arms. We re-implement `iss`/`aud`/`exp`/`nbf` enforcement here rather +than push it into `@suaveplan/jws` because those are JWT-claim +concerns, not JWS-protected-header concerns — the JWS package +deliberately handles only RFC 7515 (signature) and leaves RFC 7519 +(payload claims) to its consumers. diff --git a/docs/api-stack/api/api-auth-jwt/src/security-scheme/security-scheme.md b/docs/api-stack/api/api-auth-jwt/src/security-scheme/security-scheme.md new file mode 100644 index 0000000..d0021e4 --- /dev/null +++ b/docs/api-stack/api/api-auth-jwt/src/security-scheme/security-scheme.md @@ -0,0 +1,66 @@ +# `security-scheme` — OpenAPI Bearer JWT contribution + + +_(no submodules)_ + + +## Purpose + +Builds the `SecuritySchemeContribution` this adapter contributes to the +generated OpenAPI document. The shape is the canonical OAS 3.1 +`http` / `bearer` scheme with `bearerFormat: "JWT"`. Stage-8 +`@suaveplan/api-openapi` consumes the contribution and inlines it under +`components.securitySchemes[name]`, then references it from operation +`security` blocks for non-public routes. + +## Features + +- Canonical Bearer-JWT scheme — no surprise extensions, no proprietary + fields. +- Configurable contribution name (`bearerAuth` default) so multiple JWT + resolvers can coexist (e.g. user-side `bearerAuth` + service-side + `serviceBearerAuth`). +- `JWT_BEARER_SCHEME` constant for callers that only ever expose one + JWT resolver. +- Human-readable `description` field that links the scheme back to the + adapter so docs readers understand where verification happens. + +## Usage: Basic + +```ts +import { JWT_BEARER_SCHEME } from "@suaveplan/api-auth-jwt/security-scheme"; + +const adapter = { + resolver: createJwtSessionResolver(...).resolver, + securityScheme: JWT_BEARER_SCHEME, +}; +``` + +## Usage: Advanced + +Rename the contribution for a dual-resolver host: + +```ts +import { createJwtBearerSecurityScheme } from "@suaveplan/api-auth-jwt/security-scheme"; + +const userScheme = createJwtBearerSecurityScheme("userAuth"); +const serviceScheme = createJwtBearerSecurityScheme("serviceAuth"); +``` + +## API Reference + +- `createJwtBearerSecurityScheme(name = "bearerAuth")` → + `SecuritySchemeContribution` from `@suaveplan/api-auth`. +- `JWT_BEARER_SCHEME` — pre-built `bearerAuth`-named contribution. + +## Implementation Notes + +The `http` / `bearer` form is the only OAS 3.1 scheme that documents +"this endpoint accepts a Bearer JWT" without forcing the OpenAPI +emitter to inline OAuth-flow metadata that this adapter does not own. +The `bearerFormat` field is documentation-only per the spec, but +populating it as `"JWT"` is the convention every OAS reader (Swagger +UI, Redoc, Stoplight) recognises. Tenant or scope expectations are +expressed by individual route handlers, not the scheme itself — +keeping the scheme orthogonal to the route catalogue keeps it stable +across plugin upgrades. diff --git a/docs/api-stack/api/api-auth-provider/README.md b/docs/api-stack/api/api-auth-provider/README.md new file mode 100644 index 0000000..463129a --- /dev/null +++ b/docs/api-stack/api/api-auth-provider/README.md @@ -0,0 +1,68 @@ +# @suaveplan/api-auth-provider - Abstract auth-provider contract for the Suaveplan API plugin system. Defines AuthProviderAdapter, the canonical provider route surface, path-ownership registry, collision detector, the auth.provider CapabilityId, the AUTH_PROVIDER error-code registry, and the provider conformance harness. $2; concrete providers (better-auth, rolled) ship in Stages 6 and 8. + +Abstract account-lifecycle contract for the Suaveplan API plugin system +(contracts). This package is OPTIONAL: hosted-IdP deployments +(Clerk, Auth0, Cognito) install only the session resolver from +`@suaveplan/api-auth`; self-hosted deployments install exactly one provider +implementation (`api-auth-better-auth` , `api-auth-rolled` in +Stage 8) which structurally implements `AuthProviderAdapter` from this +package. + + +## Documentation tree + +- [capability-id](./src/capability-id/capability-id.md) — The `capability-id` module pins the runtime literal for the `"auth.provider"` capability this package contributes to th… + - [capability-id](./src/capability-id/capability-id.md) — The `capability-id` module pins the runtime literal for the `"auth.provider"` capability this package contributes to th… +- [collision-detector](./src/collision-detector/collision-detector.md) — `collision-detector` is the install-time guard that prevents a plugin from accidentally squatting on the auth-provider'… + - [collision-detector](./src/collision-detector/collision-detector.md) — `collision-detector` is the install-time guard that prevents a plugin from accidentally squatting on the auth-provider'… +- [error-codes](./src/error-codes/error-codes.md) — This module centralises the four stable error codes the auth-provider contract emits — `PATH_COLLISION`, `MULTIPLE_PROV… + - [error-codes](./src/error-codes/error-codes.md) — This module centralises the four stable error codes the auth-provider contract emits — `PATH_COLLISION`, `MULTIPLE_PROV… +- [path-ownership](./src/path-ownership/path-ownership.md) — `path-ownership` is the runtime registry the host consults to enforce the "exactly one auth provider per deployment" in… + - [path-ownership](./src/path-ownership/path-ownership.md) — `path-ownership` is the runtime registry the host consults to enforce the "exactly one auth provider per deployment" in… +- [provider](./src/provider/provider.md) — The `provider` module is the type-level + thin-runtime heart of `@suaveplan/api-auth-provider`. It declares the abstrac… + - [provider](./src/provider/provider.md) — The `provider` module is the type-level + thin-runtime heart of `@suaveplan/api-auth-provider`. It declares the abstrac… +- [route-surface](./src/route-surface/route-surface.md) — `route-surface` declares the closed set of paths an auth provider OWNS relative to its `pathPrefix`. The set is the uni… + - [route-surface](./src/route-surface/route-surface.md) — `route-surface` declares the closed set of paths an auth provider OWNS relative to its `pathPrefix`. The set is the uni… +- [testing](./src/testing/conformance.md) — `runAuthProviderConformance` is the runner-agnostic harness every concrete `AuthProviderAdapter` MUST clear. It exercis… + - [conformance](./src/testing/conformance.md) — `runAuthProviderConformance` is the runner-agnostic harness every concrete `AuthProviderAdapter` MUST clear. It exercis… + + +## What ships here + +- `AuthProviderAdapter` contract — `id`, `pathPrefix`, + `routes(router, ctx)`, four-hook lifecycle. +- `AuthPathPrefix` brand + Zod-validated `authPathPrefix` constructor. +- `PROVIDER_ROUTE_SURFACE` — the canonical 9-entry route table providers + project from. +- `PathOwnership` runtime registry — enforces "exactly one provider" + install-time invariant. +- `detectAuthPathCollisions` — install-time guard that plugin routes do not + squat on the provider's owned prefix. +- `AUTH_PROVIDER_CAPABILITY_ID` constant — `"auth.provider"`. +- `AUTH_PROVIDER_CODES` — the four-code error registry plus + `AuthProviderError` and the `authProviderError` factory. +- `runAuthProviderConformance` — runner-agnostic harness every concrete + provider clears. + +## Module index + +- [provider](src/provider/provider.md) +- [route-surface](src/route-surface/route-surface.md) +- [path-ownership](src/path-ownership/path-ownership.md) +- [collision-detector](src/collision-detector/collision-detector.md) +- [capability-id](src/capability-id/capability-id.md) +- [error-codes](src/error-codes/error-codes.md) +- [testing/conformance](src/testing/conformance.md) + +## Dependencies + +- `@suaveplan/api-types` (workspace) — `AuthProviderAdapter` consumes + `Router`, `PluginContext`, `CapabilityId`, `CapabilityRequirements`. +- `@suaveplan/error` (workspace) — `SuaveplanError` + `defineCodes`. +- `zod` (catalog) — `AuthPathPrefixSchema`. +- `tslib` (catalog) — emitter helpers. + +## Stage / status + +Concrete providers ship in Stages 6 / 8. + diff --git a/docs/api-stack/api/api-auth-provider/src/capability-id/capability-id.md b/docs/api-stack/api/api-auth-provider/src/capability-id/capability-id.md new file mode 100644 index 0000000..814f0bc --- /dev/null +++ b/docs/api-stack/api/api-auth-provider/src/capability-id/capability-id.md @@ -0,0 +1,78 @@ +# `capability-id` — `"auth.provider"` capability contribution + + +_(no submodules)_ + + +## Purpose + +The `capability-id` module pins the runtime literal for the +`"auth.provider"` capability this package contributes to the host's +capability registry. The closed `CapabilityId` union in +`@suaveplan/api-types` already includes `"auth.provider"` (alongside +`"auth.session"`); this module simply exposes a typed constant and predicate +so concrete providers, the host's capability resolver, and downstream +plugin manifests can author against a single value rather than a free-form +string. Centralising the literal gives us one place to grep if the id ever +needs to evolve via an OpenSpec change. + +## Features + +- `AUTH_PROVIDER_CAPABILITY_ID` constant pinned to `"auth.provider"` via a + `satisfies` clause that fails the build if the literal drifts out of the + `CapabilityId` union. +- `isAuthProviderCapabilityId(value)` runtime type-guard for capability + descriptors that flow through `unknown`. +- `AuthProviderCapabilityId` type alias — `Extract` — + so consumers can name the type without re-spelling the literal. + +## Usage: Basic + +```ts +import { AUTH_PROVIDER_CAPABILITY_ID } from "@suaveplan/api-auth-provider/capability-id"; + +definePlugin({ + requires: [AUTH_PROVIDER_CAPABILITY_ID] as const, + start: async (ctx) => { + // ctx.capabilities["auth.provider"] is now in scope. + }, +}); +``` + +## Usage: Advanced + +The host's capability resolver inspects untyped descriptors and narrows them +to the typed slot via the predicate: + +```ts +import { + AUTH_PROVIDER_CAPABILITY_ID, + isAuthProviderCapabilityId, +} from "@suaveplan/api-auth-provider/capability-id"; + +function bindCapability(descriptor: { id: string }) { + if (isAuthProviderCapabilityId(descriptor.id)) { + // descriptor.id is now typed as "auth.provider". + registerSlot(AUTH_PROVIDER_CAPABILITY_ID, descriptor); + } +} +``` + +## API Reference + +- `const AUTH_PROVIDER_CAPABILITY_ID: AuthProviderCapabilityId` — frozen + literal. +- `function isAuthProviderCapabilityId(value: string): value is AuthProviderCapabilityId` +- `type AuthProviderCapabilityId = Extract` + +## Implementation Notes + +The `satisfies` clause is the load-bearing line of the module — if the +`CapabilityId` union ever loses `"auth.provider"`, the build fails here +rather than downstream. The predicate uses an equality test against the +constant rather than the literal to keep the two in lockstep — if a future +change renames the id, the constant and predicate move together. There is +intentionally no companion type-augmentation block here; the union in +`@suaveplan/api-types` is closed and pre-includes every capability the host +knows about, so adding a capability is a co-located OpenSpec change to that +package and not a downstream module-augmentation pattern. diff --git a/docs/api-stack/api/api-auth-provider/src/collision-detector/collision-detector.md b/docs/api-stack/api/api-auth-provider/src/collision-detector/collision-detector.md new file mode 100644 index 0000000..406e3d2 --- /dev/null +++ b/docs/api-stack/api/api-auth-provider/src/collision-detector/collision-detector.md @@ -0,0 +1,88 @@ +# `collision-detector` — install-time auth-path collision check + + +_(no submodules)_ + + +## Purpose + +`collision-detector` is the install-time guard that prevents a plugin from +accidentally squatting on the auth-provider's owned path prefix. It walks +every plugin route, segment-aligns its path against the provider's +`pathPrefix`, and emits `AUTH_PROVIDER.PATH_COLLISION` entries for every +overlap that is not on the plugin's `publicRoutes` allowlist or marked +`isPublic` on the per-route descriptor. Returning a report instead of +throwing keeps callers in control of how to surface aggregated failures — +typically the host turns a non-empty report into a single error listing +every offender. + +## Features + +- Segment-aware containment — `/auth` matches `/auth` and `/auth/login` but + NOT `/authoritative`. +- Configurable prefix — a deployment that mounts the provider under + `/myauth` shifts the collision domain accordingly. +- Per-route `isPublic` opt-out for plugin routes that augment the auth + surface (e.g. a custom `/auth/healthz`). +- Plugin-level `publicRoutes` allowlist — identical effect, declared once + per plugin manifest. +- Aggregating reporter — every offender is returned in one frozen report. +- Trailing-slash normalisation — `/auth` and `/auth/` are treated as equal. + +## Usage: Basic + +```ts +import { detectAuthPathCollisions } from "@suaveplan/api-auth-provider/collision-detector"; + +const report = detectAuthPathCollisions({ provider, plugins }); +if (report.hasCollisions) { + throw new Error(`Auth-path collisions: ${report.entries.length}`); +} +``` + +## Usage: Advanced + +Aggregating a problem-detail response across every offender: + +```ts +import { + detectAuthPathCollisions, + type CollisionReportEntry, +} from "@suaveplan/api-auth-provider/collision-detector"; + +const report = detectAuthPathCollisions({ provider, plugins }); +if (report.hasCollisions) { + const offenders = report.entries.map( + (e: CollisionReportEntry) => ({ plugin: e.details.plugin, path: e.details.path }) + ); + return new Response( + JSON.stringify({ type: "auth-collision", offenders }), + { status: 409 } + ); +} +``` + +## API Reference + +- `function detectAuthPathCollisions(input: DetectCollisionsInput): CollisionReport` +- `function isInsidePrefix(routePath: string, prefix: string): boolean` +- `function normalisePrefix(prefix: string): string` +- `interface DetectCollisionsInput { provider; plugins }` +- `interface PluginDescriptor { name; routes; publicRoutes? }` +- `interface PluginRouteDescriptor { path; method?; isPublic? }` +- `interface CollisionReport { entries; hasCollisions }` +- `interface CollisionReportEntry { code; message; details }` + +## Implementation Notes + +The detector returns a non-throwing report so the host can decide whether a +collision is fatal or merely loggable — empirically a deployment running an +older plugin against a newer provider needs the choice. Segment-aware +matching is essential: a naïve `startsWith` would falsely flag +`/authoritative` (or worse, `/auth-cache`) when the provider owns `/auth`. +The root prefix `"/"` is short-circuited to "owns nothing" so a deployment +that mistakenly configures the auth provider at the root does not blow up +the whole route table; the path-prefix validator catches that mis-configuration +at construction time. Two opt-out paths (per-route `isPublic` and plugin +`publicRoutes`) coexist because manifests historically use one or the other +and supporting both keeps migration tractable. diff --git a/docs/api-stack/api/api-auth-provider/src/error-codes/error-codes.md b/docs/api-stack/api/api-auth-provider/src/error-codes/error-codes.md new file mode 100644 index 0000000..9c35e4e --- /dev/null +++ b/docs/api-stack/api/api-auth-provider/src/error-codes/error-codes.md @@ -0,0 +1,91 @@ +# `error-codes` — `AUTH_PROVIDER` error-code registry + + +_(no submodules)_ + + +## Purpose + +This module centralises the four stable error codes the auth-provider +contract emits — `PATH_COLLISION`, `MULTIPLE_PROVIDERS_REGISTERED`, +`PROVIDER_LIFECYCLE_FAILED`, `OAUTH_CALLBACK_INVALID_STATE` — and pairs each +with HTTP / severity / retry metadata so downstream consumers (problem-detail +mappers, log routers, retry wrappers) classify failures without +string-matching messages. The registry is built with `defineCodes` from +`@suaveplan/error`, which preserves the literal-typed union through the +public surface so exhaustive `switch (err.code)` blocks report unhandled +reasons at type-check time. + +## Features + +- `AUTH_PROVIDER_CODES` — frozen `{ REASON: "AUTH_PROVIDER.REASON" }` record. +- `AuthProviderErrorCode` union of fully-qualified codes. +- `AuthProviderErrorKey` union of short keys (`"PATH_COLLISION"`). +- `AUTH_PROVIDER_ERROR_METADATA` — per-code HTTP status / severity / retryable + flag / human description. +- `AuthProviderError` — concrete `SuaveplanError` subclass with a public + constructor. +- `authProviderError(key, opts)` — factory that defaults `messageKey` to + `auth_provider.errors.`. +- `getAuthProviderCodeMetadata(code)` — lookup helper used by adapters. + +## Usage: Basic + +```ts +import { authProviderError } from "@suaveplan/api-auth-provider/error-codes"; + +throw authProviderError("OAUTH_CALLBACK_INVALID_STATE", { + context: { state: requestState }, +}); +``` + +## Usage: Advanced + +A problem-detail mapper turns any thrown `AuthProviderError` into an HTTP +response with the correct status, retry hint, and severity-driven log level. + +```ts +import { + AUTH_PROVIDER_ERROR_METADATA, + AuthProviderError, +} from "@suaveplan/api-auth-provider/error-codes"; + +function mapToProblem(err: AuthProviderError): Response { + const meta = AUTH_PROVIDER_ERROR_METADATA[err.code]; + return new Response( + JSON.stringify({ + type: `https://errors.suaveplan/${err.code}`, + title: err.message, + status: meta.httpStatus, + retryable: meta.retryable, + }), + { status: meta.httpStatus } + ); +} +``` + +## API Reference + +- `const AUTH_PROVIDER_CODES` +- `type AuthProviderErrorCode` +- `type AuthProviderErrorKey` +- `interface AuthProviderCodeMetadata` +- `const AUTH_PROVIDER_ERROR_METADATA: Readonly>` +- `class AuthProviderError extends SuaveplanError` — + public constructor `(code, messageKey, opts?)`. +- `function authProviderError(key, opts?): AuthProviderError` +- `function getAuthProviderCodeMetadata(code: string): AuthProviderCodeMetadata | undefined` + +## Implementation Notes + +`SuaveplanError`'s base constructor is `protected`; the subclass exposes a +public constructor so callers outside this package — including the +conformance harness — can build typed errors without going through the +factory. The factory is preferred for everyday use because it derives the +i18n message key from the short reason key, keeping the call site dense. The +metadata record is frozen with `Object.freeze` (not just `as const`) so a +runtime caller cannot mutate the table; `satisfies` keeps the table +exhaustive at type-check time. `PATH_COLLISION` maps to HTTP 409 because the +host refuses the install rather than overwriting an existing route; an +adapter that needs a different status should override the mapper rather than +re-shape the registry. diff --git a/docs/api-stack/api/api-auth-provider/src/path-ownership/path-ownership.md b/docs/api-stack/api/api-auth-provider/src/path-ownership/path-ownership.md new file mode 100644 index 0000000..25575cc --- /dev/null +++ b/docs/api-stack/api/api-auth-provider/src/path-ownership/path-ownership.md @@ -0,0 +1,83 @@ +# `path-ownership` — single-provider registry + + +_(no submodules)_ + + +## Purpose + +`path-ownership` is the runtime registry the host consults to enforce the +"exactly one auth provider per deployment" invariant from design §2.3. A +provider claims its `pathPrefix` at install time; any subsequent registration +with a different provider id throws `MULTIPLE_PROVIDERS_REGISTERED`. The +registry is deliberately not a module-global singleton — each host instance +constructs its own `PathOwnership`, which keeps multi-tenant test runners +and hot-reload scenarios deterministic. + +## Features + +- `PathOwnership` class with `register`, `release`, `current`, `hasProvider`. +- Injectable `clock` — defaults to `Date.now`, used for the `claimedAt` + timestamp on the recorded claim. +- Idempotent registration — re-registering the same instance, or a different + instance with the same provider id, returns the existing claim. +- Strict rejection of a different provider id with + `AUTH_PROVIDER.MULTIPLE_PROVIDERS_REGISTERED`, including a structured + `context` payload (`incomingProviderId`, `incumbentProviderId`, + `prefix`) suitable for diagnostic logs. +- `release()` drops the current claim — used by host shutdown and the + blue-green hot-reload sequence to swap providers atomically. + +## Usage: Basic + +```ts +import { PathOwnership } from "@suaveplan/api-auth-provider/path-ownership"; + +const ownership = new PathOwnership(); +ownership.register(myProvider); +``` + +## Usage: Advanced + +Tests inject a deterministic clock so the recorded `claimedAt` is stable +across runs: + +```ts +import { PathOwnership } from "@suaveplan/api-auth-provider/path-ownership"; + +const ownership = new PathOwnership({ clock: () => 1_000_000 }); +const claim = ownership.register(myProvider); +// claim.claimedAt === 1_000_000 + +// Hot-reload: release before swapping in the new provider. +ownership.release(); +ownership.register(replacementProvider); +``` + +## API Reference + +- `class PathOwnership` — runtime registry. + - `constructor(options?: PathOwnershipOptions)` + - `register(provider): PathOwnershipClaim` + - `release(): void` + - `current(): ProviderClaim | null` + - `hasProvider(): boolean` +- `interface PathOwnershipOptions { clock? }` +- `type OwnershipClock = () => number` +- `interface PathOwnershipClaim { providerId; prefix; claimedAt }` +- `interface ProviderClaim { provider; claim }` + +## Implementation Notes + +The registry stores both the `AuthProviderAdapter` instance and a flat +`PathOwnershipClaim` record. Two layers exist because consumers fall into +two camps: hosts that need the live provider for lifecycle dispatch, and +diagnostic tooling that only needs the metadata. Idempotency is decided by +identity first, id second — so a host that constructs a fresh provider +instance per hot-reload still cannot accidentally register two providers +with the same id. The `MULTIPLE_PROVIDERS_REGISTERED` error carries enough +context for operators to diagnose double-installation in a misconfigured +multi-process deployment without consulting the host logs. The class uses a +private field rather than a module-level variable so multiple registries can +coexist in the same process — essential for runner-agnostic test suites and +multi-tenant in-process deployments. diff --git a/docs/api-stack/api/api-auth-provider/src/provider/provider.md b/docs/api-stack/api/api-auth-provider/src/provider/provider.md new file mode 100644 index 0000000..c52c3bb --- /dev/null +++ b/docs/api-stack/api/api-auth-provider/src/provider/provider.md @@ -0,0 +1,92 @@ +# `provider` — `AuthProviderAdapter` contract + path-prefix validation + + +_(no submodules)_ + + +## Purpose + +The `provider` module is the type-level + thin-runtime heart of +`@suaveplan/api-auth-provider`. It declares the abstract `AuthProviderAdapter` +interface every concrete account-lifecycle provider (Better-Auth, the rolled +reference, future Cognito/Auth0 bridges) structurally implements, and ships +the Zod-validated `authPathPrefix` constructor that asserts a deployment's +configured prefix is a legal segment-aligned mount point. By splitting the +contract from any concrete provider we keep this package optional: a +hosted-IdP deployment installs the session resolver (`api-auth`) only and +never pulls in a provider implementation. + +## Features + +- `AuthProviderAdapter` interface with `id`, configurable `pathPrefix`, + `routes(router, ctx)` registration callback, and the four-hook + `AuthProviderLifecycle` quartet (`install`/`start`/`stop`/`uninstall`). +- `AuthPathPrefix` opaque brand — protects against accidental string + substitution at the install boundary. +- `AuthPathPrefixSchema` — a Zod schema enforcing leading slash, no trailing + slash (except `/`), no path parameters, no whitespace. +- `authPathPrefix(value)` constructor — returns the branded value or throws + `AUTH_PROVIDER.PROVIDER_LIFECYCLE_FAILED` with a structured `reason`. +- `isAuthPathPrefix(value)` predicate — non-throwing variant for tests. +- `DEFAULT_AUTH_PATH_PREFIX` constant (`"/auth"`). + +## Usage: Basic + +```ts +import { + authPathPrefix, + DEFAULT_AUTH_PATH_PREFIX, + type AuthProviderAdapter, +} from "@suaveplan/api-auth-provider/provider"; + +const myProvider: AuthProviderAdapter = { + id: "rolled", + pathPrefix: authPathPrefix(DEFAULT_AUTH_PATH_PREFIX), + routes(router) { + router.post("/login", { auth: null }, async () => new Response()); + }, + lifecycle: { + install: async () => {}, + start: async () => {}, + stop: async () => {}, + uninstall: async () => {}, + }, +}; +``` + +## Usage: Advanced + +A deployment that mounts its provider under a non-standard prefix MUST run +the input through `authPathPrefix` so the value is validated before the host +records the claim in the path-ownership registry. + +```ts +import { authPathPrefix } from "@suaveplan/api-auth-provider/provider"; + +const prefix = authPathPrefix(process.env.AUTH_PREFIX ?? "/auth/v2"); +// Throws AUTH_PROVIDER.PROVIDER_LIFECYCLE_FAILED on input like +// "/auth/v2/" or "/auth/:tenant". +``` + +## API Reference + +- `interface AuthProviderAdapter` — provider contract. +- `interface AuthProviderLifecycle` — install/start/stop/uninstall. +- `type AuthPathPrefix` — branded prefix string. +- `const AuthPathPrefixSchema: ZodType` — validation schema. +- `function authPathPrefix(value: string): AuthPathPrefix` — throwing + constructor. +- `function isAuthPathPrefix(value: string): boolean` — predicate. +- `const DEFAULT_AUTH_PATH_PREFIX = "/auth"` — host default. + +## Implementation Notes + +The brand is purely a TypeScript construct (`unique symbol`) — at runtime +`authPathPrefix("/auth")` returns the string unchanged. The schema's order of +refinements is significant: the leading-slash check fires first so callers +see the most actionable error message. Whitespace is rejected before the +parameter check because shell-supplied configuration is the typical source of +both classes of error. The constructor surfaces failures as +`PROVIDER_LIFECYCLE_FAILED` (not a hypothetical `INVALID_PREFIX`) because the +install lifecycle is the only legitimate call site — keeping the code small +makes the error registry tighter and the metadata table denser. diff --git a/docs/api-stack/api/api-auth-provider/src/route-surface/route-surface.md b/docs/api-stack/api/api-auth-provider/src/route-surface/route-surface.md new file mode 100644 index 0000000..30a0e4e --- /dev/null +++ b/docs/api-stack/api/api-auth-provider/src/route-surface/route-surface.md @@ -0,0 +1,87 @@ +# `route-surface` — canonical auth-provider route surface + + +_(no submodules)_ + + +## Purpose + +`route-surface` declares the closed set of paths an auth provider OWNS +relative to its `pathPrefix`. The set is the union of the routes any +realistic concrete provider exposes — register, login, logout, refresh, two +OAuth-flow endpoints, email verification, and the forgot/reset-password +pair. Providers MAY implement a subset; the canonical list is the bar the +collision detector measures against and the manifest the OpenAPI emitter +projects when stitching a unified document at build time. + +## Features + +- `PROVIDER_ROUTE_SURFACE` — frozen array of `ProviderRouteEntry` records, + every entry carrying `path`, `method`, stable `name`, and OpenAPI + `summary`. +- `ProviderRouteName` literal union — exhaustive narrowing in switch blocks. +- `lookupProviderRoute(name)` — name → entry lookup. +- `resolveProviderRoutePath(prefix, entry)` — mount under a given prefix + (handles `"/"` as a no-op). +- `listProviderRouteNames()` — declaration-order name iteration; used by the + conformance harness to verify every canonical name has a scenario. + +## Usage: Basic + +```ts +import { + PROVIDER_ROUTE_SURFACE, + resolveProviderRoutePath, +} from "@suaveplan/api-auth-provider/route-surface"; + +for (const entry of PROVIDER_ROUTE_SURFACE) { + console.log(entry.method, resolveProviderRoutePath("/auth", entry)); +} +``` + +## Usage: Advanced + +The OpenAPI emitter walks the surface to generate the global `paths` block +for the unified document, projecting `summary` directly into the OpenAPI +operation and using `name` as `operationId` after kebab → camelCase +conversion. + +```ts +import { + PROVIDER_ROUTE_SURFACE, + resolveProviderRoutePath, +} from "@suaveplan/api-auth-provider/route-surface"; + +const openapiPaths: Record = {}; +for (const entry of PROVIDER_ROUTE_SURFACE) { + const path = resolveProviderRoutePath(provider.pathPrefix, entry); + openapiPaths[path] = { + [entry.method.toLowerCase()]: { + operationId: entry.name.replace(/[-.]/g, "_"), + summary: entry.summary, + tags: ["auth"], + }, + }; +} +``` + +## API Reference + +- `interface ProviderRouteEntry { path; method; name; summary }` +- `type ProviderRouteName` — closed union of 9 names. +- `const PROVIDER_ROUTE_SURFACE: ReadonlyArray` +- `function lookupProviderRoute(name: ProviderRouteName): ProviderRouteEntry | undefined` +- `function resolveProviderRoutePath(prefix: string, entry: ProviderRouteEntry): string` +- `function listProviderRouteNames(): ReadonlyArray` + +## Implementation Notes + +The surface is frozen at module-load with two layers of `Object.freeze` — +once around the outer array and once around each entry — to keep downstream +hosts from mutating the table at runtime. `resolveProviderRoutePath` treats +`"/"` as the empty-prefix case so a deployment that mounts the provider at +the host root produces `"/login"` rather than `"//login"`. Adding a new +canonical route requires an OpenSpec change because the conformance harness +and the OpenAPI projector both treat the surface as authoritative; touching +either side without the other is the bug class this list-as-data design +guards against. diff --git a/docs/api-stack/api/api-auth-provider/src/testing/conformance.md b/docs/api-stack/api/api-auth-provider/src/testing/conformance.md new file mode 100644 index 0000000..00c7e53 --- /dev/null +++ b/docs/api-stack/api/api-auth-provider/src/testing/conformance.md @@ -0,0 +1,89 @@ +# `testing/conformance` — provider conformance harness + + +_(no submodules)_ + + +## Purpose + +`runAuthProviderConformance` is the runner-agnostic harness every concrete +`AuthProviderAdapter` MUST clear. It exercises the four critical contract +surfaces — path ownership, canonical route surface, lifecycle quartet, and +collision-detector behaviour — against a fresh provider instance per +scenario. Concrete provider packages call the harness inside a `describe()` +block in their own test file and turn each returned `ConformanceScenarioResult` +into an `it()` assertion. The harness deliberately does not import a test +runner; that responsibility stays at the call site so providers compatible +with `vitest`, `bun:test`, or any other runner can all share the same +behaviour bar. + +## Features + +- Four-category coverage — `path-ownership`, `route-surface`, `lifecycle`, + `collision`. +- Fresh-provider-per-scenario semantics — the factory is invoked once per + scenario so cross-scenario state cannot leak. +- Records every category and scenario name in the returned array so callers + can verify (in their own tests) that every category is exercised. +- Returns a `passed` boolean per scenario plus an optional `detail` string + for debug context. +- Frozen return value — the caller cannot accidentally mutate the report + while iterating. + +## Usage: Basic + +```ts +import { describe, expect, it } from "@suaveplan/testing/runner"; +import { runAuthProviderConformance } from "@suaveplan/api-auth-provider/testing"; + +describe("better-auth conformance", () => { + const results = runAuthProviderConformance({ + label: "better-auth", + factory: () => buildBetterAuthProvider(), + }); + for (const r of results) { + it(`[${r.category}] ${r.name}`, { timeout: 5000 }, () => { + expect(r.passed, r.detail).toBe(true); + }); + } +}); +``` + +## Usage: Advanced + +A provider whose factory is async (e.g. needs to bring up a Mailpit +testcontainer for verify-email) wraps the synchronous factory the harness +expects and runs setup outside it: + +```ts +import { runAuthProviderConformance } from "@suaveplan/api-auth-provider/testing"; + +const env = await startMailpit(); +const results = runAuthProviderConformance({ + label: "better-auth-with-mailpit", + factory: () => buildBetterAuthProvider({ smtp: env.connection }), +}); +await env.dispose(); +``` + +## API Reference + +- `function runAuthProviderConformance(options): ReadonlyArray` +- `interface AuthProviderConformanceOptions { label; factory }` +- `type AuthProviderConformanceFactory = () => AuthProviderAdapter` +- `type AuthProviderConformanceCategory = + "path-ownership" | "route-surface" | "lifecycle" | "collision"` +- `interface ConformanceScenarioResult { category; name; passed; detail? }` + +## Implementation Notes + +The harness deliberately drives a synchronous factory because the +information it asserts is structural — `id`, `pathPrefix`, lifecycle quartet +presence, route surface enumeration — and forcing async setup into every +provider creates fixture-management noise where none is needed. Providers +that need real I/O (e.g. database-backed user creation) layer their own +scenarios on top. Each category drives a fresh provider instance, so a +scenario that crashes one provider does not leave global state poisoned for +the next. The `lifecycle` category checks for the four-function quartet by +`typeof === "function"`; a provider whose `stop` hook is missing or +non-callable fails the check loud rather than at runtime. diff --git a/docs/api-stack/api/api-auth-rolled/README.md b/docs/api-stack/api/api-auth-rolled/README.md new file mode 100644 index 0000000..938c88c --- /dev/null +++ b/docs/api-stack/api/api-auth-rolled/README.md @@ -0,0 +1,83 @@ +# @suaveplan/api-auth-rolled — rolled-our-own auth provider. Implements both `auth.session` and `auth.provider` capability contracts. Session tokens are RS256-signed JWTs (via @suaveplan/crypto-rsa + @suaveplan/jws) with rotating `kid` for non-disruptive key rotation. Passwords are hashed via Argon2id (@suaveplan/crypto-hash), gated by @suaveplan/password-strength and @suaveplan/hibp at registration. Provider mounts the canonical 9-route PROVIDER_ROUTE_SURFACE under a configurable path prefix. DB access via injected @suaveplan/types `DatabaseLike` — shares the host's main connection per design §2.3. Projects DB rows onto the @suaveplan/api-types `Principal` shape. Contributes cookie + bearer OpenAPI security schemes. + +Stage-8.12 rolled session-token resolver for `@suaveplan/api`. Issues +RS256-signed JWTs with rotating `kid` slots, verifies tokens through the +rotator's active + retired-non-revoked key set, projects DB rows onto +the `@suaveplan/api-types` `Principal` contract, and contributes cookie ++ bearer OpenAPI security schemes. + +This milestone ships the **session-resolver half** of the eventual dual +contract (`auth.session`). The matching `AuthProviderAdapter` +(account-lifecycle routes, password gating, MFA, OAuth) is deferred to +a successor change `api-auth-rolled-provider`. + + +## Documentation tree + +- [composition](./src/composition/composition.md) — Top-level factory `createRolledAuthAdapter` that wires the four sub-modules (`token-rotator`, `session`, `principal-pro… + - [composition](./src/composition/composition.md) — Top-level factory `createRolledAuthAdapter` that wires the four sub-modules (`token-rotator`, `session`, `principal-pro… +- [error-codes](./src/error-codes/error-codes.md) — Stable error-code registry for `@suaveplan/api-auth-rolled`. Every code is namespaced under `AUTH_ROLLED.*` so cross-pa… + - [error-codes](./src/error-codes/error-codes.md) — Stable error-code registry for `@suaveplan/api-auth-rolled`. Every code is namespaced under `AUTH_ROLLED.*` so cross-pa… +- [options](./src/options/options.md) — Defines the configuration shape accepted by `createRolledAuthAdapter` and the Zod schema that validates it. Operators w… + - [options](./src/options/options.md) — Defines the configuration shape accepted by `createRolledAuthAdapter` and the Zod schema that validates it. Operators w… +- [principal-projection](./src/principal-projection/principal-projection.md) — Projects the package's internal `UserRow` storage shape onto the abstract `Principal` contract published by `@suaveplan… + - [principal-projection](./src/principal-projection/principal-projection.md) — Projects the package's internal `UserRow` storage shape onto the abstract `Principal` contract published by `@suaveplan… +- [security-schemes](./src/security-schemes/security-schemes.md) — Contributes OpenAPI 3.1 `securitySchemes` entries describing both transports the rolled session resolver accepts — `Aut… + - [security-schemes](./src/security-schemes/security-schemes.md) — Contributes OpenAPI 3.1 `securitySchemes` entries describing both transports the rolled session resolver accepts — `Aut… +- [session](./src/session/session.md) — The rolling-JWT session resolver — the keystone of the rolled auth adapter. Builds a `SessionResolver` (per `@suaveplan… + - [session](./src/session/session.md) — The rolling-JWT session resolver — the keystone of the rolled auth adapter. Builds a `SessionResolver` (per `@suaveplan… +- [token-rotator](./src/token-rotator/token-rotator.md) — Owns the rotating-keyset state for the rolled session-token resolver. The active key signs new JWTs; retired-but-non-re… + - [token-rotator](./src/token-rotator/token-rotator.md) — Owns the rotating-keyset state for the rolled session-token resolver. The active key signs new JWTs; retired-but-non-re… + + +## Why + +This package gives operators a +session-auth path that owns zero third-party runtime dependencies. + +## Install + +```bash +bun add @suaveplan/api-auth-rolled +``` + +## Modules + +| Module | What it owns | +|---|---| +| `composition/` | `createRolledAuthAdapter` — the public factory. | +| `error-codes/` | The 4-code `AUTH_ROLLED.*` registry. | +| `options/` | Zod-validated options + named defaults. | +| `principal-projection/` | `UserRow` → `Principal` projection. | +| `security-schemes/` | Cookie + bearer OpenAPI contributions. | +| `session/` | RS256 sign/verify, cookie+bearer extraction, `Set-Cookie`. | +| `token-rotator/` | Rotating-key state machine. | + +## Quick start + +```ts +import { createRolledAuthAdapter } from "@suaveplan/api-auth-rolled"; + +const adapter = createRolledAuthAdapter({ + store: hostStore, + keys: [{ kid: "k1", privateJwk, publicJwk, active: true }], + issuer: "https://api.example.com", + audience: "example-front", +}); + +host.registerAuthSession(adapter); +``` + +Rotation cron: + +```ts +setInterval(async () => { + if (!adapter.rotator.decide().shouldRotate) return; + adapter.rotator.setKeys(await kms.nextKeyset()); +}, 60_000); +``` + +## License + +MIT + diff --git a/docs/api-stack/api/api-auth-rolled/src/composition/composition.md b/docs/api-stack/api/api-auth-rolled/src/composition/composition.md new file mode 100644 index 0000000..3d08ef2 --- /dev/null +++ b/docs/api-stack/api/api-auth-rolled/src/composition/composition.md @@ -0,0 +1,85 @@ +# `composition` + + +_(no submodules)_ + + +## Purpose + +Top-level factory `createRolledAuthAdapter` that wires the four +sub-modules (`token-rotator`, `session`, `principal-projection`, +`security-schemes`) into a single `AuthAdapter` ready for the host to +register. Keeping the composition explicit (rather than letting each +sub-module own its own host wiring) means the dependency graph is one +arrow: options flow in, an adapter object flows out, no hidden state. + +The returned value extends the `AuthAdapter` contract (`resolver` + +`securityScheme`) with three additional surfaces the future provider +half (`api-auth-rolled-provider`) will consume: `issueToken`, +`verifyToken`, and the rotator handle so operators can wire +`setKeys(...)` from an out-of-band rotation cron. + +## Features + +- Single entry point — `createRolledAuthAdapter(rawOptions)`. +- Options validated via the package's Zod schema before any wiring runs. +- Defaults filled at the composition layer (cookie name, rotation + period, session TTL) so individual sub-modules stay focused on their + one concern. +- Returned adapter is structurally a valid `AuthAdapter` so any host + that accepts the contract will accept the rolled adapter. + +## Usage: Basic + +```ts +import { createRolledAuthAdapter } from "@suaveplan/api-auth-rolled"; + +const adapter = createRolledAuthAdapter({ + store, + keys: [ + { kid: "k1", privateJwk, publicJwk, active: true }, + ], + issuer: "https://api.example.com", + audience: "example-front", +}); + +host.registerAuthSession(adapter); +``` + +## Usage: Advanced + +```ts +import { createRolledAuthAdapter } from "@suaveplan/api-auth-rolled"; + +const adapter = createRolledAuthAdapter({ + store, + keys: initialKeys, + issuer: "https://api.example.com", + audience: "example-front", + cookieName: "acme.session", + sessionTtlSec: 1800, + rotationPeriodMs: 12 * 60 * 60 * 1000, +}); + +// Operator rotation cron — fetch new key from KMS, swap atomically. +setInterval(async () => { + if (!adapter.rotator.decide().shouldRotate) return; + const next = await kms.nextKeyset(); + adapter.rotator.setKeys(next); +}, 60_000); +``` + +## API Reference + +- `createRolledAuthAdapter(rawOptions: unknown): RolledAuthAdapter` +- `RolledAuthAdapter extends AuthAdapter`: adds `id: "rolled"`, `rotator`, + `issueToken(userId)`, `verifyToken(token)`. + +## Implementation Notes + +The adapter intentionally keeps `id` as the literal `"rolled"` so a host +running both Better-Auth and rolled can disambiguate by adapter id. The +`securityScheme` slot points at the bearer contribution (the canonical +single-scheme shape) but the `.schemes` map on the contribution exposes +both the cookie and bearer entries — emitters aware of dual-transport +adapters can register both names without a separate adapter property. diff --git a/docs/api-stack/api/api-auth-rolled/src/error-codes/error-codes.md b/docs/api-stack/api/api-auth-rolled/src/error-codes/error-codes.md new file mode 100644 index 0000000..3e2b0a5 --- /dev/null +++ b/docs/api-stack/api/api-auth-rolled/src/error-codes/error-codes.md @@ -0,0 +1,78 @@ +# `error-codes` + + +_(no submodules)_ + + +## Purpose + +Stable error-code registry for `@suaveplan/api-auth-rolled`. Every code is +namespaced under `AUTH_ROLLED.*` so cross-package consumers (the host's audit +log, the OpenAPI emitter, the conformance harness) can identify the package +that raised the failure without string-matching on free-form messages. + +The milestone ships the session-resolver half only; the registry +is correspondingly minimal — four operator-actionable infrastructure codes, +all of which are thrown synchronously from production code paths and +covered by the conformance test. Per-request soft failures (missing token, +bad signature, expired) collapse to `null` per `SessionResolver` chain +semantics and are therefore NOT codes. Account-lifecycle codes +(`USER_NOT_FOUND`, `INVALID_CREDENTIALS`, `PASSWORD_BREACHED`, …) belong to +the deferred provider half and will be added by a successor change. + +## Features + +- Tagged with `defineCodes("AUTH_ROLLED", [...])` from `@suaveplan/error`, + so all codes share a single namespace prefix. +- `AuthRolledError` extends `SuaveplanError` so `instanceof AuthRolledError` + narrows `.code` to `AuthRolledErrorCode`. +- Four codes: `SIGNING_KEY_NOT_CONFIGURED` (options validation), + `KEY_ROTATION_FAILED` (`TokenRotator.setKeys`), + `DATABASE_REQUIRED` (missing `store`), `PRINCIPAL_PROJECTION_FAILED` + (malformed user row). + +## Usage: Basic + +```ts +import { AUTH_ROLLED_CODES, AuthRolledError } from "@suaveplan/api-auth-rolled"; + +throw new AuthRolledError( + AUTH_ROLLED_CODES.DATABASE_REQUIRED, + "host did not inject a store" +); +``` + +## Usage: Advanced + +```ts +import { AUTH_ROLLED_CODES, AuthRolledError } from "@suaveplan/api-auth-rolled"; + +try { + /* ... */ +} catch (err) { + if (err instanceof AuthRolledError) { + // .rolledCode is typed as AuthRolledErrorCode — no narrowing cast. + if (err.rolledCode === AUTH_ROLLED_CODES.KEY_ROTATION_FAILED) { + log.fatal({ err }, "operator key-rotation contract violated"); + } + } + throw err; +} +``` + +## API Reference + +- `AUTH_ROLLED_CODES` — frozen `Record`. +- `AuthRolledErrorCode` — string-literal union of every code value. +- `AuthRolledError extends SuaveplanError` — has a + `rolledCode: AuthRolledErrorCode` convenience accessor. + +## Implementation Notes + +The set of 20 codes is fixed by the OpenSpec spec delta. The conformance +test enumerates `AUTH_ROLLED_CODES` and asserts every code has a named +production trigger; if a code is added without a trigger, the test fails +loudly. Cross-package codes (e.g. `HIBP.*` propagated from +`@suaveplan/hibp` when the breach lookup fails) are NOT re-encoded — they +surface to the caller intact through `SuaveplanError`'s `cause` chain so +operators can attribute failures to the originating layer. diff --git a/docs/api-stack/api/api-auth-rolled/src/options/options.md b/docs/api-stack/api/api-auth-rolled/src/options/options.md new file mode 100644 index 0000000..b9b17ac --- /dev/null +++ b/docs/api-stack/api/api-auth-rolled/src/options/options.md @@ -0,0 +1,90 @@ +# `options` + + +_(no submodules)_ + + +## Purpose + +Defines the configuration shape accepted by `createRolledAuthAdapter` and +the Zod schema that validates it. Operators wire this from `host.json` or +build it programmatically; everything the rest of the package needs flows +from a single validated `RolledAuthOptions` value, which keeps invariants +(active-key count, prefix shape, TTL positivity) in one place. + +The schema deliberately validates injected functions and the `store` +adapter as `unknown` and then refines them later — Zod cannot verify +function-argument shapes statically, and TypeScript already does that work +at the call boundary. + +## Features + +- Zod schema `RolledAuthOptionsSchema` covering every operator-facing + knob. +- A `superRefine` cross-field invariant that exactly one key is both + `active: true` and non-revoked — keeps sign-time semantics ambiguity-free. +- Stable named defaults (`DEFAULT_COOKIE_NAME`, `DEFAULT_ROUTE_PREFIX`, + TTLs, rotation period, minimum strength score) so consumers can + reference the defaults without re-reading the source. +- Two distinct error codes for failures: `DATABASE_REQUIRED` when `store` + is missing (operator hooked up nothing), `SIGNING_KEY_NOT_CONFIGURED` + for every other schema failure (Zod issues attached as `context`). + +## Usage: Basic + +```ts +import { parseRolledAuthOptions } from "@suaveplan/api-auth-rolled"; + +const opts = parseRolledAuthOptions({ + store: myStore, + keys: [{ kid: "k1", privateJwk, publicJwk, active: true }], + issuer: "https://api.example.com", + audience: "example-frontend", +}); +``` + +## Usage: Advanced + +```ts +import { + DEFAULT_ROTATION_PERIOD_MS, + parseRolledAuthOptions, +} from "@suaveplan/api-auth-rolled"; + +const opts = parseRolledAuthOptions({ + store, + keys, + issuer: "https://api.example.com", + audience: "example-frontend", + routePrefix: "/api/auth", + cookieName: "acme.session", + cookieSameSite: "strict", + cookieSecure: true, + sessionTtlSec: 1800, + refreshTtlSec: 7 * 24 * 60 * 60, + rotationPeriodMs: DEFAULT_ROTATION_PERIOD_MS / 2, + minPasswordStrength: 4, + strength: { async score(pw) { return 4; } }, + breach: { async isBreached() { return false; } }, +}); +``` + +## API Reference + +- `parseRolledAuthOptions(raw): RolledAuthOptions` — throws + `AuthRolledError` on bad input. +- `RolledAuthOptionsSchema` — the Zod schema, re-exported for advanced + consumers that want to layer their own refinements. +- `DEFAULT_*` constants — every operator-facing default exposed as a + named export. + +## Implementation Notes + +The schema is `strictObject` so unknown keys produce a Zod error rather +than silently passing through. The `keys[]` `active` invariant is enforced +in `superRefine` rather than as a `transform` so the invariant message +appears in the validation issue list instead of as a thrown exception +mid-parse. Cross-field invariants that cross the option/store boundary +(e.g. "every kid actually resolves to a JWK") are checked later inside the +session/token-rotator modules so the options layer remains synchronous and +pure. diff --git a/docs/api-stack/api/api-auth-rolled/src/principal-projection/principal-projection.md b/docs/api-stack/api/api-auth-rolled/src/principal-projection/principal-projection.md new file mode 100644 index 0000000..fa71538 --- /dev/null +++ b/docs/api-stack/api/api-auth-rolled/src/principal-projection/principal-projection.md @@ -0,0 +1,73 @@ +# `principal-projection` + + +_(no submodules)_ + + +## Purpose + +Projects the package's internal `UserRow` storage shape onto the abstract +`Principal` contract published by `@suaveplan/api-types`. Keeping the +projection in one place ensures that no storage-specific columns leak +into the principal seen by downstream plugins, and that the four +documented principal fields (`id`, `scopes`, `tenantId?`, `claims`) are +the only surface area authors can rely on. + +The projection is deliberately strict: structurally-invalid rows raise +`AUTH_ROLLED.PRINCIPAL_PROJECTION_FAILED`, surfacing storage-driver bugs +loudly rather than letting malformed data flow into route handlers. + +## Features + +- One-shot pure function — no DB calls, no async, no allocations beyond + the new array of branded `Scope`s. +- Validates every column the projection touches (`id` non-empty string, + `scopes` array of non-empty strings, `claims` plain object). +- Omits `tenantId` from the output `Principal` when the storage row's + value is `null`, matching the optional shape in `Principal`. +- Brands strings as `PrincipalId` / `Scope` / `TenantId` at the boundary + so type narrowing carries through to consumers. + +## Usage: Basic + +```ts +import { projectUserRowToPrincipal } from "@suaveplan/api-auth-rolled"; + +const principal = projectUserRowToPrincipal(row); +console.log(principal.id, principal.scopes); +``` + +## Usage: Advanced + +```ts +import { projectUserRowToPrincipal } from "@suaveplan/api-auth-rolled"; + +function resolveSession(row: UserRow): Principal { + try { + return projectUserRowToPrincipal(row); + } catch (err) { + // Storage adapter returned a malformed row — log + treat as an + // anonymous request rather than surfacing the bug to the client. + log.error({ err }, "principal projection failed"); + throw err; + } +} +``` + +## API Reference + +- `projectUserRowToPrincipal(row: UserRow): Principal` — pure projection. + Throws `AuthRolledError(PRINCIPAL_PROJECTION_FAILED)` on any structural + invariant violation. + +## Implementation Notes + +The projection allocates a fresh `scopes` array rather than spreading the +row's array — this is intentional so that downstream handlers cannot +mutate the source row through the principal reference. `claims` is a +shallow read-only reference so deep-cloning every claim object on every +request stays optional (consumers wanting deep immutability can wrap with +`Object.freeze`). The `tenantId` branding mirrors the contract published +by `@suaveplan/api-tenant-resolver-*` adapters — keeping the brand at the +projection boundary means downstream code that takes a `TenantId` never +needs an unsafe cast. diff --git a/docs/api-stack/api/api-auth-rolled/src/security-schemes/security-schemes.md b/docs/api-stack/api/api-auth-rolled/src/security-schemes/security-schemes.md new file mode 100644 index 0000000..124d93e --- /dev/null +++ b/docs/api-stack/api/api-auth-rolled/src/security-schemes/security-schemes.md @@ -0,0 +1,73 @@ +# `security-schemes` + + +_(no submodules)_ + + +## Purpose + +Contributes OpenAPI 3.1 `securitySchemes` entries describing both +transports the rolled session resolver accepts — `Authorization: Bearer +` and a `Cookie` carrying the same JWT. Keeping the two entries +co-located means a single source of truth describes what the resolver +accepts on the wire; the `api-openapi` emitter (Stage 8.6) walks the +adapter's `securityScheme` slot AND its `.schemes` map so both are +surfaced in the generated document. + +## Features + +- Bearer entry: OpenAPI 3.1 `http` / `bearer` form with `bearerFormat: + "JWT"` — the canonical Bearer-JWT shape consumers expect. +- Cookie entry: `apiKey` / `in: cookie` form whose `name` is the + caller-configured cookie name, so the doc matches the adapter's + runtime behaviour exactly. +- `createRolledSecuritySchemes({ cookieName })` returns a single value + that satisfies the `SecuritySchemeContribution` contract (its `name` + and `scheme` point at the bearer entry) AND exposes both contributions + on `.schemes` — the emitter can pull either or both. + +## Usage: Basic + +```ts +import { createRolledSecuritySchemes } from "@suaveplan/api-auth-rolled"; + +const contribution = createRolledSecuritySchemes({ + cookieName: "suaveplan.session", +}); +``` + +## Usage: Advanced + +```ts +import { + createRolledBearerSecurityScheme, + createRolledCookieSecurityScheme, +} from "@suaveplan/api-auth-rolled"; + +// Multi-resolver host — name the contributions to disambiguate. +const userBearer = createRolledBearerSecurityScheme("userBearer"); +const serviceBearer = createRolledBearerSecurityScheme("serviceBearer"); +const cookie = createRolledCookieSecurityScheme({ + name: "userCookie", + cookieName: "acme.session", +}); +``` + +## API Reference + +- `createRolledBearerSecurityScheme(name?: string): SecuritySchemeContribution` +- `createRolledCookieSecurityScheme({ name?, cookieName }): SecuritySchemeContribution` +- `createRolledSecuritySchemes({ cookieName }): RolledSecurityContribution` + — convenience bundle. + +## Implementation Notes + +The combined `RolledSecurityContribution` is structurally a +`SecuritySchemeContribution` (so old emitters that only read `name` + +`scheme` keep working) but adds a `.schemes` map for emitters aware of +the dual-transport shape. This keeps the contribution drop-in for both +single-transport and dual-transport emitters without forcing every +caller to choose. The cookie scheme's `apiKey/in:cookie` representation +matches OpenAPI 3.1 §4.8.27.4 — there is no first-class cookie-JWT +shape in OAS 3.1 so `apiKey` with the configured name is the canonical +form. diff --git a/docs/api-stack/api/api-auth-rolled/src/session/session.md b/docs/api-stack/api/api-auth-rolled/src/session/session.md new file mode 100644 index 0000000..79061f4 --- /dev/null +++ b/docs/api-stack/api/api-auth-rolled/src/session/session.md @@ -0,0 +1,100 @@ +# `session` + + +_(no submodules)_ + + +## Purpose + +The rolling-JWT session resolver — the keystone of the rolled auth +adapter. Builds a `SessionResolver` (per `@suaveplan/api-auth`) that +parses-and-verifies a JWT extracted from either the `Authorization: +Bearer` header or a configurable cookie, runs the JWT through the +`TokenRotator` to find the verifying JWK by `kid`, projects the matching +user row onto a `Principal`, and returns `null` on every soft failure so +the host's resolver chain can move on to the next adapter. + +The same module exposes `issueToken(userId)` so the future +account-lifecycle provider (deferred to `api-auth-rolled-provider`) can +share a single signing path with the resolver. Keeping issue and verify +co-located means the JWT shape and the rotator wiring stay in lock-step. + +## Features + +- RS256 signing via `@suaveplan/jws` `compactSign` with the rotator's + active JWK; verification via `compactVerify` against the rotator's + retired-or-active JWK matched by `kid`. +- Bearer + cookie extraction in one pass — bearer wins when both are + present so service clients can override a stale cookie. +- Strict JWT-claim validation: `iss`/`aud` exact match, `exp` future, + `iat` not before `users.createdAt`. +- Soft failures (missing token, bad signature, expired, unknown kid) + collapse to `null`; hard failures (storage adapter throws) propagate + as `AuthRolledError`. +- `buildSetCookie` returns a deterministic `Set-Cookie` value with + `HttpOnly`, `Path=/`, `Max-Age`, `SameSite`, `Secure` — used by the + future provider half but published here so the cookie shape lives next + to the cookie parser. + +## Usage: Basic + +```ts +import { createRolledSessionResolver, TokenRotator } from "@suaveplan/api-auth-rolled"; + +const rotator = new TokenRotator({ keys, rotationPeriodMs, clock }); +const resolver = createRolledSessionResolver({ + options, + rotator, + clock, + cookieName: "suaveplan.session", + sessionTtlSec: 3600, +}); + +const principal = await resolver.resolve(req); +``` + +## Usage: Advanced + +```ts +import { createRolledSessionResolver } from "@suaveplan/api-auth-rolled"; + +const resolver = createRolledSessionResolver({ /* ... */ }); + +// Provider half (future) signs new tokens with the same key set as the +// resolver — sharing one path means the rotator's view of the active +// kid is the only source of truth. +const issued = await resolver.issueToken("u_1"); +const setCookie = buildSetCookie({ + name: "suaveplan.session", + value: issued.token, + maxAgeSec: issued.expiresAt - issued.issuedAt, + sameSite: "lax", + secure: true, +}); +``` + +## API Reference + +- `createRolledSessionResolver({ options, rotator, clock, cookieName, sessionTtlSec }) → SessionResolver & { issueToken, verifyToken }` +- `buildSetCookie({ name, value, maxAgeSec, sameSite, secure }) → string` +- `tokenSizeOf(token: string): number` — byte length, used by the + conformance harness to assert tokens stay under the 8 KiB cookie limit. + +## Implementation Notes + +The resolver intentionally returns `null` on every parse/verify failure +rather than throwing — `SessionResolver` chain semantics treat thrown +errors as operator-actionable infrastructure failures, so soft failures +must collapse to `null` to let the chain advance to the next adapter +(typically `api-auth-anonymous`). The two cases where the resolver does +throw are `AuthRolledError(PRINCIPAL_PROJECTION_FAILED)` raised by the +projection step (storage-driver bug) and whatever error the operator's +`store.findUserById` raises (DB connection lost). The session-resolver +chain handles both by surfacing 500 to the client and routing to the +host's audit log. + +The header parse is done manually rather than via `compactDecode` so a +malformed header (e.g. missing `kid`) bypasses the rotator lookup +entirely. The rotator can verify with retired-but-non-revoked keys, so +rotating the active key never invalidates a session mid-lifetime — +operators can rotate without coordinating with active users. diff --git a/docs/api-stack/api/api-auth-rolled/src/token-rotator/token-rotator.md b/docs/api-stack/api/api-auth-rolled/src/token-rotator/token-rotator.md new file mode 100644 index 0000000..3532230 --- /dev/null +++ b/docs/api-stack/api/api-auth-rolled/src/token-rotator/token-rotator.md @@ -0,0 +1,87 @@ +# `token-rotator` + + +_(no submodules)_ + + +## Purpose + +Owns the rotating-keyset state for the rolled session-token resolver. The +active key signs new JWTs; retired-but-non-revoked keys still verify +in-flight tokens so a rotation event never invalidates a session +mid-lifetime. The rotator does NOT generate new key material — that is an +operator-controlled action (HSM, KMS, mounted file) that submits the +replacement set through `setKeys`. This split is deliberate: keeping key +generation out of the adapter means the adapter never holds long-lived +private key material outside of the operator's chosen storage layer. + +## Features + +- Snapshots the keyset atomically (`snapshot()`) — the session module + reads the snapshot, signs with it, and never observes a half-rotated + state. +- Decides when to rotate (`decide()`) based on the active key's age vs + the configured `rotationPeriodMs`. Decision is advisory — the host + schedules the actual rotation cron. +- `setKeys(...)` validates the replacement keyset (exactly one active + + non-revoked) before swapping; throws `KEY_ROTATION_FAILED` if the new + set would leave signing ambiguous. +- `publicJwkFor(kid)` resolves the verifying JWK for any non-revoked kid + — including retired keys — so verification of in-flight tokens works + through the rotation window. + +## Usage: Basic + +```ts +import { TokenRotator } from "@suaveplan/api-auth-rolled"; + +const rotator = new TokenRotator({ + keys, + rotationPeriodMs: 24 * 60 * 60 * 1000, + clock: () => Date.now(), +}); + +const snap = rotator.snapshot(); +const activeJwk = snap.active.privateJwk; +``` + +## Usage: Advanced + +```ts +import { TokenRotator } from "@suaveplan/api-auth-rolled"; + +const rotator = new TokenRotator({ + keys: initialKeys, + rotationPeriodMs: 24 * 60 * 60 * 1000, + clock, +}); + +// Periodic rotator cron: +setInterval(async () => { + const decision = rotator.decide(); + if (!decision.shouldRotate) return; + const next = await fetchKeysFromKms(); // operator-specific + rotator.setKeys(next); +}, 60 * 1000); +``` + +## API Reference + +- `new TokenRotator({ keys, rotationPeriodMs, clock })` — construct. +- `snapshot(): KeySetSnapshot` — atomic read. +- `decide(): RotationDecision` — should we rotate now? +- `setKeys(next: readonly SigningKeyEntry[]): void` — swap keys. +- `publicJwkFor(kid): Record | undefined` — verify-side + lookup. + +## Implementation Notes + +The rotator keeps its `activeSince` timestamp in instance state rather +than reading `keys[i].activatedAt`, so the in-memory rotation timer is +independent of any timestamps the operator stamps on the JWK records. This +means a fresh keyset injected via `setKeys` starts a brand-new rotation +window regardless of when the underlying key material was generated — the +operator's intent ("treat this as the new active key as of now") is the +authoritative signal. The exactly-one-active invariant is enforced both +in `parseRolledAuthOptions` and in `setKeys` so there is no path through +which the rotator can observe an invalid keyset. diff --git a/docs/api-stack/api/api-auth-static-principal/README.md b/docs/api-stack/api/api-auth-static-principal/README.md new file mode 100644 index 0000000..40ca05c --- /dev/null +++ b/docs/api-stack/api/api-auth-static-principal/README.md @@ -0,0 +1,125 @@ +# @suaveplan/api-auth-static-principal — fixed-principal session resolver for @suaveplan/api: returns a configured Principal verbatim on every request. Used in plugin integration tests and the api-plugin-example fixture. + +Fixed-`Principal` session resolver for the `@suaveplan/api` plugin +system. Returns the configured `Principal` verbatim on every request — +no token decoding, no network I/O, no internal state. Used in plugin +integration tests and the `api-plugin-example` fixture, where the goal is to +exercise the entire downstream pipeline (RBAC gate, tenant resolver chain +reading `principal.tenantId`, tenant-scoped DB) with a deterministic +identity carried in config. + + +## Documentation tree + +- [adapter](./src/adapter/adapter.md) — Bundles the static-principal resolver, the (absent) security-scheme contribution, and a pinned `csrf: false` into a sin… + - [adapter](./src/adapter/adapter.md) — Bundles the static-principal resolver, the (absent) security-scheme contribution, and a pinned `csrf: false` into a sin… +- [error-codes](./src/error-codes/error-codes.md) — Defines the `AUTH_STATIC_PRINCIPAL.*` error-code namespace and the `AuthStaticPrincipalError` concrete subclass of `@su… + - [error-codes](./src/error-codes/error-codes.md) — Defines the `AUTH_STATIC_PRINCIPAL.*` error-code namespace and the `AuthStaticPrincipalError` concrete subclass of `@su… +- [factory](./src/factory/create-static-principal-resolver.md) — Constructs a `SessionResolver` from `@suaveplan/api-auth` that returns the configured `Principal` verbatim on every req… + - [create-static-principal-resolver](./src/factory/create-static-principal-resolver.md) — Constructs a `SessionResolver` from `@suaveplan/api-auth` that returns the configured `Principal` verbatim on every req… +- [options](./src/options/options.md) — Owns the runtime contract between the test harness call site and the resolver factory. The schema validates both the ou… + - [options](./src/options/options.md) — Owns the runtime contract between the test harness call site and the resolver factory. The schema validates both the ou… +- [security-scheme](./src/security-scheme/security-scheme.md) — Provides the per-adapter `SecuritySchemeContribution` slot of `AuthAdapter`. The static-principal adapter is a test-onl… + - [security-scheme](./src/security-scheme/security-scheme.md) — Provides the per-adapter `SecuritySchemeContribution` slot of `AuthAdapter`. The static-principal adapter is a test-onl… + + +## Why does this exist? + +Per the API foundation design doc §13.2, the testing kit needs an auth +adapter that supplies a fixed `Principal` without any token decoding. The +§13.2 example uses it directly: + +```ts +adapters: { + "auth.session": { + kind: "static-principal", + principal: { id: "u1", scopes: ["billing:write"], tenantId: "acme" }, + }, +} +``` + +Tests exercise the whole pipeline — RBAC, tenant resolution, tenant-scoped +DB — with a deterministic principal in config. No mocks, no JWKS setup, no +token signing. + +## Surface + +| Subpath | Export | +| -------------- | --------------------------------------------------------------------------------------- | +| `./resolver` | `createStaticPrincipalResolver(opts): SessionResolver` | +| `./adapter` | `createStaticPrincipalAdapter(opts): AuthAdapter` | +| `./error-codes`| `AUTH_STATIC_PRINCIPAL_CODES`, `AuthStaticPrincipalError`, `AuthStaticPrincipalErrorCode` | + +The root barrel re-exports the resolver, adapter, error codes, options +schema (`StaticPrincipalResolverOptionsSchema` / +`parseStaticPrincipalResolverOptions`), and the empty +`staticPrincipalSecurityScheme()` contribution. + +## Usage + +```ts +import { createStaticPrincipalAdapter } from "@suaveplan/api-auth-static-principal/adapter"; + +const adapter = createStaticPrincipalAdapter({ + principal: { + id: "u1", + scopes: ["billing:write"], + tenantId: "acme", + claims: { sub: "u1" }, + }, +}); + +host.registerAuth(adapter); +// every request now produces `principal === { id: "u1", ... }`. +``` + +Skip auth on selected paths to test `publicRoutes` behaviour without +rewiring the adapter chain: + +```ts +const adapter = createStaticPrincipalAdapter({ + principal: { id: "u1", scopes: [], claims: {} }, + nullForPaths: ["/healthz", "/webhooks/*"], + applyTo: (req) => !req.headers.has("x-skip-auth"), +}); +``` + +## Conformance + +The resolver passes `runAuthSessionConformance` from +`@suaveplan/api-auth/testing` in seeded-principal mode. See +`src/factory/create-static-principal-resolver.spec-conformance.test.ts` and +`tests/conformance/api-auth.test.ts`. + +## Errors + +`AUTH_STATIC_PRINCIPAL.INVALID_OPTIONS` — outer options bag failed Zod +validation (wrong shape, missing required fields, unknown top-level keys). + +`AUTH_STATIC_PRINCIPAL.INVALID_PRINCIPAL` — the supplied `principal` field +is malformed (missing `id`, non-string `id`, non-array `scopes`, unknown +keys inside `principal`, …). + +Both fire synchronously at construction time. The resolver itself never +throws at request time. + +## Stage-5 wiring (forward-looking) + +When `api-host/testing` ships its Stage-5 `createTestHost` surface, this +adapter is registered in the adapter table under +`kind: "static-principal"`, so tests will declare it inline: + +```ts +const host = createTestHost({ + adapters: { + "auth.session": { + kind: "static-principal", + principal: { id: "u1", scopes: ["billing:write"], tenantId: "acme" }, + }, + }, +}); +``` + +Until then, callers wire the adapter directly via +`createStaticPrincipalAdapter()` as shown above. + diff --git a/docs/api-stack/api/api-auth-static-principal/src/adapter/adapter.md b/docs/api-stack/api/api-auth-static-principal/src/adapter/adapter.md new file mode 100644 index 0000000..34849a3 --- /dev/null +++ b/docs/api-stack/api/api-auth-static-principal/src/adapter/adapter.md @@ -0,0 +1,81 @@ +# `adapter` — composite `AuthAdapter` factory + + +_(no submodules)_ + + +## Purpose + +Bundles the static-principal resolver, the (absent) security-scheme +contribution, and a pinned `csrf: false` into a single `AuthAdapter` value. +This is the call-site shape for the canonical "test host with a known +Principal" wiring — `host.registerAuth(createStaticPrincipalAdapter({...}))` +gives the test the entire auth pipeline without further plumbing. + +The factory delegates construction-time validation to +`createStaticPrincipalResolver`, so misconfigured options surface as the +same typed `AuthStaticPrincipalError` they do at the resolver level. The +adapter holds no state of its own. + +## Features + +- Single-call construction of the resolver + scheme + csrf triple. +- Pins `csrf: false` because the static-principal layer has no session + cookie to forge against — every request carries the configured Principal + by construction. +- `securityScheme` omitted (matching `api-auth-anonymous` topology) so the + generated OpenAPI document doesn't advertise a real auth flow for + routes wired to this adapter. + +## Usage: Basic + +```ts +import { createStaticPrincipalAdapter } from "@suaveplan/api-auth-static-principal/adapter"; + +const adapter = createStaticPrincipalAdapter({ + principal: { + id: "u1", + scopes: ["billing:write"], + tenantId: "acme", + claims: { sub: "u1" }, + }, +}); + +host.registerAuth(adapter); +``` + +## Usage: Advanced + +Compose with `applyTo` / `nullForPaths` to skip auth on test-only routes: + +```ts +import { createStaticPrincipalAdapter } from "@suaveplan/api-auth-static-principal/adapter"; + +const adapter = createStaticPrincipalAdapter({ + principal: { id: "u1", scopes: [], claims: {} }, + nullForPaths: ["/healthz", "/webhooks/*"], +}); + +// host.registerAuth(adapter) — /healthz and /webhooks/* resolve to null; +// every other route gets the configured Principal. +``` + +## API Reference + +| Symbol | Kind | Description | +| ------------------------------------- | -------- | ---------------------------------------------------------- | +| `createStaticPrincipalAdapter(opts)` | function | Returns `AuthAdapter` composed from the four building blocks. | + +## Implementation Notes + +`csrf: false` is the load-bearing pin: a static-principal host can't honour +a real CSRF check (there's no session cookie carrying a synchronizer +token), so the host should skip CSRF entirely for routes wired to this +adapter. If a downstream test needs CSRF behaviour exercised in isolation, +compose with a separate adapter that pins `csrf: true` and let the host's +adapter-chain merge rule pick the safer value (the host's policy is to use +the strictest `csrf` flag in the chain). + +`validateAuthAdapter` accepts this adapter's shape (security scheme absent; +csrf set to a boolean). The package's adapter test asserts the validation +contract is satisfied without re-implementing the validator. diff --git a/docs/api-stack/api/api-auth-static-principal/src/error-codes/error-codes.md b/docs/api-stack/api/api-auth-static-principal/src/error-codes/error-codes.md new file mode 100644 index 0000000..4f2df25 --- /dev/null +++ b/docs/api-stack/api/api-auth-static-principal/src/error-codes/error-codes.md @@ -0,0 +1,87 @@ +# `error-codes` — stable code registry for the static-principal adapter + + +_(no submodules)_ + + +## Purpose + +Defines the `AUTH_STATIC_PRINCIPAL.*` error-code namespace and the +`AuthStaticPrincipalError` concrete subclass of +`@suaveplan/error/SuaveplanError`. This module is the single source of truth +for every failure code the package can surface to a caller — wiring this +registry into the host's error envelope is how a malformed test-time +Principal configuration reaches the developer rather than silently producing a +broken auth chain. + +Codes are produced via `defineCodes("AUTH_STATIC_PRINCIPAL", [...])` so the +full literal value is e.g. `"AUTH_STATIC_PRINCIPAL.INVALID_OPTIONS"`. The +class augments the base error with `authStaticPrincipalCode`, providing a +narrowed code property when consumers have already discriminated by +`instanceof`. + +## Features + +- Stable, frozen `AUTH_STATIC_PRINCIPAL_CODES` map built via `defineCodes` so + the prefix can't drift. +- Discriminated-union friendly: `AuthStaticPrincipalErrorCode` is a literal + union over the registry entries. +- Carries arbitrary `context` (Zod issues, the offending field path) via the + base `SuaveplanError` options bag. + +## Usage: Basic + +```ts +import { + AUTH_STATIC_PRINCIPAL_CODES, + AuthStaticPrincipalError, +} from "@suaveplan/api-auth-static-principal/error-codes"; + +throw new AuthStaticPrincipalError( + AUTH_STATIC_PRINCIPAL_CODES.INVALID_OPTIONS, + "createStaticPrincipalResolver: options failed schema validation" +); +``` + +## Usage: Advanced + +Attach Zod issues so the caller can pinpoint the bad field without re-running +validation: + +```ts +import { + AUTH_STATIC_PRINCIPAL_CODES, + AuthStaticPrincipalError, +} from "@suaveplan/api-auth-static-principal/error-codes"; +import z from "zod"; + +const parsed = OptionsSchema.safeParse(input); +if (!parsed.success) { + throw new AuthStaticPrincipalError( + AUTH_STATIC_PRINCIPAL_CODES.INVALID_PRINCIPAL, + "principal failed schema validation", + { context: { issues: parsed.error.issues } } + ); +} +``` + +## API Reference + +| Symbol | Kind | Description | +| ----------------------------------- | -------- | ------------------------------------------------------------------------ | +| `AUTH_STATIC_PRINCIPAL_CODES` | constant | Frozen map of code constants. Keys are the short names; values are full. | +| `AuthStaticPrincipalErrorCode` | type | Literal union over the registry values. | +| `AuthStaticPrincipalError` | class | `SuaveplanError` subclass typed against the code registry. | + +## Implementation Notes + +`defineCodes` joins the prefix with each suffix using a single `.` so the +resulting strings match the host's structured-log code field. The class +stores the code twice — once in the inherited `code` slot and once in the +narrower `authStaticPrincipalCode` slot — so callers that already narrowed by +`instanceof` get a precisely-typed code field without a follow-up `as`. + +The package's static-principal resolver never throws at request time; both +codes are construction-time only. This is deliberate — every per-request +failure for fixed-principal tests should manifest in the test assertion, not +in the auth pipeline. diff --git a/docs/api-stack/api/api-auth-static-principal/src/factory/create-static-principal-resolver.md b/docs/api-stack/api/api-auth-static-principal/src/factory/create-static-principal-resolver.md new file mode 100644 index 0000000..ed43373 --- /dev/null +++ b/docs/api-stack/api/api-auth-static-principal/src/factory/create-static-principal-resolver.md @@ -0,0 +1,99 @@ +# `factory/create-static-principal-resolver` — fixed-Principal resolver + + +_(no submodules)_ + + +## Purpose + +Constructs a `SessionResolver` from `@suaveplan/api-auth` that returns the +configured `Principal` verbatim on every request — no token decoding, no +JWKS, no I/O. This is the workhorse adapter for plugin integration tests, +the `api-plugin-example` fixture, and any environment where the goal is to +exercise the downstream pipeline (RBAC gate, tenant resolver chain reading +`principal.tenantId`, tenant-scoped DB) with a deterministic identity carried +in config. + +The factory consumes options previously validated by the `options` module so +construction is total: every misuse maps to either +`AUTH_STATIC_PRINCIPAL.INVALID_OPTIONS` or `AUTH_STATIC_PRINCIPAL.INVALID_PRINCIPAL` +and surfaces synchronously at construction time. The resolver itself never +throws at request time. + +## Features + +- Defensive clone on every `resolve()` — callers cannot mutate one returned + Principal and observe the change on subsequent calls. +- `applyTo(req)` predicate for arbitrary "return null for this request" + rules. +- `nullForPaths` suffix-glob list (`/webhooks/*`) and exact-match patterns + for the most common public-route test setup. +- Idempotent no-op `dispose()` matching the `SessionResolver` contract. +- Returned objects are frozen (top-level + `scopes` + `claims`) to make + attempted mutations fail loudly in strict mode. + +## Usage: Basic + +```ts +import { createStaticPrincipalResolver } from "@suaveplan/api-auth-static-principal/resolver"; + +const resolver = createStaticPrincipalResolver({ + principal: { + id: "u1", + scopes: ["billing:write"], + tenantId: "acme", + claims: { sub: "u1" }, + }, +}); + +const principal = await resolver.resolve( + new Request("https://example.test/api/billing/invoices") +); +// principal.id === "u1" +``` + +## Usage: Advanced + +Combine `applyTo` and `nullForPaths` to model a mixed-route test surface: + +```ts +import { createStaticPrincipalResolver } from "@suaveplan/api-auth-static-principal/resolver"; + +const resolver = createStaticPrincipalResolver({ + principal: { + id: "u1", + scopes: ["billing:write", "billing:read"], + tenantId: "acme", + claims: { sub: "u1" }, + }, + nullForPaths: ["/webhooks/*", "/healthz"], + applyTo: (req) => !req.headers.has("x-skip-auth"), +}); + +// /healthz and /webhooks/stripe resolve to null. +// Requests with the `x-skip-auth` header resolve to null. +// Everything else returns the configured Principal. +``` + +## API Reference + +| Symbol | Kind | Description | +| ----------------------------------- | -------- | ------------------------------------------------------------------ | +| `createStaticPrincipalResolver(o)` | function | Returns a `SessionResolver` carrying `o.principal` on every match. | + +## Implementation Notes + +The clone strategy is: deep-freeze a single template at construction, then +clone-from-template per `resolve()`. The per-call clone is unavoidable — +otherwise two callers each freezing the returned object would freeze each +other's state. The per-call clone copies the top level plus `scopes` (array +spread) and `claims` (object spread); deeper structures inside `claims` are +not cloned. This matches the `Principal` contract: `claims` values are +`unknown`, so the package can't responsibly deep-clone them. Callers passing +mutable nested claims values are responsible for not mutating them in-place. + +`pathMatches` accepts only exact-match and a single suffix glob (`/foo/*`) +on purpose — richer matching belongs in `applyTo`. The trailing slash is +preserved when stripping the `*` so `/foo/*` matches `/foo/x` but not +`/foox`. The pattern dialect is documented on the spec and exercised by the +test file. diff --git a/docs/api-stack/api/api-auth-static-principal/src/options/options.md b/docs/api-stack/api/api-auth-static-principal/src/options/options.md new file mode 100644 index 0000000..0105811 --- /dev/null +++ b/docs/api-stack/api/api-auth-static-principal/src/options/options.md @@ -0,0 +1,82 @@ +# `options` — Zod-validated options for `createStaticPrincipalResolver` + + +_(no submodules)_ + + +## Purpose + +Owns the runtime contract between the test harness call site and the +resolver factory. The schema validates both the outer options bag +(`{ principal, nullForPaths?, applyTo? }`) and the nested `Principal` shape +(non-empty `id`, readonly `scopes`, optional `tenantId`, default-`{}` +`claims`). On failure it raises a typed `AuthStaticPrincipalError` carrying +the originating Zod issues — splitting between `INVALID_OPTIONS` (anything +outside `principal`) and `INVALID_PRINCIPAL` (anything inside it). + +This module is the only place the package touches Zod at runtime. Keeping it +isolated lets the resolver factory stay a thin three-line function and lets +the conformance test target the resolver behaviour without invoking schema +side-effects. + +## Features + +- Strict outer schema — unknown keys at the top level reject with + `INVALID_OPTIONS`. +- Discriminated error codes: `principal` issues map to `INVALID_PRINCIPAL`; + everything else maps to `INVALID_OPTIONS`. +- Pre-flight type check rejects non-object inputs with `INVALID_OPTIONS` + before Zod sees them — a cleaner message than the Zod default for `null` / + arrays. +- `claims` defaults to `{}` so callers don't have to write + `claims: {}` for the common case. + +## Usage: Basic + +```ts +import { parseStaticPrincipalResolverOptions } from "@suaveplan/api-auth-static-principal/resolver"; + +const opts = parseStaticPrincipalResolverOptions({ + principal: { + id: "u_1", + scopes: ["billing:write"], + tenantId: "acme", + claims: { email: "user@acme.test" }, + }, +}); +``` + +## Usage: Advanced + +Validate options that include both `applyTo` and `nullForPaths`: + +```ts +import { parseStaticPrincipalResolverOptions } from "@suaveplan/api-auth-static-principal/resolver"; + +const opts = parseStaticPrincipalResolverOptions({ + principal: { id: "u_1", scopes: [], claims: {} }, + nullForPaths: ["/webhooks/*", "/healthz"], + applyTo: (req) => !req.headers.has("x-skip-auth"), +}); +``` + +## API Reference + +| Symbol | Kind | Description | +| -------------------------------------------- | -------- | ----------------------------------------------------------------- | +| `StaticPrincipalResolverOptionsSchema` | Zod | Strict object schema for the outer bag. | +| `parseStaticPrincipalResolverOptions(raw)` | function | Returns the validated options or throws `AuthStaticPrincipalError`. | + +## Implementation Notes + +The pre-flight `typeof`/`Array.isArray` check lets the function return a +single canonical error for "you handed me something that isn't an object" — +Zod's own behaviour on `null` is to emit +`{ code: "invalid_type", expected: "object" }`, which is correct but verbose. +Splitting into a pre-flight + Zod pass is one extra branch but keeps the +caller-facing failure message stable. + +`claims` is recorded as `z.record(z.unknown())` so any free-form JWT/claims +payload validates. Coercing to readonly happens at the TypeScript boundary +(`StaticPrincipalResolverOptions`), not in Zod — Zod's `.readonly()` is +type-level only and would re-wrap arrays at runtime unnecessarily. diff --git a/docs/api-stack/api/api-auth-static-principal/src/security-scheme/security-scheme.md b/docs/api-stack/api/api-auth-static-principal/src/security-scheme/security-scheme.md new file mode 100644 index 0000000..413de16 --- /dev/null +++ b/docs/api-stack/api/api-auth-static-principal/src/security-scheme/security-scheme.md @@ -0,0 +1,75 @@ +# `security-scheme` — OpenAPI contribution for the static-principal adapter + + +_(no submodules)_ + + +## Purpose + +Provides the per-adapter `SecuritySchemeContribution` slot of +`AuthAdapter`. The static-principal adapter is a test-only construct: there +is no real authentication flow to document on routes that use it. This +module returns `undefined` deliberately — which `validateAuthAdapter` from +`@suaveplan/api-auth` permits — so the generated OpenAPI document emits no +security entry for routes under this adapter, mirroring how the anonymous +tail adapter is treated. + +Wrapping the absence in a function gives the package a symmetric surface +with adapters that compute their contribution dynamically, and gives the +test suite a callable to target for the "intentionally absent" assertion. + +## Features + +- Returns `undefined` so the host omits a `security` entry on routes wired + to this adapter. +- Permitted by `validateAuthAdapter` (the anonymous-style topology). +- Callable surface for symmetry with adapters that compute their scheme. + +## Usage: Basic + +```ts +import { staticPrincipalSecurityScheme } from "@suaveplan/api-auth-static-principal/adapter"; +import type { AuthAdapter } from "@suaveplan/api-auth"; + +const adapter: AuthAdapter = { + resolver, + securityScheme: staticPrincipalSecurityScheme(), + csrf: false, +}; +``` + +## Usage: Advanced + +When composing static-principal with another adapter that supplies a real +scheme, drop this contribution and use the other adapter's scheme in the +composite — the host requires only one to be present per route. The +function still acts as documentation that the static-principal layer +contributes nothing of its own: + +```ts +import { staticPrincipalSecurityScheme } from "@suaveplan/api-auth-static-principal/adapter"; + +if (staticPrincipalSecurityScheme() !== undefined) { + // unreachable in this version — the function is documented to return + // undefined. Tests assert this invariant. +} +``` + +## API Reference + +| Symbol | Kind | Description | +| ----------------------------------- | -------- | ------------------------------------------------ | +| `staticPrincipalSecurityScheme()` | function | Returns `undefined` — no OpenAPI contribution. | + +## Implementation Notes + +`validateAuthAdapter` treats `securityScheme: undefined` as a permitted +topology (the "no auth configured" path used by `api-auth-anonymous`). The +generated OpenAPI document omits a `security` array on routes wired to an +adapter that omits the scheme; combined with the host's `publicRoutes` +decision, this matches the runtime behaviour of the static-principal +adapter in tests. + +Changing this to return a real scheme in a future version would be a +breaking change for downstream consumers' OpenAPI snapshots; treat the +"returns undefined" behaviour as a load-bearing contract. diff --git a/docs/api-stack/api/api-auth/README.md b/docs/api-stack/api/api-auth/README.md new file mode 100644 index 0000000..d8bb3bf --- /dev/null +++ b/docs/api-stack/api/api-auth/README.md @@ -0,0 +1,109 @@ +# @suaveplan/api-auth - Abstract session-resolver contract for the Suaveplan API plugin system. Defines the SessionResolver interface (Request → Principal | null), SessionResolverChain (ordered, first-match-wins, fail-closed-on-throw), SecuritySchemeContribution (OpenAPI emission metadata), CsrfPolicy default rules, the composite AuthAdapter, the AUTH_CODES registry, and a runAuthSessionConformance harness reused by every concrete resolver in Stages 4/6/8. + +**$2** for the Suaveplan API plugin system. Defines +the abstract session-resolver shape (`Request → Principal | null`) used by the +host on every request, plus the first-match-wins runner, the OpenAPI +security-scheme contribution, the default CSRF policy, the composite +`AuthAdapter`, and the conformance harness every concrete resolver +implementation passes. + +This package is **session resolution only** — account lifecycle (login, +register, oauth callback, password reset) lives in the separate +`@suaveplan/api-auth-provider` package per design doc §2.3. + + +## Documentation tree + +- [capability-id](./src/capability-id/capability-id.md) — Pins this package's `CapabilityId` contribution as a stand-alone literal type plus runtime constant. The `CapabilityId`… + - [capability-id](./src/capability-id/capability-id.md) — Pins this package's `CapabilityId` contribution as a stand-alone literal type plus runtime constant. The `CapabilityId`… +- [chain](./src/chain/chain.md) — Ordered, first-match-wins runtime over an array of `SessionResolver`s. The chain is the integration point at design-doc… + - [chain](./src/chain/chain.md) — Ordered, first-match-wins runtime over an array of `SessionResolver`s. The chain is the integration point at design-doc… +- [csrf-policy](./src/csrf-policy/csrf-policy.md) — Exposes a single pure predicate, `CsrfPolicy.requiresCsrf(scheme)`, that defaults CSRF protection ON for any cookie-bas… + - [csrf-policy](./src/csrf-policy/csrf-policy.md) — Exposes a single pure predicate, `CsrfPolicy.requiresCsrf(scheme)`, that defaults CSRF protection ON for any cookie-bas… +- [error-codes](./src/error-codes/error-codes.md) — Defines the stable, namespaced error-code registry for the `@suaveplan/api-auth` package and the concrete `AuthError` c… + - [error-codes](./src/error-codes/error-codes.md) — Defines the stable, namespaced error-code registry for the `@suaveplan/api-auth` package and the concrete `AuthError` c… +- [resolver](./src/resolver/resolver.md) — `SessionResolver` is the abstract per-request session-resolver shape that every concrete adapter in Stages 4/6/8 (`api-… + - [resolver](./src/resolver/resolver.md) — `SessionResolver` is the abstract per-request session-resolver shape that every concrete adapter in Stages 4/6/8 (`api-… +- [security-scheme](./src/security-scheme/security-scheme.md) — Defines the shape every concrete `SessionResolver` MUST contribute so the `api-openapi` package can emit the right `com… + - [security-scheme](./src/security-scheme/security-scheme.md) — Defines the shape every concrete `SessionResolver` MUST contribute so the `api-openapi` package can emit the right `com… +- [session-adapter](./src/session-adapter/session-adapter.md) — `AuthAdapter` is the composite shape every concrete session-auth adapter exports — pairing the per-request `SessionReso… + - [session-adapter](./src/session-adapter/session-adapter.md) — `AuthAdapter` is the composite shape every concrete session-auth adapter exports — pairing the per-request `SessionReso… +- [testing](./src/testing/conformance.md) — A reusable Vitest `describe(...)` block every concrete `SessionResolver` must pass before publishing. The harness cover… + - [conformance](./src/testing/conformance.md) — A reusable Vitest `describe(...)` block every concrete `SessionResolver` must pass before publishing. The harness cover… + + +## What's inside + +| Module | Subpath | Purpose | +|-------------------------------|----------------------------------------|---------------------------------------------------------------| +| `SessionResolver` interface | `@suaveplan/api-auth/resolver` | Abstract `resolve(req) → Principal \| null` + `dispose`. | +| `SessionResolverChain` runner | `@suaveplan/api-auth/chain` | Ordered first-match-wins; fail-closed-on-throw by default. | +| Security-scheme contract | `@suaveplan/api-auth/security-scheme` | Zod-validated OpenAPI security-scheme metadata. | +| CSRF policy default | `@suaveplan/api-auth/csrf-policy` | Cookie schemes → ON; bearer / oauth2 / OIDC → OFF. | +| Composite `AuthAdapter` | `@suaveplan/api-auth/session-adapter` | `{ resolver, securityScheme, csrf? }` registration shape. | +| `auth.session` capability id | `@suaveplan/api-auth/capability-id` | Re-export of `"auth.session"` with type-level assertion. | +| `AUTH_CODES` registry | `@suaveplan/api-auth/error-codes` | Frozen `AUTH.*` error-code registry + `AuthError` class. | +| Conformance harness | `@suaveplan/api-auth/testing` | `runAuthSessionConformance(spec)` for concrete resolvers. | + +## Co-located documentation + +Each module ships a sibling `.md`: + +- [`src/resolver/resolver.md`](src/resolver/resolver.md) +- [`src/chain/chain.md`](src/chain/chain.md) +- [`src/security-scheme/security-scheme.md`](src/security-scheme/security-scheme.md) +- [`src/csrf-policy/csrf-policy.md`](src/csrf-policy/csrf-policy.md) +- [`src/session-adapter/session-adapter.md`](src/session-adapter/session-adapter.md) +- [`src/capability-id/capability-id.md`](src/capability-id/capability-id.md) +- [`src/error-codes/error-codes.md`](src/error-codes/error-codes.md) +- [`src/testing/conformance.md`](src/testing/conformance.md) + +## Quick example + +```ts +import { SessionResolverChain } from "@suaveplan/api-auth/chain"; +import { validateAuthAdapter } from "@suaveplan/api-auth/session-adapter"; +import type { SessionResolver } from "@suaveplan/api-auth/resolver"; + +declare const jwt: SessionResolver; +declare const staticBearer: SessionResolver; + +const jwtAdapter = validateAuthAdapter({ + resolver: jwt, + securityScheme: { + name: "bearerAuth", + scheme: { type: "http", scheme: "bearer", bearerFormat: "JWT" }, + }, +}); +const bearerAdapter = validateAuthAdapter({ + resolver: staticBearer, + securityScheme: { + name: "staticBearer", + scheme: { type: "http", scheme: "bearer" }, + }, +}); + +const chain = new SessionResolverChain([ + jwtAdapter.resolver, + bearerAdapter.resolver, +]); + +const principal = await chain.resolve(new Request("https://example.test")); +``` + +## Versioning + +1.0`. Graduates to `1.0.0` when the Stage 1 +contract bundle (`api-types`, `api-auth`, `api-tenant-resolver`, +`api-secrets`, `api-db-adapter`) all reach 1.0. + +## Dependencies + +| Dep | Why | +|---------------------------|------------------------------------------------------| +| `@suaveplan/api-types` | `Principal`, `CapabilityId`. | +| `@suaveplan/error` | `SuaveplanError`, `defineCodes`. | +| `@suaveplan/types` | Cross-package contracts (logger, clock, etc.). | +| `tslib` | TypeScript runtime helpers (catalog). | +| `zod` | Boundary validation for security-scheme contributions. | + diff --git a/docs/api-stack/api/api-auth/src/capability-id/capability-id.md b/docs/api-stack/api/api-auth/src/capability-id/capability-id.md new file mode 100644 index 0000000..a3d2f49 --- /dev/null +++ b/docs/api-stack/api/api-auth/src/capability-id/capability-id.md @@ -0,0 +1,85 @@ +# `capability-id` — `"auth.session"` contribution + + +_(no submodules)_ + + +## Purpose + +Pins this package's `CapabilityId` contribution as a stand-alone literal type +plus runtime constant. The `CapabilityId` union in +`@suaveplan/api-types/capabilities` already enumerates `"auth.session"` +directly; this module ties the api-auth package to that identifier so any +future rename surfaces here first as a build break. + +Exporting the runtime literal as `AUTH_SESSION_CAPABILITY_ID` lets plugin +manifests declare `requires: [AUTH_SESSION_CAPABILITY_ID] as const` without +hard-coding the string at the manifest site — refactor-safe and centrally +documented. + +## Features + +- Compile-time `const _assignable: CapabilityId = AUTH_SESSION_CAPABILITY_ID` + asserts membership at build time. If `api-types` ever drops the token, this + package fails to type-check rather than silently regressing. +- Type and value are exported together so the consumer can pick the form that + fits the call site without re-stringifying. + +## Usage: Basic + +```ts +import { AUTH_SESSION_CAPABILITY_ID } from "@suaveplan/api-auth/capability-id"; + +const requires = [AUTH_SESSION_CAPABILITY_ID] as const; +``` + +## Usage: Advanced + +Use the literal type to constrain a manifest builder helper: + +```ts +import { + AUTH_SESSION_CAPABILITY_ID, + type AuthSessionCapabilityId, +} from "@suaveplan/api-auth/capability-id"; +import type { CapabilityId } from "@suaveplan/api-types/capabilities"; + +function manifestRequires(req: T): T { + return req; +} + +const requires = manifestRequires([ + AUTH_SESSION_CAPABILITY_ID, + "logger", +] satisfies readonly (AuthSessionCapabilityId | "logger")[]); +``` + +## API Reference + +| Symbol | Kind | Description | +|---------------------------------|------|----------------------------------------------| +| `AuthSessionCapabilityId` | type | The literal `"auth.session"`. | +| `AUTH_SESSION_CAPABILITY_ID` | const| `"auth.session"` runtime value. | + +## Implementation Notes + +- The `void _assignable` keeps the assignment from being tree-shaken; without + it Rollup MAY drop the line and the build-time assertion silently regresses + to no-op. +- This module is import-time-only — no behaviour at runtime beyond the + string literal binding. +- The literal is exported as both a `type` and a runtime `const` deliberately: + consumers that build manifests imperatively want the runtime value; consumers + that constrain compile-time-only structures (a `definePlugin` builder, for + example) want the literal type. Re-stringifying `"auth.session"` at the + consumer side would defeat the purpose of having the package central. +- The pairing with `@suaveplan/api-types/capabilities` is deliberately + one-directional. `api-types` is the source of truth for the closed union; + this package only re-asserts membership and binds the runtime value. If a + future change wanted to flip the relationship — have api-auth contribute via + declaration merging instead — that would require relaxing the `CapabilityId` + union in api-types to be `open` (i.e. `string & { brand }`), which is a + larger contract change documented as out-of-scope here. +- The runtime constant uses a type annotation rather than `as const`: the + annotation makes the assignable check above explicit, and `as const` would + widen any future enum-style rewrite. diff --git a/docs/api-stack/api/api-auth/src/chain/chain.md b/docs/api-stack/api/api-auth/src/chain/chain.md new file mode 100644 index 0000000..5794c23 --- /dev/null +++ b/docs/api-stack/api/api-auth/src/chain/chain.md @@ -0,0 +1,89 @@ +# `chain` — `SessionResolverChain` + + +_(no submodules)_ + + +## Purpose + +Ordered, first-match-wins runtime over an array of `SessionResolver`s. The +chain is the integration point at design-doc §6 step 3: the host's per-request +pipeline calls `chain.resolve(req)` exactly once and routes the result into the +`RequestContext.principal` slot (`publicRoutes` decides 401 vs `null`). + +The chain owns three orthogonal contracts that are easy to get wrong if every +adapter re-implements them: (1) iteration order — first non-null wins, no +later resolver is invoked; (2) fail-closed throw semantics — a resolver +exception surfaces `AUTH.RESOLVER_THREW` and short-circuits the chain, with an +opt-in `continueOnThrow` escape hatch documented for SaaS-provider flakiness; +(3) empty-chain rejection — `new SessionResolverChain([])` throws +`AUTH.CHAIN_EMPTY` at construction so deployment misconfiguration cannot mask +itself as "no resolvers, every request 401s." + +## Features + +- Class form implements `SessionResolver` itself — the chain can be nested + inside another chain, used as the host's only resolver, or composed with + middleware identically. +- Idempotent `dispose()` propagates to every wrapped resolver. +- Cause-chain propagation via `AuthError`'s `cause` option; the index of the + throwing resolver is recorded in `context.resolverIndex`. + +## Usage: Basic + +```ts +import { SessionResolverChain } from "@suaveplan/api-auth/chain"; +import type { SessionResolver } from "@suaveplan/api-auth/resolver"; + +declare const jwtResolver: SessionResolver; +declare const bearerStaticResolver: SessionResolver; + +const chain = new SessionResolverChain([jwtResolver, bearerStaticResolver]); + +const principal = await chain.resolve(new Request("https://example.test")); +``` + +## Usage: Advanced + +Enable `continueOnThrow` for a deployment that fronts an intentionally flaky +SaaS auth upstream — the chain logs the cause via the `AuthError` it would +have thrown, but keeps moving to the static-bearer fallback resolver: + +```ts +import { SessionResolverChain } from "@suaveplan/api-auth/chain"; +import type { SessionResolver } from "@suaveplan/api-auth/resolver"; + +declare const saasJwtResolver: SessionResolver; +declare const staticBearerResolver: SessionResolver; + +const chain = new SessionResolverChain( + [saasJwtResolver, staticBearerResolver], + { continueOnThrow: true }, +); + +const req = new Request("https://example.test/api/orders", { + headers: { authorization: "Bearer st_ops_token" }, +}); + +const principal = await chain.resolve(req); // may come from staticBearerResolver +``` + +## API Reference + +| Symbol | Kind | Description | +|---------------------------------|--------|------------------------------------------------------------| +| `SessionResolverChain` | class | `new(resolvers, options?)`; implements `SessionResolver`. | +| `SessionResolverChainOptions` | type | `{ continueOnThrow?: boolean }`. | + +## Implementation Notes + +- The chain iterates synchronously over `this.resolvers` and awaits each + resolver in turn — concurrent resolution is intentionally NOT offered. + Concurrency would change the "first match wins" semantics into "first to + return wins," producing a non-deterministic principal selection when two + resolvers both recognise the request. +- The throw-handling branch records the resolver index but NOT the resolver + identity — concrete adapters MAY redact stack traces, and the chain has no + inspection contract on its members beyond `resolve` + `dispose`. +- `dispose()` is idempotent via a `disposed` flag; the conformance harness + calls it twice and asserts no throw. diff --git a/docs/api-stack/api/api-auth/src/csrf-policy/csrf-policy.md b/docs/api-stack/api/api-auth/src/csrf-policy/csrf-policy.md new file mode 100644 index 0000000..b027b2e --- /dev/null +++ b/docs/api-stack/api/api-auth/src/csrf-policy/csrf-policy.md @@ -0,0 +1,90 @@ +# `csrf-policy` — `CsrfPolicy.requiresCsrf` + + +_(no submodules)_ + + +## Purpose + +Exposes a single pure predicate, `CsrfPolicy.requiresCsrf(scheme)`, that +defaults CSRF protection ON for any cookie-based scheme and OFF for any scheme +where the caller must actively attach the credential. This default codifies the +design-doc §6 rule "Cookie-based auth adapters trigger CSRF verification" so +every concrete adapter inherits the right behaviour without restating it. + +The package exposes only the default; the host (`api-host`) applies per-route +`csrf: false` overrides on top. Keeping the default and the override separate +means a route-level opt-out is always auditable as an explicit decision in the +manifest, never a side-effect of which adapter happened to be wired. + +## Features + +- Pure function — no side effects, no module-load cost. +- Frozen container object so test code can `expect(CsrfPolicy)` reliably and + consumers cannot monkey-patch the predicate. +- Total over the `OpenApiSecurityScheme` discriminated union — no `default` + branch means an added scheme type at the schema layer will surface a + type-level reminder to revisit the policy. + +## Usage: Basic + +```ts +import { CsrfPolicy } from "@suaveplan/api-auth/csrf-policy"; + +const needsCsrf = CsrfPolicy.requiresCsrf({ + type: "apiKey", + in: "cookie", + name: "sp_session", +}); // → true +``` + +## Usage: Advanced + +Drive a host-side CSRF middleware off the policy, with a per-route override +applied at the call site: + +```ts +import { CsrfPolicy } from "@suaveplan/api-auth/csrf-policy"; +import type { OpenApiSecurityScheme } from "@suaveplan/api-auth/security-scheme"; + +interface RouteCsrfDecision { + readonly required: boolean; + readonly reason: "scheme-default" | "route-override"; +} + +function decideCsrf( + scheme: OpenApiSecurityScheme, + routeOverride: boolean | undefined, +): RouteCsrfDecision { + if (routeOverride !== undefined) { + return { required: routeOverride, reason: "route-override" }; + } + return { + required: CsrfPolicy.requiresCsrf(scheme), + reason: "scheme-default", + }; +} + +const decision = decideCsrf( + { type: "http", scheme: "bearer" }, + undefined, +); +// → { required: false, reason: "scheme-default" } +``` + +## API Reference + +| Symbol | Kind | Description | +|----------------------------|-------------|----------------------------------------------------------| +| `CsrfPolicy.requiresCsrf` | function | `(scheme) => boolean`. Cookie schemes → `true`. | + +## Implementation Notes + +- The predicate inspects `type === "apiKey" && in === "cookie"` — apiKey-in- + header is treated identically to `Authorization: Bearer …` for CSRF purposes + because the caller must attach it explicitly. +- `oauth2` and `openIdConnect` default OFF — both are bearer-token-derived in + practice; if a deployment exposes an oauth2 access token via cookie, that's + a custom apiKey-in-cookie scheme, not the `oauth2` scheme. +- `Object.freeze` guards the predicate slot; the predicate itself is a regular + method and TypeScript prevents reassignment via the `Readonly` inference. diff --git a/docs/api-stack/api/api-auth/src/error-codes/error-codes.md b/docs/api-stack/api/api-auth/src/error-codes/error-codes.md new file mode 100644 index 0000000..4cd16f6 --- /dev/null +++ b/docs/api-stack/api/api-auth/src/error-codes/error-codes.md @@ -0,0 +1,84 @@ +# `error-codes` — `AUTH_CODES` registry + + +_(no submodules)_ + + +## Purpose + +Defines the stable, namespaced error-code registry for the `@suaveplan/api-auth` +package and the concrete `AuthError` class. Every code is reachable from a +production throw site somewhere in the package (chain construction, chain +execution, adapter registration, or principal-shape validation). The registry +is frozen via `defineCodes("AUTH", […])` so accidental drift between thrown +codes and the documented set is impossible. + +Consumers — including downstream concrete resolvers in Stages 4/6/8 such as +`api-auth-jwt`, `api-auth-anonymous`, and `api-auth-bearer-static` — branch on +the string literal (`"AUTH.RESOLVER_THREW"` etc.) or compare to the constant +(`AUTH_CODES.RESOLVER_THREW`). The literal form is preferred at the API +boundary; the constant is preferred inside the package itself so the linter +flags typos as type errors. + +## Features + +- Frozen string-literal union of all four codes. +- `AuthError` extends `SuaveplanError` so `instanceof AuthError` + narrows `code` correctly. +- Cause-chain propagation: the optional `options.cause` field is forwarded to + the base class. +- Public constructor (the base class is `protected`). + +## Usage: Basic + +```ts +import { AUTH_CODES, AuthError } from "@suaveplan/api-auth/error-codes"; + +if (chain.length === 0) { + throw new AuthError(AUTH_CODES.CHAIN_EMPTY, "at least one resolver required"); +} +``` + +## Usage: Advanced + +Re-throw a resolver error with a cause chain and inspect it downstream: + +```ts +import { AUTH_CODES, AuthError } from "@suaveplan/api-auth/error-codes"; + +try { + await resolver.resolve(req); +} catch (cause) { + throw new AuthError(AUTH_CODES.RESOLVER_THREW, "resolver A threw", { + cause, + context: { resolverIndex: 0 }, + }); +} +``` + +```ts +import { AuthError } from "@suaveplan/api-auth/error-codes"; + +if (err instanceof AuthError && err.code === "AUTH.RESOLVER_THREW") { + logger.warn("upstream session resolver failed", { cause: err.cause }); +} +``` + +## API Reference + +| Symbol | Kind | Description | +|----------------|--------|-----------------------------------------------------------------| +| `AUTH_CODES` | const | Frozen lookup `{ RESOLVER_THREW, CHAIN_EMPTY, … }`. | +| `AuthErrorCode`| type | Literal union of the four code strings. | +| `AuthError` | class | Concrete `SuaveplanError` subclass narrowed to `AuthErrorCode`. | + +## Implementation Notes + +- `defineCodes("AUTH", [...] as const)` produces an object literal with + string-literal value types, which is what gives `AuthErrorCode` its narrow + union. Removing `as const` would widen the type to `string`. +- The class field `authCode` mirrors `code` for ergonomic narrowing on + pre-instantiated error objects (some test runners obscure the inherited + `code` field via Proxy wrappers). +- Code values follow the `AUTH.` template enforced by + `@suaveplan/api-types`' `ErrorCode` template literal type. diff --git a/docs/api-stack/api/api-auth/src/resolver/resolver.md b/docs/api-stack/api/api-auth/src/resolver/resolver.md new file mode 100644 index 0000000..391fc3a --- /dev/null +++ b/docs/api-stack/api/api-auth/src/resolver/resolver.md @@ -0,0 +1,119 @@ +# `resolver` — `SessionResolver` contract + + +_(no submodules)_ + + +## Purpose + +`SessionResolver` is the abstract per-request session-resolver shape that every +concrete adapter in Stages 4/6/8 (`api-auth-jwt`, `api-auth-anonymous`, +`api-auth-bearer-static`, `api-auth-better-auth`, `api-auth-rolled`) implements. +It deliberately captures only the universal vocabulary — inspect a WHATWG +`Request`, return a `Principal | null`, dispose — so any concrete resolver can +plug behind the host's chain runner without further coordination. + +The tri-valued return contract (principal / null / throw) collapses to two +host-level outcomes: the chain short-circuits on the first principal, the host +applies its `publicRoutes` decision when every resolver returned `null`, and +`AUTH.RESOLVER_THREW` is surfaced when any resolver throws (fail-closed by +default per design doc §6). + +## Features + +- Generic over `P extends Principal` — concrete adapters MAY narrow `Principal` + via interface merging without losing assignability to the chain's `Principal` + return type. +- Async by construction; resolvers MAY fetch JWKs, hit Redis, or call a token + introspection endpoint. +- `dispose` is part of the contract, not a side concern — the host blue/green + rotates resolver chains and relies on `dispose` to release JWK caches, close + HTTP keepalive pools, etc. + +## Usage: Basic + +A minimal resolver that always returns null (the "anonymous fallback" pattern +codified in `api-auth-anonymous`): + +```ts +import type { SessionResolver } from "@suaveplan/api-auth/resolver"; + +const anonymous: SessionResolver = { + async resolve() { + return null; + }, + async dispose() { + /* no resources to release */ + }, +}; +``` + +## Usage: Advanced + +A resolver that reads a `Bearer` token, parses claims, and returns a typed +principal — with `dispose` releasing a token-cache eviction timer: + +```ts +import type { SessionResolver } from "@suaveplan/api-auth/resolver"; +import type { Principal, PrincipalId, Scope } from "@suaveplan/api-types/principal"; + +interface JwtClaims { + sub: string; + scope?: string; + [key: string]: unknown; +} + +class JwtResolver implements SessionResolver { + private readonly evictTimer: ReturnType; + private disposed = false; + + public constructor(private readonly verifyJwt: (raw: string) => Promise) { + this.evictTimer = setInterval(() => { + /* prune cache */ + }, 30_000); + } + + public async resolve(req: Request): Promise { + const header = req.headers.get("authorization"); + if (!header?.startsWith("Bearer ")) { + return null; + } + const claims = await this.verifyJwt(header.slice("Bearer ".length)); + if (claims === null) { + return null; + } + const scopes = (claims.scope ?? "").split(" ").filter(Boolean) as readonly Scope[]; + return { + id: claims.sub as PrincipalId, + scopes, + claims, + }; + } + + public async dispose(): Promise { + if (this.disposed) { + return; + } + this.disposed = true; + clearInterval(this.evictTimer); + } +} +``` + +## API Reference + +| Symbol | Kind | Description | +|-------------------|-------------|------------------------------------------------------| +| `SessionResolver` | interface | `resolve(req): Promise

` + `dispose()`. | +| `P` (generic) | type param | Defaults to `Principal`. Narrowing is opt-in. | + +## Implementation Notes + +- `Request` is the WHATWG Fetch `Request` (DOM lib). Node ≥18, Bun, Deno, and + every Workers runtime all expose it as a global; `api-auth` does not import + any Node-specific request type so the contract is universal. +- Returning `null` for "credential present but invalid" is acceptable but + discouraged — emit `AUTH.PRINCIPAL_INVALID_SHAPE` instead, so the host can + distinguish "no credential" from "bad credential" in metrics. +- `dispose` SHOULD be idempotent; tests in the conformance harness call it + twice in a row and assert no throw. diff --git a/docs/api-stack/api/api-auth/src/security-scheme/security-scheme.md b/docs/api-stack/api/api-auth/src/security-scheme/security-scheme.md new file mode 100644 index 0000000..1d7963c --- /dev/null +++ b/docs/api-stack/api/api-auth/src/security-scheme/security-scheme.md @@ -0,0 +1,89 @@ +# `security-scheme` — `SecuritySchemeContribution` + + +_(no submodules)_ + + +## Purpose + +Defines the shape every concrete `SessionResolver` MUST contribute so the +`api-openapi` package can emit the right `components.securitySchemes` block in +the generated OpenAPI document (design doc §7 step 3). Exposed as both a Zod +schema (`SecuritySchemeContributionSchema`) and an inferred TypeScript type +(`SecuritySchemeContribution`), with a `validateSecurityScheme()` boundary +helper used by the host's adapter-registration pipeline. + +Validation at the boundary is mandatory: without it, a typo in a concrete +adapter's `name` or `scheme.type` would silently emit an invalid OpenAPI +document and break every downstream client generator. The host therefore calls +`validateSecurityScheme()` from its registration code and aborts boot rather +than serve traffic with a half-configured document. + +## Features + +- Discriminated-union schema covering the four OAS 3.1 scheme types + (`apiKey`, `http`, `oauth2`, `openIdConnect`). +- Boundary validator throws `AUTH.SECURITY_SCHEME_MISSING` on absence or shape + mismatch — the host's documented signal to abort boot. +- Cause-chain propagation: Zod's `issues` array is attached as `context.issues` + so the operator log explains exactly which field rejected. + +## Usage: Basic + +```ts +import { validateSecurityScheme } from "@suaveplan/api-auth/security-scheme"; + +const contribution = validateSecurityScheme({ + name: "bearerAuth", + scheme: { type: "http", scheme: "bearer", bearerFormat: "JWT" }, +}); +``` + +## Usage: Advanced + +Use the inferred type to constrain an adapter factory, then call the validator +at registration time: + +```ts +import { + type SecuritySchemeContribution, + validateSecurityScheme, +} from "@suaveplan/api-auth/security-scheme"; + +interface AdapterFactory { + readonly securityScheme: SecuritySchemeContribution; +} + +function registerAdapter(adapter: AdapterFactory): void { + const validated = validateSecurityScheme(adapter.securityScheme); + openApiRegistry.add(validated); +} + +const cookieAdapter: AdapterFactory = { + securityScheme: { + name: "sessionCookie", + scheme: { type: "apiKey", in: "cookie", name: "sp_session" }, + }, +}; + +registerAdapter(cookieAdapter); +``` + +## API Reference + +| Symbol | Kind | Description | +|------------------------------------|--------|--------------------------------------------------------------| +| `OpenApiSecuritySchemeSchema` | const | Zod discriminated union over the four OAS 3.1 scheme types. | +| `OpenApiSecurityScheme` | type | `z.infer`. | +| `SecuritySchemeContributionSchema` | const | `{ name, scheme }` Zod object. | +| `SecuritySchemeContribution` | type | Inferred contribution shape. | +| `validateSecurityScheme` | fn | Boundary validator; throws `AUTH.SECURITY_SCHEME_MISSING`. | + +## Implementation Notes + +- `import z from "zod"` (default import, per project rule). +- `z.discriminatedUnion("type", […])` is preferred over a plain union — it + surfaces a much sharper Zod error when the input has an unknown `type`. +- The contribution schema is the host-visible shape; concrete adapters MAY + extend their internal scheme record with extension fields (`x-*`) but the + host validates and forwards only the OAS-known keys. diff --git a/docs/api-stack/api/api-auth/src/session-adapter/session-adapter.md b/docs/api-stack/api/api-auth/src/session-adapter/session-adapter.md new file mode 100644 index 0000000..e91081d --- /dev/null +++ b/docs/api-stack/api/api-auth/src/session-adapter/session-adapter.md @@ -0,0 +1,81 @@ +# `session-adapter` — composite `AuthAdapter` + + +_(no submodules)_ + + +## Purpose + +`AuthAdapter` is the composite shape every concrete session-auth adapter +exports — pairing the per-request `SessionResolver` with the OpenAPI +`SecuritySchemeContribution` and the optional adapter-level CSRF override. +`validateAuthAdapter()` is the boundary helper the host calls before stitching +an adapter into its resolver chain; it throws `AUTH.SECURITY_SCHEME_MISSING` +when the contribution is absent or malformed. + +This package owns the marriage of "what does the credential look like on the +wire" (security scheme) and "how do we turn it into a Principal" (resolver) so +that downstream consumers — `api-host`, `api-openapi`, and the host's CSRF +middleware — read a single source-of-truth shape instead of three loosely +coupled fields scattered across every concrete adapter package. + +## Features + +- `csrf` is optional, intentionally: an unset slot defers to the + `CsrfPolicy.requiresCsrf(scheme)` default, while a set value pins per-adapter + intent (auditable in the host's adapter table). +- `validateAuthAdapter` is identity on the happy path so it composes with + registration pipelines that need to forward the validated value. + +## Usage: Basic + +```ts +import { type AuthAdapter, validateAuthAdapter } from "@suaveplan/api-auth/session-adapter"; +import type { SessionResolver } from "@suaveplan/api-auth/resolver"; + +declare const jwtResolver: SessionResolver; + +const adapter: AuthAdapter = { + resolver: jwtResolver, + securityScheme: { + name: "bearerAuth", + scheme: { type: "http", scheme: "bearer", bearerFormat: "JWT" }, + }, +}; + +validateAuthAdapter(adapter); +``` + +## Usage: Advanced + +Register multiple adapters at host startup; the validator centralises the +fail-fast and the host stitches the resolvers into a `SessionResolverChain`: + +```ts +import { SessionResolverChain } from "@suaveplan/api-auth/chain"; +import { type AuthAdapter, validateAuthAdapter } from "@suaveplan/api-auth/session-adapter"; + +function buildChain(adapters: readonly AuthAdapter[]): SessionResolverChain { + const validated = adapters.map((a) => validateAuthAdapter(a)); + return new SessionResolverChain(validated.map((a) => a.resolver)); +} +``` + +## API Reference + +| Symbol | Kind | Description | +|-----------------------|-------------|---------------------------------------------------------------| +| `AuthAdapter` | interface | `{ resolver, securityScheme, csrf? }`. | +| `validateAuthAdapter` | function | Boundary validator; throws `AUTH.SECURITY_SCHEME_MISSING`. | + +## Implementation Notes + +- `csrf` is a `boolean | undefined` field rather than a richer `CsrfDecision` + record. The host's middleware combines this slot with the per-route override + and the `CsrfPolicy.requiresCsrf` default into a final decision — the + adapter does NOT need three-valued logic for the same intent. +- `validateAuthAdapter` returns its argument unchanged so call sites can write + `const a = validateAuthAdapter(buildAdapter(opts));` without re-binding. +- The structural type is `interface` (not `type`) so concrete adapter packages + MAY use declaration merging to attach extension fields without forking the + contract. diff --git a/docs/api-stack/api/api-auth/src/testing/conformance.md b/docs/api-stack/api/api-auth/src/testing/conformance.md new file mode 100644 index 0000000..47ba74f --- /dev/null +++ b/docs/api-stack/api/api-auth/src/testing/conformance.md @@ -0,0 +1,101 @@ +# `testing` — `runAuthSessionConformance` harness + + +_(no submodules)_ + + +## Purpose + +A reusable Vitest `describe(...)` block every concrete `SessionResolver` must +pass before publishing. The harness covers the three behaviours that define a +correct resolver implementation independent of the underlying credential +shape: returning `null` for unrecognised requests, returning the documented +`Principal` for a recognised request, and an idempotent `dispose()`. + +Concrete adapters in Stages 4/6/8 (`api-auth-jwt`, `api-auth-anonymous`, +`api-auth-bearer-static`, `api-auth-better-auth`, `api-auth-rolled`) call +`runAuthSessionConformance({ … })` from one of their `*.test.ts` files. The +single conformance suite means every adapter ships against the same observable +contract; new adapters drop in without re-deriving the test plan. + +## Features + +- Pure function — wires `describe` / `it` from `@suaveplan/testing/runner` so + the suite runs identically under Vitest (default) and `bun:test` (under the + `bun` test condition). +- Factory pattern — adapters re-construct their resolver inside each `it` so + parallel runners do not share resolver state across tests. +- Every `it` carries `{ timeout: 5000 }` per the project's hard rule. + +## Usage: Basic + +```ts +import { runAuthSessionConformance } from "@suaveplan/api-auth/testing"; +import type { PrincipalId, Scope } from "@suaveplan/api-types/principal"; + +import { buildAnonymousResolver } from "../src/anonymous.js"; + +runAuthSessionConformance({ + label: "anonymous", + factory: () => buildAnonymousResolver(), + seedNull: () => new Request("https://example.test/api"), + seedPrincipal: () => ({ + request: new Request("https://example.test/api", { + headers: { "x-test-principal": "1" }, + }), + expected: { + id: "anon" as PrincipalId, + scopes: [] as readonly Scope[], + claims: {}, + }, + }), +}); +``` + +## Usage: Advanced + +Compose the harness with adapter-specific extra coverage (per-adapter codes, +JWK rotation, etc.): + +```ts +import { describe, it, expect } from "@suaveplan/testing/runner"; +import { runAuthSessionConformance } from "@suaveplan/api-auth/testing"; + +import { buildJwtResolver, JWT_CODES } from "../src/index.js"; + +runAuthSessionConformance({ + label: "jwt-hs256", + factory: async () => buildJwtResolver({ jwks: testJwks }), + seedNull: () => new Request("https://example.test/api"), + seedPrincipal: () => ({ + request: new Request("https://example.test/api", { + headers: { authorization: `Bearer ${testToken}` }, + }), + expected: testPrincipal, + }), +}); + +describe("jwt-hs256 specific", () => { + it("emits JWT.EXPIRED on stale token", { timeout: 5000 }, async () => { + /* … */ + }); +}); +``` + +## API Reference + +| Symbol | Kind | Description | +|-----------------------------------|-------------|----------------------------------------------------------------------| +| `runAuthSessionConformance` | function | Adds a `describe(...)` block; runs three baseline scenarios. | +| `AuthSessionConformanceFactory` | interface | `{ factory, label, seedNull, seedPrincipal }`. | + +## Implementation Notes + +- The harness asserts `id` + `scopes` equality on the principal, not deep + equality of `claims` — `claims` is intentionally free-form and adapters may + add provider-specific fields that callers must not pin in conformance. +- `dispose()` is asserted to resolve to `undefined`, not just "not throw" — + some legacy resolvers were returning the wrong shape from the second + invocation; this assertion caught it. +- `expect` and `describe`/`it` come from `@suaveplan/testing/runner` per + project rule 11. diff --git a/docs/api-stack/api/api-db-adapter/README.md b/docs/api-stack/api/api-db-adapter/README.md new file mode 100644 index 0000000..45b617a --- /dev/null +++ b/docs/api-stack/api/api-db-adapter/README.md @@ -0,0 +1,128 @@ +# @suaveplan/api-db-adapter — bridge from @suaveplan/db engine adapters to the plugin DatabaseLike surface. Provides AdminDatabaseLike + TenantScopedDatabaseLike factories, a per-engine migration runner, the db.unsafe-queries capability gate, an open DatabaseEngineRegistry, and a worker-proxy variant for the worker host. Both direct + proxy surfaces pass the same conformance suite. + +Stage-4 bridge from the `@suaveplan/db` engine adapters to the +plugin `AdminDatabaseLike` / `TenantScopedDatabaseLike` surfaces exposed by +`@suaveplan/api-types/db`. + +The package contains five orthogonal pieces: + +1. `options` — Zod-validated `DbAdapterOptions` (`engine`, `url`, `pool?`, + `tenantColumn`, `migrationsDir?`, `autoInjectInserts`). +2. `engine-registry` — open registry of engine factories. The package + itself ships no engines pre-installed; host code (or a downstream + adapter package) calls `registerEngine("sqlite" | "postgres" | + "surrealdb" | , factory)` once at boot. The shape keeps the + package universally importable. +3. `tenant-scoped` — the SQL rewriter that injects `WHERE tenant_id = ?` + on every SELECT/UPDATE/DELETE, verifies / auto-injects the tenant + column on INSERT, and rejects DDL or unsupported SQL with + `DB_ADAPTER.TENANT_SCOPE_VIOLATION`. Strict / lenient INSERT mode is + `autoInjectInserts` on the options. +4. `migrations` — per-engine migration runner consuming a directory of + `*.sql` files; tracks applied versions in `__plugin_migrations` and + is idempotent on re-run. Failed migrations roll back where the engine + supports transactions. +5. `unsafe` — the `db.unsafe` escape hatch, gated on the + `db.unsafe-queries` capability flag in the plugin manifest. Every + permitted call increments `plugin.unsafe_query_total{plugin}`. + +The package also ships a worker-side counterpart (`createDbAdapterWorkerProxy`) +that wires the worker-side `api-db-worker-proxy` client into the same surface +so direct + proxy variants are interchangeable in plugin code. + + +## Documentation tree + +- [engine-registry](./src/engine-registry/engine-registry.md) — The engine registry is the extension point that lets `api-db-adapter` stay universally importable while still supportin… + - [engine-registry](./src/engine-registry/engine-registry.md) — The engine registry is the extension point that lets `api-db-adapter` stay universally importable while still supportin… +- [error-codes](./src/error-codes/error-codes.md) — This module is the single source of truth for every public failure code raised by `@suaveplan/api-db-adapter`. Codes ar… + - [error-codes](./src/error-codes/error-codes.md) — This module is the single source of truth for every public failure code raised by `@suaveplan/api-db-adapter`. Codes ar… +- [factory](./src/factory/create-db-adapter.md) — `createDbAdapter` is the public entry point for host code that wants to wire the `@suaveplan/db` engine adapter… + - [create-db-adapter](./src/factory/create-db-adapter.md) — `createDbAdapter` is the public entry point for host code that wants to wire the `@suaveplan/db` engine adapter… +- [migrations](./src/migrations/run-migrations.md) — `runMigrations` applies a plugin's pending migrations from a directory of `*.sql` files, recording applied versions in… + - [run-migrations](./src/migrations/run-migrations.md) — `runMigrations` applies a plugin's pending migrations from a directory of `*.sql` files, recording applied versions in… +- [options](./src/options/db-adapter-options.md) — `DbAdapterOptions` is the single config object accepted by every public factory in this package — `createDbAdapter`, `c… + - [db-adapter-options](./src/options/db-adapter-options.md) — `DbAdapterOptions` is the single config object accepted by every public factory in this package — `createDbAdapter`, `c… +- [proxy](./src/proxy/create-db-adapter-worker-proxy.md) — `createDbAdapterWorkerProxy` is the worker-side counterpart to `createDbAdapter`. Inside an `api-worker-host` worker, p… + - [create-db-adapter-worker-proxy](./src/proxy/create-db-adapter-worker-proxy.md) — `createDbAdapterWorkerProxy` is the worker-side counterpart to `createDbAdapter`. Inside an `api-worker-host` worker, p… +- [tenant-scoped](./src/tenant-scoped/create-tenant-scoped-wrapper.md) — This module is the load-bearing safety boundary between a plugin route handler and the underlying admin database surfac… + - [create-tenant-scoped-wrapper](./src/tenant-scoped/create-tenant-scoped-wrapper.md) — This module is the load-bearing safety boundary between a plugin route handler and the underlying admin database surfac… +- [unsafe](./src/unsafe/unsafe-query-gate.md) — `createUnsafeGate` builds the `ctx.db.unsafe` API exposed on every tenant- scoped surface. The gate is the only sanctio… + - [unsafe-query-gate](./src/unsafe/unsafe-query-gate.md) — `createUnsafeGate` builds the `ctx.db.unsafe` API exposed on every tenant- scoped surface. The gate is the only sanctio… + + +## Quick start + +```ts +import { createDbAdapter } from "@suaveplan/api-db-adapter/adapter"; +import { registerEngine } from "@suaveplan/api-db-adapter/engine-registry"; +import { runMigrations } from "@suaveplan/api-db-adapter/migrations"; + +registerEngine("sqlite", async (opts) => myBunSqliteFactory(opts)); + +const db = await createDbAdapter({ engine: "sqlite", url: ":memory:" }); +await runMigrations({ + plugin: "audit", + capabilities: [], + admin: db.admin, + migrationsDir: "./db/migrations", + fs: nodeFsReader, +}); + +const scoped = db.scoped("acme" as TenantId); +const rows = await scoped.query("SELECT * FROM users"); +// actual SQL: SELECT * FROM users WHERE tenant_id = ? +// bound: ["acme"] +``` + +## Tenant-scope semantics + +The wrapper rewrites SQL based on the leading keyword (case-insensitive): + +| Shape | Rewrite | +|---|---| +| `SELECT ... [WHERE ...]` | append `WHERE`/`AND tenant_id = ?` before any ORDER BY / LIMIT / RETURNING / GROUP BY tail | +| `UPDATE ... [WHERE ...]` | same | +| `DELETE ... [WHERE ...]` | same | +| `INSERT INTO t (cols) VALUES (vals)` w/o `tenant_id` and `autoInjectInserts: true` | inject column + value | +| same w/o `tenant_id` and `autoInjectInserts: false` | throw `TENANT_SCOPE_VIOLATION` | +| `INSERT ...` w/ conflicting `tenant_id` (literal or bound) | throw `TENANT_SCOPE_VIOLATION` | +| anything else (DDL, INSERT...SELECT, multi-row VALUES, record-shaped params) | throw `TENANT_SCOPE_VIOLATION` — use a migration or `db.unsafe` | + +## `db.unsafe` escape hatch + +`createUnsafeGate({ plugin, capabilities, admin })` returns an +`UnsafeQueryApi` (`query`, `execute`). The capability check is array +membership on `db.unsafe-queries`; absent → throw +`DB_ADAPTER.UNSAFE_NOT_PERMITTED`. Permitted calls increment +`plugin.unsafe_query_total{plugin}`. + +## Migration directory layout + +Files are read from `migrationsDir` and applied lexicographically. The +recommended naming convention is `NNN_.sql`: + +``` +db/migrations/ + 001_init.sql + 002_add_invoices.sql + 003_index_invoices_on_org.sql +``` + +The runner records each applied file in `__plugin_migrations(plugin, +version, applied_at)` and is idempotent — re-running with no new files is +a no-op. + +## Error codes + +- `DB_ADAPTER.TENANT_SCOPE_VIOLATION` — scoped wrapper saw conflicting + tenant value, DDL, or unsupported SQL shape. +- `DB_ADAPTER.UNSAFE_NOT_PERMITTED` — `db.unsafe.*` invoked without + `db.unsafe-queries` capability. +- `DB_ADAPTER.MIGRATION_FAILED` — migration body threw; rolled back where + supported. +- `DB_ADAPTER.ENGINE_UNSUPPORTED` — `engine` value has no registered + factory. +- `DB_ADAPTER.INVALID_OPTIONS` — Zod validation failed; issues attached + to `error.context.issues`. + diff --git a/docs/api-stack/api/api-db-adapter/src/engine-registry/engine-registry.md b/docs/api-stack/api/api-db-adapter/src/engine-registry/engine-registry.md new file mode 100644 index 0000000..bf5c8ed --- /dev/null +++ b/docs/api-stack/api/api-db-adapter/src/engine-registry/engine-registry.md @@ -0,0 +1,88 @@ +# `engine-registry` — open registry mapping engine names to factories + + +_(no submodules)_ + + +## Purpose + +The engine registry is the extension point that lets `api-db-adapter` stay +universally importable while still supporting per-engine concrete adapters +(SQLite, Postgres, SurrealDB, plus declaration-merged third-party engines). +The package itself ships zero engines pre-installed. Host code or the +downstream adapter package calls `registerEngine(name, factory)` once at +process boot; every subsequent `createDbAdapter({ engine: name, ... })` call +delegates to that factory. + +This shape avoids three failure modes: pulling `bun:sqlite` into a browser +bundle, pulling `pg` into a worker, and pulling `surrealdb.js` into a CLI. + +## Features + +- `registerEngine(name, factory)` — register or replace a factory. +- `unregisterEngine(name)` — primarily for test isolation. +- `getEngineFactory(name)` — read-only lookup. +- `listEngines()` — snapshot of all currently-registered names. +- `buildEngineAdapter(options)` — high-level: look up + invoke + return the + constructed `AdminDatabaseLike`. Throws `DB_ADAPTER.ENGINE_UNSUPPORTED` + if the engine name has no factory. + +## Usage: Basic + +```ts +import { + registerEngine, + buildEngineAdapter, +} from "@suaveplan/api-db-adapter/engine-registry"; +import { SqliteAdapter } from "@suaveplan/db-sqlite"; + +registerEngine("sqlite", async (options) => { + const adapter = new SqliteAdapter({ filename: options.url }); + await adapter.connect(); + return adaptToAdminDatabaseLike(adapter, "sqlite"); +}); + +const admin = await buildEngineAdapter({ + engine: "sqlite", + url: ":memory:", + tenantColumn: "tenant_id", + autoInjectInserts: true, +}); +``` + +## Usage: Advanced + +```ts +import { registerEngine } from "@suaveplan/api-db-adapter/engine-registry"; + +// declaration-merge a new engine +declare module "@suaveplan/api-types/db" { + interface DatabaseEngineRegistry { + readonly cockroach: true; + } +} + +registerEngine("cockroach", async (options) => { + // build a CockroachDB-backed AdminDatabaseLike from options + return buildCockroachAdmin(options); +}); +``` + +## API Reference + +- `EngineFactory: (options: DbAdapterOptions) => Promise`. +- `registerEngine(name, factory): void` — register/replace. +- `unregisterEngine(name): boolean` — remove; returns `true` if removed. +- `getEngineFactory(name): EngineFactory | undefined`. +- `listEngines(): readonly string[]`. +- `buildEngineAdapter(options): Promise` — throws + `DbAdapterError` with code `DB_ADAPTER.ENGINE_UNSUPPORTED` if the engine + name was never registered. + +## Implementation Notes + +The registry is a process-wide singleton kept in module scope. That is the +correct shape for a sealed-once-at-boot capability map. Tests use +`unregisterEngine` for isolation; concurrent registration with the same name +is well-defined (last writer wins). The error thrown on lookup miss includes +`details.known: string[]` so operator log lines surface the typo immediately. diff --git a/docs/api-stack/api/api-db-adapter/src/error-codes/error-codes.md b/docs/api-stack/api/api-db-adapter/src/error-codes/error-codes.md new file mode 100644 index 0000000..4b1b9bb --- /dev/null +++ b/docs/api-stack/api/api-db-adapter/src/error-codes/error-codes.md @@ -0,0 +1,77 @@ +# `error-codes` — `DB_ADAPTER.*` registry + `DbAdapterError` + + +_(no submodules)_ + + +## Purpose + +This module is the single source of truth for every public failure code raised +by `@suaveplan/api-db-adapter`. Codes are namespaced under `DB_ADAPTER.*` and +exposed through both a `const` registry (`DB_ADAPTER_CODES`) and a typed +`SuaveplanError` subclass (`DbAdapterError`). + +Consumers branch on the literal value at runtime — never on the message text — +which means the wire format of every error is stable across releases. The +registry is consumed by the migration runner, the tenant-scoped wrapper, the +options validator, the engine registry, and the `db.unsafe-queries` capability +gate. + +## Features + +- Five stable codes covering every public failure path: `TENANT_SCOPE_VIOLATION`, + `UNSAFE_NOT_PERMITTED`, `MIGRATION_FAILED`, `ENGINE_UNSUPPORTED`, + `INVALID_OPTIONS`. +- Single `DbAdapterError` class extending `SuaveplanError` — discriminable by + `instanceof` or by code string. +- `SuaveplanErrorOptions.cause` is honoured, so engine-side throws (e.g. a + Postgres protocol error during migration) are preserved on the cause chain. +- Compatible with the standard `SuaveplanError` wire format — no per-package + deviations. + +## Usage: Basic + +```ts +import { + DB_ADAPTER_CODES, + DbAdapterError, +} from "@suaveplan/api-db-adapter/error-codes"; + +throw new DbAdapterError( + DB_ADAPTER_CODES.UNSAFE_NOT_PERMITTED, + "plugin 'audit' does not declare db.unsafe-queries" +); +``` + +## Usage: Advanced + +```ts +import { + DB_ADAPTER_CODES, + DbAdapterError, +} from "@suaveplan/api-db-adapter/error-codes"; + +try { + await runMigrations(plugin, capabilities); +} catch (cause) { + throw new DbAdapterError( + DB_ADAPTER_CODES.MIGRATION_FAILED, + `migration ${cause.file} failed`, + { cause, context: { file: cause.file } } + ); +} +``` + +## API Reference + +- `DB_ADAPTER_CODES` — `const` registry of the five codes. +- `DbAdapterCode` — union of all registry values. +- `DbAdapterError` — subclass of `SuaveplanError`. + +## Implementation Notes + +The codes are declared via `defineCodes("DB_ADAPTER", [...])` which produces a +frozen mapping `{ TENANT_SCOPE_VIOLATION: "DB_ADAPTER.TENANT_SCOPE_VIOLATION", +... }`. Comparisons against the registry value never drift even if a future +change reorders the input array because the keys are spelled identically to the +prefixed value's tail. diff --git a/docs/api-stack/api/api-db-adapter/src/factory/create-db-adapter.md b/docs/api-stack/api/api-db-adapter/src/factory/create-db-adapter.md new file mode 100644 index 0000000..aa32a32 --- /dev/null +++ b/docs/api-stack/api/api-db-adapter/src/factory/create-db-adapter.md @@ -0,0 +1,84 @@ +# `factory/create-db-adapter` — direct-surface adapter factory + + +_(no submodules)_ + + +## Purpose + +`createDbAdapter` is the public entry point for host code that wants to wire +the `@suaveplan/db` engine adapters to the plugin +`AdminDatabaseLike` / `TenantScopedDatabaseLike` surfaces. It composes three +pieces from this package — the options validator, the engine registry, and +the tenant-scope wrapper — into a single callable that delegates engine +identity to the open `DatabaseEngineRegistry`. + +The result object exposes: + +- `admin` — the unscoped `AdminDatabaseLike` (used by migrations and admin + endpoints). +- `scoped(tenantId)` — produces a fresh `TenantScopedDatabaseLike` wrapper + over the same admin connection. The wrapper is stateless beyond the + rewrite contract, so one admin connection can back many tenant scopes + concurrently. +- `close()` — closes the underlying admin connection. + +## Features + +- Options are parsed once at factory time; the rest of the API is typed + against the *post-parse* `DbAdapterOptions`. +- Engine lookup is delegated to `buildEngineAdapter`, so any + declaration-merged engine works automatically. +- Tenant scoping config (`tenantColumn`, `autoInjectInserts`) flows from + the parsed options into every `scoped()` call — no per-call repetition. + +## Usage: Basic + +```ts +import { createDbAdapter } from "@suaveplan/api-db-adapter/adapter"; +import { registerEngine } from "@suaveplan/api-db-adapter/engine-registry"; + +registerEngine("sqlite", buildSqliteEngineFactory()); + +const db = await createDbAdapter({ engine: "sqlite", url: ":memory:" }); +const admin = db.admin; +const acme = db.scoped("acme" as TenantId); +const rows = await acme.query("SELECT * FROM users"); +await db.close(); +``` + +## Usage: Advanced + +```ts +const db = await createDbAdapter({ + engine: "postgres", + url: "postgres://app@db.local/app", + tenantColumn: "org_id", + autoInjectInserts: false, + pool: { min: 2, max: 16, idleMs: 60_000 }, +}); + +const tx = await db.scoped(tenantId).transaction!(async (tx) => { + await tx.execute( + "INSERT INTO invoices (id, org_id, amount) VALUES (?, ?, ?)", + ["inv_1", tenantId, 100] + ); + return await tx.query<{ id: string }[]>("SELECT id FROM invoices"); +}); +``` + +## API Reference + +- `createDbAdapter(input: DbAdapterOptionsInput): Promise`. +- `DbAdapter.admin: AdminDatabaseLike`. +- `DbAdapter.scoped(tenantId: TenantId): TenantScopedDatabaseLike`. +- `DbAdapter.close(): Promise`. + +## Implementation Notes + +The factory does NOT register engines on import — it expects the host or a +downstream adapter package to populate the registry before the first call. +This shape keeps `@suaveplan/api-db-adapter` universally importable and +prevents engine deps from leaking into bundles that never use them. Errors +surface synchronously where possible (options validation, engine lookup); +engine handshake errors arrive as the promise rejection. diff --git a/docs/api-stack/api/api-db-adapter/src/migrations/run-migrations.md b/docs/api-stack/api/api-db-adapter/src/migrations/run-migrations.md new file mode 100644 index 0000000..684acc4 --- /dev/null +++ b/docs/api-stack/api/api-db-adapter/src/migrations/run-migrations.md @@ -0,0 +1,103 @@ +# `migrations/run-migrations` — per-engine migration runner + + +_(no submodules)_ + + +## Purpose + +`runMigrations` applies a plugin's pending migrations from a directory of +`*.sql` files, recording applied versions in the engine-side +`__plugin_migrations(plugin, version, applied_at)` table. It is the single +entry point used by `installing` step of the plugin lifecycle FSM; the +plugin host calls it once per `(plugin, engine)` pair during boot. + +The runner is engine-neutral: it issues only standard SQL (`CREATE TABLE +IF NOT EXISTS`, `SELECT`, `INSERT`, plus the migration body). When the +underlying adapter exposes `transaction`, each migration is applied +inside an atomic transaction; on failure the transaction rolls back and +the row in `__plugin_migrations` is not written. + +## Features + +- Lexicographic file ordering (`001_init.sql` before `002_*.sql`). +- Idempotent re-run — applied versions are tracked in + `__plugin_migrations`; a second call with the same file set applies + zero migrations. +- Per-migration `transaction { body + INSERT }` for engines that support + transactions; flat `execute + execute` fall-back for those that + don't (e.g. some Surreal modes). +- OTel instruments: `api.db.migrations_applied_total{plugin}` counter + + `api.db.migration_duration_ms{plugin}` histogram. +- Injectable `fs: MigrationsFsReader` — tests use an in-memory map, + production wires `node:fs/promises`. +- On any failure: `DB_ADAPTER.MIGRATION_FAILED` with cause + details + including the failing file name. + +## Usage: Basic + +```ts +import { runMigrations } from "@suaveplan/api-db-adapter/migrations"; +import { promises as fs } from "node:fs"; + +const result = await runMigrations({ + plugin: "audit", + capabilities: [], + admin, + migrationsDir: "./db/migrations", + fs: { + readdir: (dir) => fs.readdir(dir), + readFile: (path) => fs.readFile(path, "utf8"), + }, +}); +// result.applied = ["001_init.sql", "002_add_invoices.sql"] +// result.skipped = [] // first run +``` + +## Usage: Advanced + +```ts +const memFs = { + readdir: async () => ["001.sql", "002.sql"], + readFile: async (path: string) => + path.endsWith("001.sql") + ? "CREATE TABLE users(id TEXT)" + : "ALTER TABLE users ADD COLUMN email TEXT", +}; + +const first = await runMigrations({ + plugin: "user", + capabilities: [], + admin, + migrationsDir: "/dev/null", + fs: memFs, +}); +// first.applied.length === 2 + +const second = await runMigrations({ + plugin: "user", + capabilities: [], + admin, + migrationsDir: "/dev/null", + fs: memFs, +}); +// second.applied.length === 0, second.skipped.length === 2 +``` + +## API Reference + +- `runMigrations(options): Promise`. +- `RunMigrationsOptions` — `{ plugin, capabilities, admin, migrationsDir, fs }`. +- `RunMigrationsResult` — `{ applied: string[]; skipped: string[] }`. +- `MigrationsFsReader` — `{ readdir(dir); readFile(path) }`. +- `getMigrationInstruments() / resetMigrationInstruments()`. + +## Implementation Notes + +The runner intentionally does not parse SQL inside the migration body — that +is the engine's job. Failed migrations rely on `transaction` for atomic +rollback; on engines without transactions, partial state is possible if the +body succeeds but the `INSERT` into `__plugin_migrations` fails. That is +out of scope for the runner and the responsibility of operator runbooks +(`Surrealdb` mostly). The `applied_at` column is an ISO-8601 timestamp, +matching the `MigrationCursor.appliedAt` shape on `@suaveplan/api-types/db`. diff --git a/docs/api-stack/api/api-db-adapter/src/options/db-adapter-options.md b/docs/api-stack/api/api-db-adapter/src/options/db-adapter-options.md new file mode 100644 index 0000000..cb9bcf8 --- /dev/null +++ b/docs/api-stack/api/api-db-adapter/src/options/db-adapter-options.md @@ -0,0 +1,76 @@ +# `db-adapter-options` — Zod-validated configuration for `createDbAdapter` + + +_(no submodules)_ + + +## Purpose + +`DbAdapterOptions` is the single config object accepted by every public factory +in this package — `createDbAdapter`, `createDbAdapterWorkerProxy`, and +`runMigrations` all derive from it. The schema is Zod-driven so that host code +catches configuration mistakes at construction time, before any TCP socket is +opened. + +The schema is intentionally narrow: engine, url, optional pool tuning, the +tenant column name, an optional migrations directory, and a strict-mode flag +that decides whether the tenant-scoped wrapper rejects or auto-injects `INSERT` +payloads. + +## Features + +- Zod schema with sensible defaults (`tenantColumn = "tenant_id"`, + `autoInjectInserts = true`, pool max `10`, idle `30_000` ms). +- `parseDbAdapterOptions(input)` — convenience wrapper that converts every Zod + failure into a typed `DbAdapterError` with code `INVALID_OPTIONS`. Issues + are surfaced through `error.context.issues`. +- `engine` is `z.string().min(1)` — the *literal value* check happens against + the open `DatabaseEngineRegistry` so declaration-merged engines pass. +- `pool` is an optional sub-schema with its own defaults; absent values are + forwarded as `undefined` to the engine layer rather than guessed. + +## Usage: Basic + +```ts +import { parseDbAdapterOptions } from "@suaveplan/api-db-adapter/options"; + +const options = parseDbAdapterOptions({ + engine: "sqlite", + url: ":memory:", +}); +// options.tenantColumn === "tenant_id" +// options.autoInjectInserts === true +``` + +## Usage: Advanced + +```ts +import { parseDbAdapterOptions } from "@suaveplan/api-db-adapter/options"; + +const options = parseDbAdapterOptions({ + engine: "postgres", + url: "postgres://app@db.local:5432/app", + tenantColumn: "org_id", + autoInjectInserts: false, + pool: { min: 2, max: 16, idleMs: 60_000 }, + migrationsDir: "./db/migrations", +}); +``` + +## API Reference + +- `DbAdapterOptionsSchema` — top-level Zod schema. +- `DbAdapterPoolSchema` — pool sub-schema with `min`, `max`, `idleMs`. +- `DbAdapterOptions` — inferred output type (post-parse). +- `DbAdapterOptionsInput` — inferred input type (pre-parse). +- `parseDbAdapterOptions(input): DbAdapterOptions` — throws `DbAdapterError` + with code `DB_ADAPTER.INVALID_OPTIONS` on failure. + +## Implementation Notes + +The defaults are applied via `.default(...)` on each field so the output type is +non-optional after parsing. Pool fields have their own defaults so `pool: {}` +parses to the full default block; total absence (`pool` undefined) is preserved +because it lets the engine layer pick its own defaults. Engine identity is +validated separately by the engine registry so this module stays decoupled from +the concrete `DatabaseEngineRegistry` keys. diff --git a/docs/api-stack/api/api-db-adapter/src/proxy/create-db-adapter-worker-proxy.md b/docs/api-stack/api/api-db-adapter/src/proxy/create-db-adapter-worker-proxy.md new file mode 100644 index 0000000..b9e0a5b --- /dev/null +++ b/docs/api-stack/api/api-db-adapter/src/proxy/create-db-adapter-worker-proxy.md @@ -0,0 +1,81 @@ +# `proxy/create-db-adapter-worker-proxy` — worker-side adapter factory + + +_(no submodules)_ + + +## Purpose + +`createDbAdapterWorkerProxy` is the worker-side counterpart to +`createDbAdapter`. Inside an `api-worker-host` worker, plugin code receives a +proxy that looks identical to the direct surface but marshals every call +across an `@suaveplan/api-db-worker-proxy` `MessagePort`. The host side +still owns the real engine connection and the tenant-scope rewriter; this +package is the worker-side facade. + +Cursor results survive the boundary as `ReadableStream` (transferable per +the worker-rpc layer), so a 10_000-row query streams row-by-row without +buffering. The tenant-scoped facade is structurally identical to the +direct-surface one because the host's `wrapTenantScoped` already maps +`AdminDatabaseLike` onto `TenantScopedDatabaseLike` without further SQL +rewriting (rewriting happens main-side). + +## Features + +- Identical public shape to `DbAdapter` for parity: `admin`, `scoped()`, + `close()`. +- Built on `createDbProxyClient` from `api-db-worker-proxy/worker-side`, + which manages RPC framing, cursor streaming, and stream cancellation. +- Engine identity is supplied synchronously at construction (it would + require a round-trip otherwise). + +## Usage: Basic + +```ts +import { createDbAdapterWorkerProxy } from "@suaveplan/api-db-adapter/proxy"; + +const proxy = createDbAdapterWorkerProxy({ + port: workerPort, + engine: "sqlite", +}); + +const rows = await proxy.scoped("acme" as TenantId).query("SELECT * FROM users"); +proxy.close(); +``` + +## Usage: Advanced + +```ts +import { createDbProxyHarness } from "@suaveplan/api-db-worker-proxy/testing"; +import { createDbAdapterWorkerProxy } from "@suaveplan/api-db-adapter/proxy"; + +const harness = createDbProxyHarness({ seed: [["a", { v: 1 }]] }); +try { + const proxy = createDbAdapterWorkerProxy({ + port: harness.ports.clientPort, + engine: harness.db.engine, + }); + const rows = await proxy.admin.query("SELECT *"); + proxy.close(); +} finally { + harness.close(); +} +``` + +## API Reference + +- `createDbAdapterWorkerProxy(options): DbAdapterWorkerProxy`. +- `DbAdapterWorkerProxyOptions` — `{ port, engine, clientOptions? }`. +- `DbAdapterWorkerProxy.admin: DbProxyClient` (admin + `cursor()`). +- `DbAdapterWorkerProxy.scoped(tenantId): TenantScopedDatabaseLike`. +- `DbAdapterWorkerProxy.close(): void`. + +## Implementation Notes + +The proxy intentionally exposes the underlying `DbProxyClient` (extends +`AdminDatabaseLike`) as `admin` so cursor streaming is reachable to +consumers that need it. Tenant-scope rewriting is the main side's job; this +facade only injects the `tenantId` brand into the worker-side type so route +handlers cannot accidentally pass an admin reference where a scoped one is +expected. `close()` calls `client.dispose()` which rejects in-flight calls +with `DB_PROXY.PROXY_DISPOSED`. diff --git a/docs/api-stack/api/api-db-adapter/src/tenant-scoped/create-tenant-scoped-wrapper.md b/docs/api-stack/api/api-db-adapter/src/tenant-scoped/create-tenant-scoped-wrapper.md new file mode 100644 index 0000000..17053da --- /dev/null +++ b/docs/api-stack/api/api-db-adapter/src/tenant-scoped/create-tenant-scoped-wrapper.md @@ -0,0 +1,91 @@ +# `tenant-scoped/create-tenant-scoped-wrapper` — SQL rewriter for row-level tenancy + + +_(no submodules)_ + + +## Purpose + +This module is the load-bearing safety boundary between a plugin route handler +and the underlying admin database surface. Every SELECT/UPDATE/DELETE that the +route handler issues is rewritten in flight to carry a `WHERE tenant_id = ?` +predicate; every INSERT either carries the tenant column or is rejected (or +auto-injected, configurable). The contract is enforced *at the wrapper*, so a +route handler literally cannot read another tenant's rows even if the plugin +author is malicious. + +The wrapper does not perform full SQL parsing; it performs a fast, +case-insensitive lexical pass that handles the shapes a route handler +realistically writes (simple FROM table, optional WHERE, ORDER BY, LIMIT, +RETURNING). Anything beyond — multi-row INSERT, INSERT...SELECT, DDL, named +params — is rejected with `TENANT_SCOPE_VIOLATION`, forcing the plugin author +to either move the statement into a migration or declare the +`db.unsafe-queries` capability. + +## Features + +- Auto-injects `WHERE tenant_id = ?` (or `AND tenant_id = ?` when WHERE + already exists) on SELECT/UPDATE/DELETE. Tail clauses (ORDER BY, LIMIT, + RETURNING, GROUP BY) are preserved. +- INSERT handling: detect tenant column; if absent and `autoInjectInserts: + true`, rewrite to include it; if absent and `false`, reject; if present + with a conflicting value (literal or bound), reject. +- Transactions: every `tx.query` and `tx.execute` inside the transaction + callback is rewritten identically to top-level calls. +- Prepared statements: rewriting happens at execute time (so the bound + params are visible), falling back to a non-prepared execute on the + admin surface. +- Pure-function `rewriters` export for direct testing. + +## Usage: Basic + +```ts +import { createTenantScopedWrapper } from "@suaveplan/api-db-adapter/tenant-scoped"; + +const scoped = createTenantScopedWrapper(admin, "acme" as TenantId); +const rows = await scoped.query("SELECT * FROM users"); +// executed SQL: SELECT * FROM users WHERE tenant_id = ? +// bound params: ["acme"] +``` + +## Usage: Advanced + +```ts +import { createTenantScopedWrapper } from "@suaveplan/api-db-adapter/tenant-scoped"; + +const strict = createTenantScopedWrapper(admin, tenantId, { + tenantColumn: "org_id", + autoInjectInserts: false, +}); + +// INSERT must explicitly carry org_id matching the resolved tenant +await strict.execute( + "INSERT INTO invoices (id, org_id, amount) VALUES (?, ?, ?)", + ["inv_1", tenantId, 100] +); + +// rejected: literal doesn't match scope +await strict + .execute("INSERT INTO invoices (org_id) VALUES ('other')") + .catch((e) => e.code === "DB_ADAPTER.TENANT_SCOPE_VIOLATION"); +``` + +## API Reference + +- `createTenantScopedWrapper(admin, tenantId, options?): TenantScopedDatabaseLike`. +- `TenantScopedWrapperOptions` — `{ tenantColumn?, autoInjectInserts? }`. +- `rewriters.injectWhere(sql, tenantColumn, tenantId, params)` — appends a + WHERE/AND predicate. +- `rewriters.handleInsert(sql, tenantColumn, tenantId, params, autoInject)` + — verifies or auto-injects. + +## Implementation Notes + +The rewriter uses positional `?` parameters because they are accepted by +SQLite, MySQL, and (with driver-side rebinding) Postgres. Engines requiring +`$N` placeholders are expected to rebind at the driver layer. Record-shaped +params and multi-row INSERTs are rejected explicitly rather than guessed; +that pushes complex SQL into either a migration (which runs on the admin +surface) or `db.unsafe.query` (capability-gated), keeping the rewriter +narrow and auditable. Transaction callbacks receive a wrapped `DbTransaction` +so the rewrite contract holds across the whole tx body. diff --git a/docs/api-stack/api/api-db-adapter/src/unsafe/unsafe-query-gate.md b/docs/api-stack/api/api-db-adapter/src/unsafe/unsafe-query-gate.md new file mode 100644 index 0000000..ee01088 --- /dev/null +++ b/docs/api-stack/api/api-db-adapter/src/unsafe/unsafe-query-gate.md @@ -0,0 +1,84 @@ +# `unsafe/unsafe-query-gate` — capability-gated escape hatch + + +_(no submodules)_ + + +## Purpose + +`createUnsafeGate` builds the `ctx.db.unsafe` API exposed on every tenant- +scoped surface. The gate is the only sanctioned path for a plugin to issue +raw SQL that bypasses the tenant-scope rewriter — and the only path that is +required to be auditable. The capability declaration is read from the +plugin manifest at construction time; calls without the declaration throw +synchronously, before the engine sees the SQL. + +Each permitted call increments `plugin.unsafe_query_total{plugin}` so operators +can graph which plugins are exercising the escape hatch and at what rate. A +high count is an audit signal, not an error. + +## Features + +- Capability check is a literal array membership on `db.unsafe-queries`. +- `plugin.unsafe_query_total` counter, attribute `plugin` carrying the + plugin name from `UnsafeGateOptions`. +- Lazy `getUnsafeGateInstruments()` so test harnesses can install a custom + `MeterProvider` BEFORE the gate is constructed. +- `resetUnsafeGateInstruments()` for tests that swap meter providers + between cases. +- Both `query` and `execute` are gated; the gate is symmetric across + statement shapes. + +## Usage: Basic + +```ts +import { createUnsafeGate } from "@suaveplan/api-db-adapter/unsafe"; + +const unsafe = createUnsafeGate({ + plugin: "audit", + capabilities: ["db.unsafe-queries"], + admin, +}); +const rows = await unsafe.query("SELECT * FROM audit_log"); +``` + +## Usage: Advanced + +```ts +import { metrics } from "@opentelemetry/api"; +import { + createUnsafeGate, + resetUnsafeGateInstruments, +} from "@suaveplan/api-db-adapter/unsafe"; + +// Install a test MeterProvider FIRST. +metrics.setGlobalMeterProvider(testProvider); +resetUnsafeGateInstruments(); + +const denied = createUnsafeGate({ + plugin: "user", + capabilities: [], // no db.unsafe-queries + admin, +}); + +await denied + .execute("DELETE FROM secrets") + .catch((e) => e.code === "DB_ADAPTER.UNSAFE_NOT_PERMITTED"); +``` + +## API Reference + +- `createUnsafeGate(opts: UnsafeGateOptions): UnsafeQueryApi`. +- `UnsafeQueryApi.query(sql, params?): Promise`. +- `UnsafeQueryApi.execute(sql, params?): Promise<{ rowsAffected }>`. +- `getUnsafeGateInstruments(): { meter, unsafeQueryTotal }`. +- `resetUnsafeGateInstruments(): void` — test only. + +## Implementation Notes + +The capability check happens at gate construction and again on each call (so a +permissions change applied between requests does not require the host to swap +the gate). Counter attributes use `plugin` rather than the prefixed +`db.plugin` to match the metric naming in the design doc. The gate never +inspects the SQL — that is the host's audit-sink job; the gate's contract is +"capability or `UNSAFE_NOT_PERMITTED`". diff --git a/docs/api-stack/api/api-db-sqlite-memory/README.md b/docs/api-stack/api/api-db-sqlite-memory/README.md new file mode 100644 index 0000000..7f5186d --- /dev/null +++ b/docs/api-stack/api/api-db-sqlite-memory/README.md @@ -0,0 +1,78 @@ +# @suaveplan/api-db-sqlite-memory — in-memory SQLite database adapter for the @suaveplan/api plugin host testing kit. Wraps bun:sqlite in `:memory:` mode (or an on-disk file for persistent test fixtures) behind the AdminDatabaseLike + TenantScopedDatabaseLike contracts, applies WAL + foreign_keys pragmas by default, ships a lexicographic migration runner with __plugin_migrations bookkeeping, and registers itself in the @suaveplan/api-db-adapter engine registry under the `sqlite-memory` key so `createDbAdapter({ engine: 'sqlite-memory' })` resolves transparently. + +Stage-5 in-memory SQLite database adapter for the `@suaveplan/api` plugin host testing kit. Wraps `bun:sqlite` (in `:memory:` mode by default, or a file path for longer-lived fixtures) behind the `AdminDatabaseLike` + `TenantScopedDatabaseLike` contracts from `@suaveplan/api-types/db`, ships a lexicographic migration runner with `__plugin_migrations` bookkeeping, and self-registers in the `@suaveplan/api-db-adapter` engine registry under the `sqlite-memory` key so `createDbAdapter({ engine: "sqlite-memory" })` resolves transparently. + +The adapter is production-grade — it happens to keep state in process memory. Real SQLite drives every query, transaction semantics match, foreign-key enforcement is on by default, and the migration runner is fully transactional. Tests boot in milliseconds without testcontainers or any other external service. + + +## Documentation tree + +- [engine](./src/engine/register-engine.md) — Registers the in-memory SQLite adapter under `engine: "sqlite-memory"` in the open `@suaveplan/api-db-adapter` engine r… + - [register-engine](./src/engine/register-engine.md) — Registers the in-memory SQLite adapter under `engine: "sqlite-memory"` in the open `@suaveplan/api-db-adapter` engine r… +- [error-codes](./src/error-codes/error-codes.md) — This module declares the stable error-code registry for `@suaveplan/api-db-sqlite-memory`. Every error thrown from the… + - [error-codes](./src/error-codes/error-codes.md) — This module declares the stable error-code registry for `@suaveplan/api-db-sqlite-memory`. Every error thrown from the… +- [create-sqlite-memory-adapter](./src/factory/create-sqlite-memory-adapter.md) — Opens a real `bun:sqlite` `Database` and wraps it as an `AdminDatabaseLike`. The default zero-argument call yields a `:… +- [create-sqlite-memory-db](./src/factory/create-sqlite-memory-db.md) — Stage-5 top-level testing factory. Combines `createSqliteMemoryAdapter` with the tenant-scoping wrapper from this packa… +- [migrations](./src/migrations/migrations.md) — Lexicographic forward-only migration runner for the in-memory SQLite adapter. Applies every `*.sql` file in a directory… + - [migrations](./src/migrations/migrations.md) — Lexicographic forward-only migration runner for the in-memory SQLite adapter. Applies every `*.sql` file in a directory… +- [options](./src/options/sqlite-memory-db-options.md) — Defines the Zod-validated options object accepted by `createSqliteMemoryDb`, `createSqliteMemoryAdapter`, and the engin… + - [sqlite-memory-db-options](./src/options/sqlite-memory-db-options.md) — Defines the Zod-validated options object accepted by `createSqliteMemoryDb`, `createSqliteMemoryAdapter`, and the engin… +- [tenant-scoping](./src/tenant-scoping/tenant-scoping.md) — Wraps an `AdminDatabaseLike` as a `TenantScopedDatabaseLike` that transparently injects the resolved tenant id into eve… + - [tenant-scoping](./src/tenant-scoping/tenant-scoping.md) — Wraps an `AdminDatabaseLike` as a `TenantScopedDatabaseLike` that transparently injects the resolved tenant id into eve… +- [testing](./src/testing/harness.md) — Convenience builder for plugin test files. Wraps `createSqliteMemoryDb` with an idempotent `cleanup()` so the canonical… + - [harness](./src/testing/harness.md) — Convenience builder for plugin test files. Wraps `createSqliteMemoryDb` with an idempotent `cleanup()` so the canonical… + + +## Connection string + +The canonical connection string is `":memory:"` — the default. Any non-empty string passed as `filename` is forwarded straight to `bun:sqlite`'s `Database` constructor, so an absolute path opens a persistent file-backed fixture: + +```ts +import { createSqliteMemoryAdapter } from "@suaveplan/api-db-sqlite-memory"; + +const ephemeral = createSqliteMemoryAdapter(); // ":memory:" +const persisted = createSqliteMemoryAdapter({ filename: "/tmp/fixture.sqlite" }); +``` + +## Default pragmas + +Every fresh connection has these pragmas applied at open time: + +- `journal_mode = WAL` — write-ahead logging. No-op for `:memory:`, useful for file-backed fixtures. +- `foreign_keys = ON` — SQLite ships with FK enforcement disabled by default. The adapter flips it on so referential integrity is honoured. + +Operators that want to override either default supply `pragmas` in the options object: + +```ts +const adapter = createSqliteMemoryAdapter({ + pragmas: { foreign_keys: "OFF", synchronous: "FULL" }, +}); +``` + +The final merged pragma map is `{ ...DEFAULT_PRAGMAS, ...options.pragmas }`, so any default can be overridden by repeating its key. + +## Subpath exports + +| Subpath | Purpose | +| --- | --- | +| `.` | Root barrel — re-exports every public symbol. | +| `./adapter` | `createSqliteMemoryAdapter` + OTel instrument hooks. | +| `./factory` | `createSqliteMemoryDb` returning `{ admin, scoped, close }`. | +| `./engine` | `registerSqliteMemoryEngine` for the api-db-adapter registry. | +| `./migrations` | `runSqliteMemoryMigrations` + `SqliteMigrationsFsReader`. | +| `./options` | Zod schema + `parseSqliteMemoryDbOptions` + `resolvePragmas`. | +| `./tenant-scoping` | `createTenantScopedSqliteWrapper` + pure SQL rewriters. | +| `./error-codes` | `DB_SQLITE_MEMORY_CODES` + `DbSqliteMemoryError`. | +| `./testing` | `createInMemorySqliteHarness` convenience builder. | + +## Error codes + +- `DB_SQLITE_MEMORY.OPEN_FAILED` — `bun:sqlite` constructor threw. +- `DB_SQLITE_MEMORY.INVALID_OPTIONS` — Zod validation failed. +- `DB_SQLITE_MEMORY.MIGRATION_FAILED` — a migration file threw; transaction rolled back. +- `DB_SQLITE_MEMORY.TENANT_SCOPE_VIOLATION` — cross-tenant write or unsupported SQL shape. + +## License + +MIT. + diff --git a/docs/api-stack/api/api-db-sqlite-memory/src/engine/register-engine.md b/docs/api-stack/api/api-db-sqlite-memory/src/engine/register-engine.md new file mode 100644 index 0000000..134aa7f --- /dev/null +++ b/docs/api-stack/api/api-db-sqlite-memory/src/engine/register-engine.md @@ -0,0 +1,77 @@ +# `registerSqliteMemoryEngine` + + +_(no submodules)_ + + +## Purpose + +Registers the in-memory SQLite adapter under `engine: "sqlite-memory"` in the open `@suaveplan/api-db-adapter` engine registry. Once called, any consumer that constructs an adapter via `createDbAdapter({ engine: "sqlite-memory", ... })` receives an instance produced by this package. The TypeScript-side declaration-merge into `DatabaseEngineRegistry` means the engine name is accepted as a string-literal-typed argument with no cast. + +This is the bridge that lets `@suaveplan/api-host/testing`'s Stage-5 `createTestHost` boot a plugin entirely against an in-memory SQLite without changing any of The adapter code paths. The registration is idempotent — calling twice replaces the previous factory — and the function returns a disposer so tests can unregister the engine in `afterEach`. + +## Features + +- Type-level: `declare module` extends `DatabaseEngineRegistry` with `"sqlite-memory": true`. +- Runtime: `registerEngine("sqlite-memory", factory)` against the api-db-adapter registry. +- Factory honours `DbAdapterOptions.url` → `filename` so callers may write `engine: "sqlite-memory"` + `url: ":memory:"` (or a file path). +- Forwards `tenantColumn` + `autoInjectInserts` so The wrapper composes correctly on top. +- Returns a disposer `() => boolean` that unregisters the engine. + +## Usage: Basic + +```ts +import { createDbAdapter } from "@suaveplan/api-db-adapter"; +import { registerSqliteMemoryEngine } from "@suaveplan/api-db-sqlite-memory/engine"; + +const dispose = registerSqliteMemoryEngine(); +const adapter = await createDbAdapter({ + engine: "sqlite-memory", + url: ":memory:", +}); +await adapter.admin.execute("CREATE TABLE t (id INTEGER PRIMARY KEY)"); +await adapter.close(); +dispose(); +``` + +## Usage: Advanced + +Test lifecycle with deterministic registry teardown: + +```ts +import { + afterEach, + beforeEach, + describe, + it, +} from "@suaveplan/testing/runner"; +import { createDbAdapter } from "@suaveplan/api-db-adapter"; +import { registerSqliteMemoryEngine } from "@suaveplan/api-db-sqlite-memory/engine"; + +describe("plugin install", () => { + let dispose: () => boolean; + beforeEach(() => { + dispose = registerSqliteMemoryEngine(); + }); + afterEach(() => { + dispose(); + }); + + it("resolves the engine sentinel", { timeout: 5000 }, async () => { + const adapter = await createDbAdapter({ + engine: "sqlite-memory", + url: ":memory:", + tenantColumn: "tenant_id", + }); + await adapter.close(); + }); +}); +``` + +## API Reference + +- `registerSqliteMemoryEngine()` — returns a disposer `() => boolean`. + +## Implementation Notes + +The declaration-merge happens inside this module so the type extension is only visible after the consumer imports from `@suaveplan/api-db-sqlite-memory/engine` (or the package root, which re-exports). That keeps the engine sentinel scoped to plugins that opt in, matching the design intent of the open `DatabaseEngineRegistry`. The factory normalises an empty or `"sqlite-memory:"` url to `":memory:"` because `createDbAdapter`'s Zod schema requires `url` to be non-empty — without this normalisation, callers would have to write `url: ":memory:"` redundantly even when the engine name already implies it. diff --git a/docs/api-stack/api/api-db-sqlite-memory/src/error-codes/error-codes.md b/docs/api-stack/api/api-db-sqlite-memory/src/error-codes/error-codes.md new file mode 100644 index 0000000..dd17af2 --- /dev/null +++ b/docs/api-stack/api/api-db-sqlite-memory/src/error-codes/error-codes.md @@ -0,0 +1,64 @@ +# `DB_SQLITE_MEMORY_*` error codes + + +_(no submodules)_ + + +## Purpose + +This module declares the stable error-code registry for `@suaveplan/api-db-sqlite-memory`. Every error thrown from the adapter, the migration runner, the tenant-scoping wrapper, or the engine registration helper extends `DbSqliteMemoryError` so consumers can branch on either `instanceof` or on the fully-qualified code string. + +The four-code registry intentionally mirrors `@suaveplan/api-db-adapter`'s `DB_ADAPTER_*` shape: `TENANT_SCOPE_VIOLATION`, `MIGRATION_FAILED`, `INVALID_OPTIONS`, and the SQLite-specific `OPEN_FAILED`. Tests assert each code is produced by at least one production path. + +## Features + +- Discriminated codes via `defineCodes("DB_SQLITE_MEMORY", [...])` — typed `${prefix}.${code}` template literal union. +- `DbSqliteMemoryError` extends `SuaveplanError` so `error.code` is narrowed to the union. +- Compatible with `@suaveplan/error`'s cause-chain traversal, redaction, and OTel span-event adapters. + +## Usage: Basic + +```ts +import { + DB_SQLITE_MEMORY_CODES, + DbSqliteMemoryError, +} from "@suaveplan/api-db-sqlite-memory/error-codes"; + +throw new DbSqliteMemoryError( + DB_SQLITE_MEMORY_CODES.INVALID_OPTIONS, + "filename must be ':memory:' or a non-empty string" +); +``` + +## Usage: Advanced + +Pattern-match on the code union inside a typed error boundary: + +```ts +try { + await createSqliteMemoryDb(opts); +} catch (err) { + if (err instanceof DbSqliteMemoryError) { + switch (err.code) { + case DB_SQLITE_MEMORY_CODES.OPEN_FAILED: + console.error("filesystem issue", err.cause); + break; + case DB_SQLITE_MEMORY_CODES.MIGRATION_FAILED: + console.error("schema migration aborted", err.context); + break; + default: + throw err; + } + } +} +``` + +## API Reference + +- `DB_SQLITE_MEMORY_CODES` — frozen `Record`. +- `DbSqliteMemoryCode` — union of every fully-qualified code string. +- `DbSqliteMemoryError` — constructor `(code, message, options?)`. + +## Implementation Notes + +`defineCodes` namespaces every entry under `DB_SQLITE_MEMORY.` at runtime — the dot-separated form is what surfaces in logs and OTel span events, so log scrapers can pivot on `DB_SQLITE_MEMORY.OPEN_FAILED` to root-cause early-boot failures distinct from upstream `DB_ADAPTER.ENGINE_UNSUPPORTED` messages. Keeping the namespace distinct from `DB_ADAPTER` lets operators tell at a glance whether the failure was inside the SQLite engine or inside the adapter façade that hosts it. diff --git a/docs/api-stack/api/api-db-sqlite-memory/src/factory/create-sqlite-memory-adapter.md b/docs/api-stack/api/api-db-sqlite-memory/src/factory/create-sqlite-memory-adapter.md new file mode 100644 index 0000000..869c0e7 --- /dev/null +++ b/docs/api-stack/api/api-db-sqlite-memory/src/factory/create-sqlite-memory-adapter.md @@ -0,0 +1,65 @@ +# `createSqliteMemoryAdapter` + +## Purpose + +Opens a real `bun:sqlite` `Database` and wraps it as an `AdminDatabaseLike`. The default zero-argument call yields a `:memory:` connection with `journal_mode=WAL` and `foreign_keys=ON` applied at boot — the canonical Stage-5 testing fixture. Every prepared statement, transaction, query, and execute path runs against the real SQLite engine; nothing is emulated. + +The adapter is the lowest layer in the package: it owns the `bun:sqlite` lifecycle, instruments the OTel histograms + error counter, and exposes the underlying `Database` handle via `getRawDatabase(admin)` so the migration runner can drive raw `BEGIN/COMMIT` when it needs to. Higher-level surfaces (`createSqliteMemoryDb`, the engine-registry factory, the `createInMemorySqliteHarness` builder) all delegate to this function. + +## Features + +- Real `bun:sqlite` `Database` — no shim, no interpreter. +- WAL + foreign-keys pragmas by default, every pragma overridable. +- `query` / `execute` / `prepare` / `transaction` all implemented. +- Real `BEGIN IMMEDIATE` / `COMMIT` / `ROLLBACK` so transaction semantics match production SQLite. +- OTel histograms `api.db.query_duration_ms`, `api.db.execute_duration_ms` and counter `api.db.errors_total`. +- Idempotent `close()` — repeated calls are a no-op. +- `DB_SQLITE_MEMORY.OPEN_FAILED` raised with the original error chained on `cause` when the `bun:sqlite` constructor throws. + +## Usage: Basic + +```ts +import { createSqliteMemoryAdapter } from "@suaveplan/api-db-sqlite-memory/adapter"; + +const admin = createSqliteMemoryAdapter(); +await admin.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)"); +await admin.execute("INSERT INTO users (name) VALUES (?)", ["alice"]); +const rows = await admin.query("SELECT * FROM users"); +await admin.close(); +``` + +## Usage: Advanced + +Open a file-backed fixture, disable WAL, and drive a transaction: + +```ts +import { createSqliteMemoryAdapter } from "@suaveplan/api-db-sqlite-memory/adapter"; + +const admin = createSqliteMemoryAdapter({ + filename: "/tmp/fixture.sqlite", + pragmas: { journal_mode: "DELETE", foreign_keys: "ON" }, +}); + +if (admin.transaction !== undefined) { + await admin.transaction(async (tx) => { + await tx.execute("CREATE TABLE t (id INTEGER PRIMARY KEY)"); + await tx.execute("INSERT INTO t (id) VALUES (1)"); + const r = await tx.query<{ id: number }[]>("SELECT * FROM t"); + if (r.length !== 1) throw new Error("rollback"); + }); +} + +await admin.close(); +``` + +## API Reference + +- `createSqliteMemoryAdapter(input?)` — returns an `AdminDatabaseLike`. +- `SQLITE_MEMORY_ENGINE` — the literal `"sqlite-memory"` engine sentinel string. +- `getAdapterInstruments()` — lazily-cached OTel histograms + error counter. +- `resetAdapterInstruments()` — test helper to drop the cache so a new MeterProvider is picked up. +- `getRawDatabase(admin)` — accessor for the underlying `bun:sqlite` `Database` handle when present; returns `undefined` for any non-matching adapter. + +## Implementation Notes + +The adapter intentionally calls prepare-per-query rather than caching prepared statements — Stage-5 tests are short-lived, the call overhead is dominated by the per-test SQLite open, and a stale statement cache would surprise tests that mutate schema between queries. The transaction implementation uses `BEGIN IMMEDIATE` for the same reason `@suaveplan/db-sqlite` does: it locks the database for write at transaction start, so a concurrent test reader cannot observe a partial mid-transaction view. The SQLite `run` method is preferred for `BEGIN/COMMIT/ROLLBACK` because the call returns a `Statement.RunResult` and any SQLite-level error surfaces synchronously, whereas a batch-execute path would silently swallow malformed PRAGMA values. diff --git a/docs/api-stack/api/api-db-sqlite-memory/src/factory/create-sqlite-memory-db.md b/docs/api-stack/api/api-db-sqlite-memory/src/factory/create-sqlite-memory-db.md new file mode 100644 index 0000000..585990c --- /dev/null +++ b/docs/api-stack/api/api-db-sqlite-memory/src/factory/create-sqlite-memory-db.md @@ -0,0 +1,75 @@ +# `createSqliteMemoryDb` + +## Purpose + +Stage-5 top-level testing factory. Combines `createSqliteMemoryAdapter` with the tenant-scoping wrapper from this package so callers get the canonical `{ admin, scoped, close }` triple in one call. This is the function the `@suaveplan/api-host/testing` adapter table reaches for when a plugin test asks for `engine: "sqlite-memory"`. + +The `admin` surface is the bare `AdminDatabaseLike` returned by the adapter — unscoped, useful for migrations and operator-style work. `scoped(tenantId)` produces a fresh `TenantScopedDatabaseLike` over the same underlying connection so route handlers see a tenant-bound surface that auto-injects (or rejects) cross-tenant payloads. `close()` is the idempotent shutdown. + +## Features + +- One-call assembly of admin + scoped + close. +- Tenant column + auto-inject mode forwarded from `SqliteMemoryDbOptions`. +- Both surfaces share the same `bun:sqlite` connection — closing once frees everything. +- The `admin.engine` field is `"sqlite-memory"`; `scoped().engine` matches. + +## Usage: Basic + +```ts +import { createSqliteMemoryDb } from "@suaveplan/api-db-sqlite-memory"; +import type { TenantId } from "@suaveplan/api-types/tenant"; + +const db = createSqliteMemoryDb(); +await db.admin.execute( + "CREATE TABLE notes (id INTEGER PRIMARY KEY, tenant_id TEXT, body TEXT)" +); +const tenant = "acme" as TenantId; +await db + .scoped(tenant) + .execute("INSERT INTO notes (body) VALUES (?)", ["hello"]); +const rows = await db.scoped(tenant).query("SELECT body FROM notes"); +await db.close(); +``` + +## Usage: Advanced + +Customise the tenant column and disable auto-inject so missing `org_id` payloads are rejected: + +```ts +import { createSqliteMemoryDb } from "@suaveplan/api-db-sqlite-memory"; +import type { TenantId } from "@suaveplan/api-types/tenant"; + +const db = createSqliteMemoryDb({ + tenantColumn: "org_id", + autoInjectInserts: false, +}); + +await db.admin.execute( + "CREATE TABLE items (id INTEGER PRIMARY KEY, org_id TEXT, name TEXT)" +); + +await db + .scoped("acme" as TenantId) + .execute("INSERT INTO items (org_id, name) VALUES (?, ?)", [ + "acme", + "widget", + ]); + +// Throws DB_SQLITE_MEMORY.TENANT_SCOPE_VIOLATION: +await db + .scoped("acme" as TenantId) + .execute("INSERT INTO items (name) VALUES (?)", ["broken"]); + +await db.close(); +``` + +## API Reference + +- `createSqliteMemoryDb(input?)` — returns `SqliteMemoryDb`. +- `SqliteMemoryDb.admin` — `AdminDatabaseLike` from `createSqliteMemoryAdapter`. +- `SqliteMemoryDb.scoped(tenantId)` — fresh `TenantScopedDatabaseLike`. +- `SqliteMemoryDb.close()` — idempotent close of the underlying database. + +## Implementation Notes + +The wrapper does not cache scoped instances — each `scoped(tenantId)` call builds a fresh `TenantScopedDatabaseLike` over the same admin connection. Caching would risk leaking a stale tenant binding between tests, and the wrapper is cheap enough that per-request construction is fine. Closing the admin closes the SQLite handle directly, so any outstanding scoped wrappers stop working at the same instant — there is no second close pass needed. diff --git a/docs/api-stack/api/api-db-sqlite-memory/src/migrations/migrations.md b/docs/api-stack/api/api-db-sqlite-memory/src/migrations/migrations.md new file mode 100644 index 0000000..c7e970f --- /dev/null +++ b/docs/api-stack/api/api-db-sqlite-memory/src/migrations/migrations.md @@ -0,0 +1,81 @@ +# `runSqliteMemoryMigrations` + + +_(no submodules)_ + + +## Purpose + +Lexicographic forward-only migration runner for the in-memory SQLite adapter. Applies every `*.sql` file in a directory in sorted order against an `AdminDatabaseLike`, recording each successful application in a host-managed `__plugin_migrations` table keyed by `(plugin, version)`. + +The runner is idempotent: re-running with no new files returns immediately. A failing migration throws `DB_SQLITE_MEMORY.MIGRATION_FAILED` with the offending file on `error.context.file`, and the transaction is rolled back so `__plugin_migrations` never reflects a half-applied state. + +## Features + +- Lexicographic ordering — `001_*.sql` runs before `002_*.sql`. +- Idempotent — re-running skips already-applied versions, returns them as `skipped`. +- Transactional per-file when the admin adapter supports `transaction()`; falls back to a plain `execute` pair when it does not. +- OTel `api.db.migrations_applied_total` counter + `api.db.migration_duration_ms` histogram emitted per applied file. +- Pluggable filesystem reader via `SqliteMigrationsFsReader` — tests pass an in-memory map; production uses `node:fs/promises`. +- Failed migrations throw `DB_SQLITE_MEMORY.MIGRATION_FAILED` with the original SQLite error chained on `cause`. + +## Usage: Basic + +```ts +import { readFile, readdir } from "node:fs/promises"; +import { createSqliteMemoryAdapter } from "@suaveplan/api-db-sqlite-memory"; +import { runSqliteMemoryMigrations } from "@suaveplan/api-db-sqlite-memory/migrations"; + +const admin = createSqliteMemoryAdapter(); +const result = await runSqliteMemoryMigrations({ + plugin: "users", + admin, + migrationsDir: "/abs/path/to/migrations", + fs: { readdir, readFile: (p) => readFile(p, "utf8") }, +}); +console.log(result.applied, result.skipped); +``` + +## Usage: Advanced + +In-memory filesystem reader for tests: + +```ts +import { + runSqliteMemoryMigrations, + type SqliteMigrationsFsReader, +} from "@suaveplan/api-db-sqlite-memory/migrations"; + +const files: Record = { + "001_init.sql": "CREATE TABLE notes (id INTEGER PRIMARY KEY)", + "002_body.sql": "ALTER TABLE notes ADD COLUMN body TEXT", +}; + +const fs: SqliteMigrationsFsReader = { + readdir: async () => Object.keys(files), + readFile: async (p) => { + const base = p.split("/").pop() as string; + const f = files[base]; + if (f === undefined) throw new Error(`missing: ${base}`); + return f; + }, +}; + +await runSqliteMemoryMigrations({ + plugin: "notes", + admin, + migrationsDir: "/virtual", + fs, +}); +``` + +## API Reference + +- `runSqliteMemoryMigrations(options)` — returns `{ applied, skipped }`. +- `SqliteMigrationsFsReader` — `readdir(dir)` + `readFile(path)` contract. +- `RunSqliteMemoryMigrationsOptions` — `plugin`, `admin`, `migrationsDir`, `fs`. +- `getMigrationInstruments()` / `resetMigrationInstruments()` — OTel cache hooks. + +## Implementation Notes + +The `__plugin_migrations` table uses a composite `(plugin, version)` primary key so multiple plugins can coexist in the same database without colliding on filenames. The runner queries the applied rows once per call and builds an in-memory `Set` rather than `SELECT EXISTS` per file — a plugin with a hundred migrations would otherwise run a hundred no-op queries on every restart. Lexicographic ordering is the same convention used by `@suaveplan/api-db-adapter`'s migration runner so plugin authors can move between in-memory and Postgres-backed engines without renaming migration files. diff --git a/docs/api-stack/api/api-db-sqlite-memory/src/options/sqlite-memory-db-options.md b/docs/api-stack/api/api-db-sqlite-memory/src/options/sqlite-memory-db-options.md new file mode 100644 index 0000000..f10475d --- /dev/null +++ b/docs/api-stack/api/api-db-sqlite-memory/src/options/sqlite-memory-db-options.md @@ -0,0 +1,65 @@ +# `SqliteMemoryDbOptions` + + +_(no submodules)_ + + +## Purpose + +Defines the Zod-validated options object accepted by `createSqliteMemoryDb`, `createSqliteMemoryAdapter`, and the engine-registry factory. Every field is optional and carries a default — the zero-argument call yields the canonical `:memory:` connection that the api-host testing kit uses by convention. + +The schema is the single source of truth for what a "valid in-memory SQLite test adapter" means inside Suaveplan. Both the direct factory and the engine registration helper pass raw caller input through `parseSqliteMemoryDbOptions` before doing any work, which means Zod issues surface as the same `DB_SQLITE_MEMORY.INVALID_OPTIONS` code no matter the entry point. + +## Features + +- `filename` defaults to `":memory:"`; any non-empty string accepted for file-backed fixtures. +- `tenantColumn` defaults to `"tenant_id"` — matches the column convention shared with `@suaveplan/api-db-adapter`. +- `migrationsDir` optional; consumed by `runSqliteMemoryMigrations`. +- `pragmas` merges atop `DEFAULT_PRAGMAS` (`journal_mode=WAL`, `foreign_keys=ON`). +- `autoInjectInserts` controls the tenant-scoping wrapper's strictness. +- `readonly` opens the underlying `bun:sqlite` `Database` in read-only mode. +- `resolvePragmas(options)` returns the effective pragma map without opening a connection — useful for tests + diagnostics. + +## Usage: Basic + +```ts +import { parseSqliteMemoryDbOptions } from "@suaveplan/api-db-sqlite-memory/options"; + +const opts = parseSqliteMemoryDbOptions(); +// opts.filename === ":memory:" +// opts.pragmas effective = { journal_mode: "WAL", foreign_keys: "ON" } +``` + +## Usage: Advanced + +Customise pragmas + override the tenant column while keeping every other default: + +```ts +import { + parseSqliteMemoryDbOptions, + resolvePragmas, +} from "@suaveplan/api-db-sqlite-memory/options"; + +const opts = parseSqliteMemoryDbOptions({ + filename: "/tmp/fixture.sqlite", + tenantColumn: "org_id", + pragmas: { foreign_keys: "OFF", synchronous: "FULL" }, + autoInjectInserts: false, +}); + +const effective = resolvePragmas(opts); +// { journal_mode: "WAL", foreign_keys: "OFF", synchronous: "FULL" } +``` + +## API Reference + +- `SqliteMemoryDbOptionsSchema` — the Zod schema object. +- `SqliteMemoryDbOptions` — `z.infer` of the schema. +- `SqliteMemoryDbOptionsInput` — `z.input` of the schema. +- `parseSqliteMemoryDbOptions(input?)` — parse + throw `DbSqliteMemoryError` on failure. +- `resolvePragmas(options)` — final merged pragma map. +- `DEFAULT_PRAGMAS` — `{ journal_mode: "WAL", foreign_keys: "ON" }`. + +## Implementation Notes + +The schema deliberately uses `z.record(z.string(), z.string())` for `pragmas` rather than a closed enum — SQLite ships dozens of pragmas and operators occasionally want to flip `synchronous`, `temp_store`, or `cache_size` for fixture warm-up. The merge order (`{ ...DEFAULT_PRAGMAS, ...options.pragmas }`) means a caller can disable any default by re-supplying the same key, so the policy is "safe defaults, full override". Field-level `.default(...)` calls run inside `.safeParse`, so `parseSqliteMemoryDbOptions(undefined)` is the same as passing `{}` — handy for the engine-registry path where the adapter url-fragment may legitimately be empty. diff --git a/docs/api-stack/api/api-db-sqlite-memory/src/tenant-scoping/tenant-scoping.md b/docs/api-stack/api/api-db-sqlite-memory/src/tenant-scoping/tenant-scoping.md new file mode 100644 index 0000000..33177e3 --- /dev/null +++ b/docs/api-stack/api/api-db-sqlite-memory/src/tenant-scoping/tenant-scoping.md @@ -0,0 +1,81 @@ +# `createTenantScopedSqliteWrapper` + + +_(no submodules)_ + + +## Purpose + +Wraps an `AdminDatabaseLike` as a `TenantScopedDatabaseLike` that transparently injects the resolved tenant id into every SELECT/UPDATE/DELETE and validates (or auto-injects) the same column on INSERTs. The wrapper is engine-agnostic in shape but ships with this package because its error code namespace is `DB_SQLITE_MEMORY.*` — the SQL-rewrite algorithm mirrors `@suaveplan/api-db-adapter` so behaviour is identical to The path. + +The wrapper is what `RequestContext.db` resolves to inside route handlers when the host has installed the in-memory engine; tests using `createSqliteMemoryDb` go through `scoped(tenantId)` and never touch the admin connection directly. + +## Features + +- SELECT/UPDATE/DELETE: `WHERE tenant_id = ?` (or `AND tenant_id = ?` if a WHERE already exists), preserving `ORDER BY` / `LIMIT` / `GROUP BY` / `RETURNING` tail clauses. +- INSERT: auto-injects the tenant column when `autoInjectInserts: true`; rejects with `DB_SQLITE_MEMORY.TENANT_SCOPE_VIOLATION` when `false` and the column is missing. +- INSERT with a literal mismatched tenant value → `TENANT_SCOPE_VIOLATION`. +- INSERT with a bound `?` parameter whose value mismatches the bound tenant → `TENANT_SCOPE_VIOLATION`. +- DDL / non-CRUD statements rejected — use the admin surface for migrations. +- Record-style params (named binds) rejected — wrapper is positional only. +- `prepare` + `transaction` are forwarded with rewritten SQL. + +## Usage: Basic + +```ts +import { createSqliteMemoryAdapter } from "@suaveplan/api-db-sqlite-memory"; +import { createTenantScopedSqliteWrapper } from "@suaveplan/api-db-sqlite-memory/tenant-scoping"; +import type { TenantId } from "@suaveplan/api-types/tenant"; + +const admin = createSqliteMemoryAdapter(); +await admin.execute( + "CREATE TABLE users (id INTEGER PRIMARY KEY, tenant_id TEXT, name TEXT)" +); +const acme = createTenantScopedSqliteWrapper(admin, "acme" as TenantId); +await acme.execute("INSERT INTO users (name) VALUES (?)", ["alice"]); +// SQL rewritten to: INSERT INTO users (name, tenant_id) VALUES (?, ?) +const rows = await acme.query("SELECT * FROM users"); +// SQL rewritten to: SELECT * FROM users WHERE tenant_id = ? +``` + +## Usage: Advanced + +Strict mode + bound-param mismatch surfacing: + +```ts +import { + DB_SQLITE_MEMORY_CODES, + DbSqliteMemoryError, +} from "@suaveplan/api-db-sqlite-memory"; +import { createTenantScopedSqliteWrapper } from "@suaveplan/api-db-sqlite-memory/tenant-scoping"; + +const strict = createTenantScopedSqliteWrapper(admin, "acme" as TenantId, { + autoInjectInserts: false, +}); + +try { + await strict.execute("INSERT INTO users (tenant_id, name) VALUES (?, ?)", [ + "bigcorp", + "bob", + ]); +} catch (err) { + if ( + err instanceof DbSqliteMemoryError && + err.code === DB_SQLITE_MEMORY_CODES.TENANT_SCOPE_VIOLATION + ) { + // bound tenant "bigcorp" does not match scope "acme" + } +} +``` + +## API Reference + +- `createTenantScopedSqliteWrapper(admin, tenantId, options?)` — returns `TenantScopedDatabaseLike`. +- `TenantScopedSqliteWrapperOptions.tenantColumn` — default `"tenant_id"`. +- `TenantScopedSqliteWrapperOptions.autoInjectInserts` — default `true`. +- `sqliteRewriters.injectWhere` — pure helper exposed for unit tests. +- `sqliteRewriters.handleInsert` — pure helper exposed for unit tests. + +## Implementation Notes + +The rewriter does string parsing on the SQL because SQLite does not expose an AST visitor that would let us bolt-on a tenant predicate at the engine level. The closed grammar of supported shapes (single-row INSERT, simple SELECT/UPDATE/DELETE with optional trailing clauses) keeps the regex set small and auditable — anything outside that grammar throws `TENANT_SCOPE_VIOLATION` so callers cannot silently bypass the policy. Tail-clause detection finds the first of `RETURNING/ORDER BY/LIMIT/GROUP BY` and splices the predicate before it; without that, appending the predicate to the bare SQL would corrupt `LIMIT 10` into `LIMIT 10 WHERE ...`. diff --git a/docs/api-stack/api/api-db-sqlite-memory/src/testing/harness.md b/docs/api-stack/api/api-db-sqlite-memory/src/testing/harness.md new file mode 100644 index 0000000..bbe10f4 --- /dev/null +++ b/docs/api-stack/api/api-db-sqlite-memory/src/testing/harness.md @@ -0,0 +1,68 @@ +# `createInMemorySqliteHarness` + + +_(no submodules)_ + + +## Purpose + +Convenience builder for plugin test files. Wraps `createSqliteMemoryDb` with an idempotent `cleanup()` so the canonical `beforeEach` / `afterEach` pair stays one line each. The result conforms to `SqliteMemoryDb` so callers can treat the harness exactly like a direct factory return value, with the bonus that double-cleanup is safe — the second call observes the `closed` flag and returns without touching the database. + +This is the entry point Stage-5 plugin tests should reach for. Direct construction via `createSqliteMemoryDb` works too, but the harness keeps the test boilerplate uniform across packages. + +## Features + +- Same shape as `SqliteMemoryDb` plus an extra `cleanup` method. +- Idempotent `cleanup` — safe to call from both an explicit teardown and a try/finally. +- Forwards every `SqliteMemoryDbOptions` field to `createSqliteMemoryDb`. + +## Usage: Basic + +```ts +import { afterEach, beforeEach, it } from "@suaveplan/testing/runner"; +import { + createInMemorySqliteHarness, + type InMemorySqliteHarness, +} from "@suaveplan/api-db-sqlite-memory/testing"; + +let harness: InMemorySqliteHarness; +beforeEach(() => { + harness = createInMemorySqliteHarness(); +}); +afterEach(() => harness.cleanup()); + +it("inserts a row", { timeout: 5000 }, async () => { + await harness.admin.execute( + "CREATE TABLE t (id INTEGER PRIMARY KEY, tenant_id TEXT)" + ); +}); +``` + +## Usage: Advanced + +Customise the tenant column + open a file-backed fixture for a longer-lived test: + +```ts +import { createInMemorySqliteHarness } from "@suaveplan/api-db-sqlite-memory/testing"; + +const harness = createInMemorySqliteHarness({ + filename: "/tmp/long-fixture.sqlite", + tenantColumn: "org_id", +}); +try { + await harness.admin.execute( + "CREATE TABLE items (id INTEGER PRIMARY KEY, org_id TEXT)" + ); +} finally { + await harness.cleanup(); +} +``` + +## API Reference + +- `createInMemorySqliteHarness(options?)` — returns `InMemorySqliteHarness`. +- `InMemorySqliteHarness` — extends `SqliteMemoryDb` with `cleanup(): Promise`. + +## Implementation Notes + +`cleanup()` and `close()` share the same idempotency flag — the harness owns the `closed` boolean and the `close()` method on the embedded `SqliteMemoryDb` is exposed verbatim so legacy code that still calls `close` does not silently bypass the flag. This matters when a test file mixes a manual `close()` with an `afterEach` cleanup: the second of the two is a guaranteed no-op rather than a hard error from `bun:sqlite`'s "database already closed" path. diff --git a/docs/api-stack/api/api-db-worker-proxy/README.md b/docs/api-stack/api/api-db-worker-proxy/README.md new file mode 100644 index 0000000..7d7200a --- /dev/null +++ b/docs/api-stack/api/api-db-worker-proxy/README.md @@ -0,0 +1,112 @@ +# @suaveplan/api-db-worker-proxy - Worker-side proxy for the api `db` capability. Marshals AdminDatabaseLike / TenantScopedDatabaseLike calls — including transactions and cursor streams — over @suaveplan/api-worker-rpc MessagePort frames. Tenant scoping is enforced main-side; this package is the transport. + +Worker-side proxy for the api `db` capability. Marshals +`AdminDatabaseLike` and `TenantScopedDatabaseLike` calls — including +transactions and cursor streams — over `@suaveplan/api-worker-rpc` +`MessagePort` frames. + +The main side mounts a real DB adapter and exposes it over a port; +the worker side imports a proxy whose API surface is identical to a +direct adapter. Worker plugin code never touches a real connection +and never sees plaintext credentials. + +**Tenant scoping is enforced on the main side**, NOT in this package. +`wrapTenantScoped(adminProxy, tenantId)` is purely a type-level facade +that prevents an admin reference from being passed where a tenant +reference is required by the type system. + + +## Documentation tree + +- [error-codes](./src/error-codes/error-codes.md) — This module owns the `DB_PROXY.*` stable error-code registry for `@suaveplan/api-db-worker-proxy`. Every failure that c… + - [error-codes](./src/error-codes/error-codes.md) — This module owns the `DB_PROXY.*` stable error-code registry for `@suaveplan/api-db-worker-proxy`. Every failure that c… +- [main-side](./src/main-side/main-side.md) — This module exposes `createDbProxyServer(port, db)` — the trusted-side endpoint of the worker DB proxy. It mounts an `A… + - [main-side](./src/main-side/main-side.md) — This module exposes `createDbProxyServer(port, db)` — the trusted-side endpoint of the worker DB proxy. It mounts an `A… +- [tenant-scoped](./src/tenant-scoped/tenant-scoped.md) — This module exposes `wrapTenantScoped(adminProxy, tenantId)` — a worker-side type-level facade that re-presents an admi… + - [tenant-scoped](./src/tenant-scoped/tenant-scoped.md) — This module exposes `wrapTenantScoped(adminProxy, tenantId)` — a worker-side type-level facade that re-presents an admi… +- [testing](./src/testing/testing.md) — This module provides the in-memory test harness for `@suaveplan/api-db-worker-proxy`. It exposes `createInMemoryAdminDb… + - [testing](./src/testing/testing.md) — This module provides the in-memory test harness for `@suaveplan/api-db-worker-proxy`. It exposes `createInMemoryAdminDb… +- [worker-side](./src/worker-side/worker-side.md) — This module exposes `createDbProxyClient(port, { engine })` — the untrusted-side endpoint of the worker DB proxy. It re… + - [worker-side](./src/worker-side/worker-side.md) — This module exposes `createDbProxyClient(port, { engine })` — the untrusted-side endpoint of the worker DB proxy. It re… + + +## Why + +Per the `api-plugin` foundation design (§5.1, §5.2a, §6) every +capability ships in two surfaces: a direct in-process binding for +trusted plugins and a `MessagePort`-marshalled binding for +isolated / sandboxed plugins. The `db` capability is special because + +1. its operations return result sets that can be huge (favouring + streaming over buffering), +2. its operations are transactional (transaction handles MUST be + bound to a single connection lifetime), and +3. tenant-scoping is a security boundary the worker MUST NOT be able + to circumvent. + +This package is Stage-3 worker-isolation infrastructure: every +Stage-4 DB adapter (`api-db-adapter`, `api-db-sqlite-memory`, …) MUST +pass conformance under BOTH the direct surface AND this proxy +surface before can be declared complete. + +## Install + +```bash +bun add @suaveplan/api-db-worker-proxy +``` + +## Quick start + +```ts +// main side +import { createDbProxyServer } from "@suaveplan/api-db-worker-proxy/main-side"; +import { MessageChannel, Worker } from "node:worker_threads"; + +const channel = new MessageChannel(); +createDbProxyServer(channel.port1, realAdminAdapter); + +const worker = new Worker("./plugin-worker.js"); +worker.postMessage({ port: channel.port2, engine: "sqlite" }, [channel.port2]); +``` + +```ts +// worker side +import { parentPort } from "node:worker_threads"; +import { createDbProxyClient } from "@suaveplan/api-db-worker-proxy/worker-side"; +import { wrapTenantScoped } from "@suaveplan/api-db-worker-proxy/tenant-scoped"; +import type { TenantId } from "@suaveplan/api-types/tenant"; + +parentPort?.once("message", (boot) => { + const admin = createDbProxyClient(boot.port, { engine: boot.engine }); + + // request scope + const tenantScoped = wrapTenantScoped(admin, "acme" as TenantId); + void runHandler(tenantScoped); +}); +``` + +## Surface + +- `./main-side` — `createDbProxyServer(port, db)`: serves an + `AdminDatabaseLike` over `@suaveplan/api-worker-rpc`. Returns a + `DbProxyServer` with `close()`, `activeTransactionCount()`, + `activePreparedCount()`. +- `./worker-side` — `createDbProxyClient(port, { engine })`: returns + an `AdminDatabaseLike`-shaped object plus `cursor(sql, params)` + for streaming row iteration and `dispose()` for abrupt teardown. +- `./tenant-scoped` — `wrapTenantScoped(adminProxy, tenantId)`: + type-level facade. Tenant scoping is enforced main-side. +- `./error-codes` — `DB_PROXY.*` codes: + `UNSAFE_NOT_PERMITTED`, `TRANSACTION_LOST`, `STREAM_INTERRUPTED`, + `PROXY_DISPOSED`. +- `./testing` — `createInMemoryAdminDb` + `createDbProxyHarness` for + downstream conformance suites. + +## Co-located docs + +- [`src/main-side/main-side.md`](./src/main-side/main-side.md) +- [`src/worker-side/worker-side.md`](./src/worker-side/worker-side.md) +- [`src/tenant-scoped/tenant-scoped.md`](./src/tenant-scoped/tenant-scoped.md) +- [`src/error-codes/error-codes.md`](./src/error-codes/error-codes.md) +- [`src/testing/testing.md`](./src/testing/testing.md) + diff --git a/docs/api-stack/api/api-db-worker-proxy/src/error-codes/error-codes.md b/docs/api-stack/api/api-db-worker-proxy/src/error-codes/error-codes.md new file mode 100644 index 0000000..20ae60e --- /dev/null +++ b/docs/api-stack/api/api-db-worker-proxy/src/error-codes/error-codes.md @@ -0,0 +1,81 @@ +# `error-codes` + + +_(no submodules)_ + + +## Purpose + +This module owns the `DB_PROXY.*` stable error-code registry for +`@suaveplan/api-db-worker-proxy`. Every failure that crosses the public +surface — proxy disposed, transaction lost, cursor stream interrupted, +unsafe-call attempt against a tenant-scoped wrapper — is raised as a +`DbProxyError` carrying one of these four codes so consumers can +discriminate without string-matching messages. + +The codes are stable across the package lifecycle: once published, the +literal value is frozen. New codes are added by extending the +`defineCodes` tuple; never by renaming. + +## Features + +- `DB_PROXY_CODES` — frozen registry of fully-qualified code strings. +- `DbProxyCode` — string-literal union of every registered code. +- `DbProxyError` — typed subclass of `SuaveplanError` + carrying the code, cause chain, and Zod-wire-safe serialisation + inherited from `@suaveplan/error`. + +## Usage: Basic + +```ts +import { + DB_PROXY_CODES, + DbProxyError, +} from "@suaveplan/api-db-worker-proxy/error-codes"; + +throw new DbProxyError( + DB_PROXY_CODES.PROXY_DISPOSED, + "cannot call .query() after .close()" +); +``` + +## Usage: Advanced + +Branch on the code, not the message. The code is part of the public +contract; messages are free text and change without notice. + +```ts +try { + await proxy.query("SELECT 1"); +} catch (err) { + if (err instanceof DbProxyError) { + switch (err.code) { + case DB_PROXY_CODES.PROXY_DISPOSED: + return reopenProxy(); + case DB_PROXY_CODES.TRANSACTION_LOST: + return retryUnit(); + case DB_PROXY_CODES.STREAM_INTERRUPTED: + return reissueCursor(); + case DB_PROXY_CODES.UNSAFE_NOT_PERMITTED: + throw err; // never retry an unsafe path. + } + } + throw err; +} +``` + +## API Reference + +- `DB_PROXY_CODES: { UNSAFE_NOT_PERMITTED, TRANSACTION_LOST, STREAM_INTERRUPTED, PROXY_DISPOSED }` — frozen mapping of short names to fully-qualified code strings (`"DB_PROXY."`). +- `type DbProxyCode = (typeof DB_PROXY_CODES)[keyof typeof DB_PROXY_CODES]`. +- `class DbProxyError extends SuaveplanError` — constructor `(code, message, options?)` where `options` accepts a `cause` and arbitrary `details`. + +## Implementation Notes + +The registry is built via `defineCodes("DB_PROXY", [...] as const)` so +that adding a code without updating both the runtime registry and the +type union is a compile error. `DbProxyError`'s `name` is set to +`"DbProxyError"` so structured logs and `errorToEnvelope` round-trip +correctly across the worker boundary — `@suaveplan/api-worker-rpc`'s +error-reconstruction layer will reconstruct the class by `code` even +when the original prototype isn't reachable on the other side. diff --git a/docs/api-stack/api/api-db-worker-proxy/src/main-side/main-side.md b/docs/api-stack/api/api-db-worker-proxy/src/main-side/main-side.md new file mode 100644 index 0000000..5a04518 --- /dev/null +++ b/docs/api-stack/api/api-db-worker-proxy/src/main-side/main-side.md @@ -0,0 +1,85 @@ +# `main-side` + + +_(no submodules)_ + + +## Purpose + +This module exposes `createDbProxyServer(port, db)` — the trusted-side +endpoint of the worker DB proxy. It mounts an `AdminDatabaseLike` +adapter on a `MessagePort` and turns every worker-issued RPC frame +into a real call on the wrapped adapter. The main side is the only +side that touches the underlying DB driver; the worker code that +imported `@suaveplan/api-db-worker-proxy/worker-side` never sees a +real connection, never sees plaintext credentials, and cannot +fabricate a tenant identity. + +The server keeps a registry of live transaction handles and prepared +statements keyed by id so the worker can drive them across multiple +round-trips without leaking driver handles into the worker's address +space. + +## Features + +- Marshals `query`, `execute`, `prepare`, `transaction`, `cursor`, + `engine`, and `close` over `@suaveplan/api-worker-rpc`. +- Streams cursor rows as `stream-chunk` frames; worker-side break + triggers `cancel` which the handler observes via its `AbortSignal`. +- Bounds transaction lifetimes by port: closing the server (or + receiving `goodbye`) raises `TRANSACTION_LOST` on every dangling + handle rather than leaking driver state. +- Exposes diagnostic counters `activeTransactionCount` and + `activePreparedCount`. + +## Usage: Basic + +```ts +import { createDbProxyServer } from "@suaveplan/api-db-worker-proxy/main-side"; +import { Worker, MessageChannel } from "node:worker_threads"; + +const channel = new MessageChannel(); +const server = createDbProxyServer(channel.port1, realAdapter); + +const worker = new Worker("./worker.js"); +worker.postMessage({ port: channel.port2 }, [channel.port2]); +``` + +## Usage: Advanced + +When the host needs to scope the adapter per request, pass an +already-tenant-scoped adapter to a per-request server. The proxy +itself does NOT rewrite SQL — that responsibility lives in the +adapter the host hands in here. `wrapTenantScoped` on the worker +side is purely a type-level facade. + +```ts +const scoped = realAdapter.scopedFor(tenantId); // host responsibility +const server = createDbProxyServer(port, scoped); +// shut down at request end: +server.close("request finished"); +``` + +## API Reference + +- `createDbProxyServer(port: PortLike, db: AdminDatabaseLike): DbProxyServer`. +- `DbProxyServer.close(reason?: string): void` — closes the server, + rolling back live transactions and finalising prepared statements. +- `DbProxyServer.activeTransactionCount(): number`. +- `DbProxyServer.activePreparedCount(): number`. + +## Implementation Notes + +The cursor handler returns an `AsyncGenerator`; `serveWorkerRpc`'s +streaming path interprets the return as `AsyncIterable` and +emits one `stream-chunk` per yield, then `stream-end ok`. Cancellation +from the worker comes in as an `AbortSignal.aborted = true` on the +handler's `signal`; the generator throws `STREAM_INTERRUPTED` which +the server marshals as `stream-end ok=false` carrying the +`DB_PROXY.STREAM_INTERRUPTED` code. + +Transactions are implemented by holding the adapter's `transaction()` +promise open until either `tx.commit` or `tx.rollback` fires from the +worker. Rolling back is signalled by throwing inside the adapter +callback, which mirrors the adapter's own rollback semantics without +adding a parallel state machine. diff --git a/docs/api-stack/api/api-db-worker-proxy/src/tenant-scoped/tenant-scoped.md b/docs/api-stack/api/api-db-worker-proxy/src/tenant-scoped/tenant-scoped.md new file mode 100644 index 0000000..bbbe692 --- /dev/null +++ b/docs/api-stack/api/api-db-worker-proxy/src/tenant-scoped/tenant-scoped.md @@ -0,0 +1,81 @@ +# `tenant-scoped` + + +_(no submodules)_ + + +## Purpose + +This module exposes `wrapTenantScoped(adminProxy, tenantId)` — a +worker-side type-level facade that re-presents an admin-surface +`AdminDatabaseLike` as a `TenantScopedDatabaseLike`. The facade +matters because the two surface types are deliberately +non-assignable in `@suaveplan/api-types`: a request handler declared +to accept `TenantScopedDatabaseLike` MUST NOT accidentally receive +an unscoped admin proxy, and vice versa. + +**Tenant scoping is enforced on the main side.** The actual SQL +rewrite / row-level security / connection routing all live in the +host's adapter. This wrapper does NOT add policy; it asserts a +shape so the type system can guarantee the slot in the request +context has been narrowed to a tenant. + +## Features + +- Returns a fresh facade object on every call so the same admin + proxy can back many concurrent request scopes. +- Exposes `tenantId` on the returned object for audit logging. +- Preserves the optional `prepare` / `transaction` capabilities only + if the admin proxy advertised them; absent capabilities throw + `DB_PROXY.UNSAFE_NOT_PERMITTED`. +- `close` is intentionally omitted because + `TenantScopedDatabaseLike` does not expose it — the admin proxy + retains lifecycle ownership. + +## Usage: Basic + +```ts +import { wrapTenantScoped } from "@suaveplan/api-db-worker-proxy/tenant-scoped"; +import type { TenantId } from "@suaveplan/api-types/tenant"; + +const tenantId = "acme" as TenantId; +const scoped = wrapTenantScoped(adminProxy, tenantId); +const rows = await scoped.query("SELECT * FROM invoices"); +``` + +## Usage: Advanced + +Use the facade inside a request middleware that materialises +`RequestContext.db`. The middleware constructs the wrapper from the +already-resolved `tenantId` so route handlers only ever see the +tenant-scoped type. + +```ts +function attachDb(adminProxy: AdminDatabaseLike) { + return async (c: Context, next: Next): Promise => { + const tenantId = c.get("tenantId") as TenantId; + const scoped = wrapTenantScoped(adminProxy, tenantId); + c.set("db", scoped); + await next(); + }; +} +``` + +## API Reference + +- `wrapTenantScoped(adminProxy: AdminDatabaseLike, tenantId: TenantId): TenantScopedDatabaseLike`. +- Throws `DB_PROXY.UNSAFE_NOT_PERMITTED` from `prepare` / `transaction` + when the underlying admin proxy doesn't expose that capability. + +## Implementation Notes + +The wrapper rebinds `prepare` and `transaction` so the underlying +admin proxy's `this`-context survives the indirection (the methods +are looked up off the proxy each call, not captured eagerly, so +admin-side disposal is observed on the next call rather than at wrap +time). + +The `tenantId` field is set on the returned object purely so audit +loggers and `RequestContext` consumers can read it directly. The +field name and type match `TenantScopedDatabaseLike.tenantId` +exactly; both are `TenantId` (a branded string). diff --git a/docs/api-stack/api/api-db-worker-proxy/src/testing/testing.md b/docs/api-stack/api/api-db-worker-proxy/src/testing/testing.md new file mode 100644 index 0000000..296b14a --- /dev/null +++ b/docs/api-stack/api/api-db-worker-proxy/src/testing/testing.md @@ -0,0 +1,97 @@ +# `testing` + + +_(no submodules)_ + + +## Purpose + +This module provides the in-memory test harness for +`@suaveplan/api-db-worker-proxy`. It exposes `createInMemoryAdminDb` +— a deterministic `AdminDatabaseLike` backed by a `Map` — and +`createDbProxyHarness`, which pairs that adapter with a real +`MessageChannel`, a `createDbProxyServer` on one port, and a +`createDbProxyClient` on the other. Tests can drive the full +client-port-server-adapter chain end-to-end without a real DB and +without any mocking framework. + +The harness exists in `src/testing/` (rather than `tests/`) so it +can be imported by downstream Stage-4 adapter packages from the +package's `"./testing"` subpath export. + +## Features + +- `createInMemoryAdminDb({ engine?, seed?, cursorDelayMs? })` — a + full `AdminDatabaseLike` implementation including `prepare`, + `transaction`, and a synthetic `SELECT-CURSOR *` that returns an + `AsyncIterable` for cursor streaming tests. +- `createDbProxyHarness(opts)` — bundles adapter + ports + server + + client into one disposable handle. +- Tiny command DSL (`INSERT `, `DELETE `, `SELECT *`, + `SELECT-CURSOR *`, `COUNT`, `SELECT-SCALAR`, `THROW`) chosen so + every code path in the proxy can be exercised without parsing real + SQL. + +## Usage: Basic + +```ts +import { createDbProxyHarness } from "@suaveplan/api-db-worker-proxy/testing"; + +const h = createDbProxyHarness({ seed: [["a", { v: 1 }]] }); +try { + expect(await h.client.query("SELECT *")).toEqual([{ v: 1 }]); +} finally { + await h.client.close(); + h.close(); +} +``` + +## Usage: Advanced + +To assert that cursor cancellation propagates, set a per-row delay +on the in-memory cursor and abort partway through: + +```ts +const h = createDbProxyHarness({ + seed: Array.from({ length: 100 }, (_, i) => [String(i), { i }]), + cursorDelayMs: 5, +}); +try { + const ac = new AbortController(); + let n = 0; + for await (const _row of h.client.cursor("SELECT-CURSOR *", undefined, { + signal: ac.signal, + })) { + if (++n >= 3) { + ac.abort(); + break; + } + } + expect(n).toBe(3); +} finally { + await h.client.close(); + h.close(); +} +``` + +## API Reference + +- `createInMemoryAdminDb(opts?): InMemoryAdminDb` — `AdminDatabaseLike` + plus `rows: ReadonlyMap` and `closed(): boolean` + for assertions. +- `createDbProxyHarness(opts?): DbProxyHarness` — `{ db, server, + client, ports, close() }`. +- `InMemoryAdminDbOptions` — `{ engine?, seed?, cursorDelayMs? }`. + +## Implementation Notes + +The in-memory adapter ignores parameter placeholders for `INSERT` / +`DELETE` and instead encodes the row key in the SQL string. This is +intentional — the harness exists to exercise the proxy plumbing, not +to validate a real query language. Concrete adapters (Stage 4) ship +their own conformance suites under their own engine semantics. + +The harness's `close()` does NOT call `client.close()` so tests can +choose between observing graceful close (`await client.close()`) and +abrupt disconnect (`client.dispose()`, then `harness.close()`). Both +paths are first-class. diff --git a/docs/api-stack/api/api-db-worker-proxy/src/worker-side/worker-side.md b/docs/api-stack/api/api-db-worker-proxy/src/worker-side/worker-side.md new file mode 100644 index 0000000..580fe1c --- /dev/null +++ b/docs/api-stack/api/api-db-worker-proxy/src/worker-side/worker-side.md @@ -0,0 +1,96 @@ +# `worker-side` + + +_(no submodules)_ + + +## Purpose + +This module exposes `createDbProxyClient(port, { engine })` — the +untrusted-side endpoint of the worker DB proxy. It returns an +`AdminDatabaseLike`-shaped object whose methods marshal across a +`MessagePort` to the main side's `createDbProxyServer`. Worker plugin +code uses the returned proxy exactly as it would use a direct adapter +— `await db.query(...)`, `await db.transaction(async (tx) => ...)` — +without knowing the real connection lives in another process. + +The factory is synchronous because `AdminDatabaseLike.engine` is a +synchronous getter; the caller supplies the engine identifier +up-front (the host knows which engine it has provisioned, so this is +free information). + +## Features + +- Full `AdminDatabaseLike` surface: `query`, `execute`, `prepare`, + `transaction`, `close`, `engine`. +- Bonus `cursor(sql, params)` returns an `AsyncIterable` + backed by `@suaveplan/api-worker-rpc` streaming; consumer `break` + cancels the main-side cursor. +- `transaction(fn)` auto-commits on resolve and auto-rolls-back on + reject; the inner `tx` handle becomes invalid after the callback + resolves and any subsequent call throws `DB_PROXY.TRANSACTION_LOST`. +- `dispose()` (alongside the interface's `close`) tears down the + underlying port without invoking the main-side `close()` handler. + +## Usage: Basic + +```ts +import { createDbProxyClient } from "@suaveplan/api-db-worker-proxy/worker-side"; + +const db = createDbProxyClient(port, { engine: "sqlite" }); +const rows = await db.query("SELECT * FROM users"); +``` + +## Usage: Advanced + +Streaming a large cursor without buffering everything in worker +memory: + +```ts +const ac = new AbortController(); +let seen = 0; +for await (const row of db.cursor("SELECT-CURSOR *", undefined, { + signal: ac.signal, +})) { + if (++seen >= 100) { + ac.abort(); + break; + } + process(row); +} +``` + +`db.transaction` wires commit/rollback through the same port, so the +main-side transaction is bound to the worker's logical scope: + +```ts +await db.transaction(async (tx) => { + await tx.execute("INSERT user-1", { name: "Alice" }); + await tx.execute("INSERT user-2", { name: "Bob" }); +}); // auto-commit +``` + +## API Reference + +- `createDbProxyClient(port, opts): DbProxyClient` — extends + `AdminDatabaseLike` with `cursor(...)` and `dispose()`. +- `DbProxyClientOptions.engine: DatabaseEngine` — supplied by host. +- `DbProxyClient.cursor(sql, params?, { signal? }): AsyncIterable`. +- `DbProxyClient.dispose(): void` — close port without server round-trip. + +## Implementation Notes + +Cursor iteration wraps `streamRequest` from +`@suaveplan/api-worker-rpc` so the same backpressure policy (default +64-frame bounded queue) governs row delivery. The wrapper translates +any non-`DbProxyError` exception coming up from the stream into +`DB_PROXY.STREAM_INTERRUPTED` so consumers can branch uniformly on +the proxy's error namespace. + +`transaction(fn)` uses a closure-flag (`inScope`) to gate every `tx` +method; after the callback resolves and the proxy issues `tx.commit`, +the flag flips and any leaked reference to `tx` throws +`DB_PROXY.TRANSACTION_LOST`. The auto-commit is suppressed if the +callback already invoked `tx.commit` itself (the second commit +would otherwise raise `TRANSACTION_LOST` from the main side, which +this layer catches and silences). diff --git a/docs/api-stack/api/api-events-in-memory/README.md b/docs/api-stack/api/api-events-in-memory/README.md new file mode 100644 index 0000000..e900166 --- /dev/null +++ b/docs/api-stack/api/api-events-in-memory/README.md @@ -0,0 +1,105 @@ +# @suaveplan/api-events-in-memory - In-memory EventsBus adapter for the @suaveplan/api testing kit. Wraps @suaveplan/events' EventBus with a per-topic recording layer so tests can assert that side-effect publishes happened. Exposes published(topic) and reset() helpers, options-bounded history with EVENTS_IN_MEMORY.HISTORY_OVERFLOW protection, Zod-validated options at the boundary, and a small waitFor harness for async assertions. No mocks — the real production bus delivers events to subscribers; this adapter only records publish history. + +In-memory events bus adapter for the `@suaveplan/api` testing kit. +Wraps `@suaveplan/events`' production `EventBus` with a per-topic +recording layer so tests can assert that side-effect publishes +happened, without booting cross-process IPC and without mocks. The +real bus delivers events to subscribers; this adapter only adds a +queryable publish history. + + +## Documentation tree + +- [bus](./src/bus/bus.md) — `createInMemoryEventsBus` is the factory entry point of `@suaveplan/api-events-in-memory`. It returns a fresh {@link In… + - [bus](./src/bus/bus.md) — `createInMemoryEventsBus` is the factory entry point of `@suaveplan/api-events-in-memory`. It returns a fresh {@link In… +- [error-codes](./src/error-codes/error-codes.md) — The error-code registry pins the two failure modes that the in-memory events bus exposes to test code. Together they le… + - [error-codes](./src/error-codes/error-codes.md) — The error-code registry pins the two failure modes that the in-memory events bus exposes to test code. Together they le… +- [history](./src/history/history.md) — `History` is the per-topic append-only payload store that backs `bus.published(topic)`. Each `publish` invocation appen… + - [history](./src/history/history.md) — `History` is the per-topic append-only payload store that backs `bus.published(topic)`. Each `publish` invocation appen… +- [options](./src/options/options.md) — The options module is the single boundary at which user-supplied configuration enters the in-memory events bus. It owns… + - [options](./src/options/options.md) — The options module is the single boundary at which user-supplied configuration enters the in-memory events bus. It owns… +- [testing](./src/testing/testing.md) — The testing harness packages an {@link InMemoryEventsBus} with a `waitFor` helper for tests that publish asynchronously… + - [testing](./src/testing/testing.md) — The testing harness packages an {@link InMemoryEventsBus} with a `waitFor` helper for tests that publish asynchronously… + + +## Why + +Per the API Plugin Foundation design (§13.2), the testing kit needs an +events bus whose publishes are observable from the test code: + +```ts +import { createInMemoryEventsBus } from "@suaveplan/api-events-in-memory"; + +const bus = createInMemoryEventsBus(); + +// app code under test +bus.publish("billing.invoice.created", { invoiceId: "inv_1", amount: 100 }); + +// test +expect(bus.published("billing.invoice.created")).toHaveLength(1); +``` + +The simplest correct implementation wraps the production bus and adds +a recording layer around `publish` / `publishAsync`. Subscribers fire +as usual; ordering and FIFO invariants from the real bus are preserved. + +## Install + +```sh +bun add -d @suaveplan/api-events-in-memory +``` + +## Surface + +- `./` — `createInMemoryEventsBus`, `createInMemoryEventBus` (alias), + `InMemoryEventsBus`, `History`, error codes, options. +- `./bus` (a.k.a. `./adapter`) — factory + types only. +- `./testing` — `createInMemoryEventsBusHarness` with a `waitFor` + helper for async assertions. +- `./error-codes` — `EVENTS_IN_MEMORY_CODES` + `EventsInMemoryError`. +- `./options` — Zod schema + `resolveInMemoryEventsBusOptions`. +- `./history` — standalone history ring (used by the bus internally). + +## Quick reference + +```ts +import { createInMemoryEventsBus } from "@suaveplan/api-events-in-memory"; +import { createInMemoryEventsBusHarness } from "@suaveplan/api-events-in-memory/testing"; + +const bus = createInMemoryEventsBus({ maxHistoryPerTopic: 100 }); +bus.on("user.signup", (payload) => doStuff(payload)); +await bus.publishAsync("user.signup", { userId: "u1" }); +expect(bus.published("user.signup")).toEqual([{ userId: "u1" }]); + +const harness = createInMemoryEventsBusHarness(); +await harness.waitFor((b) => b.published("welcome.email").length === 1); +harness.dispose(); +``` + +## Options + +| Option | Default | Notes | +| ---------------------- | ------- | ------------------------------------------------------------------ | +| `maxHistoryPerTopic` | `1000` | Strict-throw cap; `publish` raises `HISTORY_OVERFLOW` past the cap | + +Invalid options raise `EVENTS_IN_MEMORY.INVALID_OPTIONS` with the +underlying `z.ZodError` on `cause`. + +## Error codes + +| Code | Raised when | +| ----------------------------------------- | --------------------------------------------------- | +| `EVENTS_IN_MEMORY.HISTORY_OVERFLOW` | `publish` would exceed `maxHistoryPerTopic` | +| `EVENTS_IN_MEMORY.INVALID_OPTIONS` | factory options fail Zod validation | + +## Out of scope + +- Persistence across process restarts — by design, in-memory. +- Multi-host fan-out — see future `api-events-redis`. +- Bounded-queue backpressure — `@suaveplan/events` already provides + this and the in-memory adapter inherits it through delegation. + +## License + +MIT — Suaveplan Team. + diff --git a/docs/api-stack/api/api-events-in-memory/src/bus/bus.md b/docs/api-stack/api/api-events-in-memory/src/bus/bus.md new file mode 100644 index 0000000..1c5ea06 --- /dev/null +++ b/docs/api-stack/api/api-events-in-memory/src/bus/bus.md @@ -0,0 +1,124 @@ +# `createInMemoryEventsBus` + + +_(no submodules)_ + + +## Purpose + +`createInMemoryEventsBus` is the factory entry point of +`@suaveplan/api-events-in-memory`. It returns a fresh +{@link InMemoryEventsBus} whose `publish` calls are recorded in a +per-topic ring of payloads and whose subscriber delivery is delegated +to a private `@suaveplan/events` `EventBus`. Tests can both assert +"this event was published with this payload" (via `published(topic)`) +and assert "this subscriber observed the side-effect" (via the +subscriber callback) without any mocks or test doubles — the real +production bus runs underneath. + +## Features + +- Recording layer wraps every `publish` / `publishAsync` / `emit` call; + the payload is appended to the topic's history BEFORE dispatch so + history is still complete even if a subscriber throws. +- Strict-throw history-overflow policy via the cap-bounded + {@link History}. `published(topic)`'s "every publish since + `reset()`" guarantee survives long-running test suites. +- Subscriber surface (`on` / `once` / `off`) mirrors + `@suaveplan/events`' `EventBus`; the more powerful + `EventBus.emitAsync` semantics are exposed through `publishAsync` + (sequential await over registered listeners; same delivery order; + same error-capture model). +- `emit(topic, payload)` alias satisfies the structural + `CapabilityEventBusLike` contract from + `@suaveplan/api-types/capabilities` so the bus can be handed to API + plugins as their `events` capability without an additional adapter. +- `dispose()` clears history AND tears down every subscriber so test + isolation is straightforward — call once per test, no leaks. +- `createInMemoryEventBus` (no "s") is a stable alias matching the + prompt's `./adapter` subpath; both spellings will continue to exist. + +## Usage: Basic + +```ts +import { createInMemoryEventsBus } from "@suaveplan/api-events-in-memory/bus"; + +const bus = createInMemoryEventsBus(); +const seen: unknown[] = []; +bus.on("billing.invoice.created", (payload) => seen.push(payload)); + +bus.publish("billing.invoice.created", { invoiceId: "inv_1", amount: 100 }); + +console.log(bus.published("billing.invoice.created")); +// [{ invoiceId: "inv_1", amount: 100 }] +console.log(seen); +// [{ invoiceId: "inv_1", amount: 100 }] + +bus.reset(); +console.log(bus.published("billing.invoice.created")); // [] +``` + +## Usage: Advanced + +Pin the per-topic cap when the test publishes in a tight loop, then +recover by `reset()` between batches: + +```ts +import { createInMemoryEventsBus } from "@suaveplan/api-events-in-memory/bus"; +import { + EVENTS_IN_MEMORY_CODES, + EventsInMemoryError, +} from "@suaveplan/api-events-in-memory/error-codes"; + +const bus = createInMemoryEventsBus({ maxHistoryPerTopic: 3 }); + +async function fanOut(count: number) { + for (let i = 0; i < count; i += 1) { + await bus.publishAsync("metrics.tick", { i }); + } +} + +try { + await fanOut(5); +} catch (error) { + if ( + error instanceof EventsInMemoryError && + error.code === EVENTS_IN_MEMORY_CODES.HISTORY_OVERFLOW + ) { + bus.reset(); + await fanOut(2); + } else { + throw error; + } +} + +console.log(bus.published("metrics.tick").length); // 2 +bus.dispose(); +``` + +## API Reference + +- `createInMemoryEventsBus(options?: InMemoryEventsBusOptions): InMemoryEventsBus` — factory. +- `createInMemoryEventBus` — alias, same return value. +- `InMemoryEventsBus.publish(topic, payload): void` — sync publish; appends history first. +- `InMemoryEventsBus.publishAsync(topic, payload): Promise` — async publish. +- `InMemoryEventsBus.emit(topic, payload): Promise` — `CapabilityEventBusLike` alias. +- `InMemoryEventsBus.on(topic, listener): Unsubscribe` — register a subscriber. +- `InMemoryEventsBus.once(topic, listener): Unsubscribe` — one-shot subscriber. +- `InMemoryEventsBus.off(topic, listener): void` — remove a subscriber. +- `InMemoryEventsBus.published(topic): readonly unknown[]` — snapshot of history. +- `InMemoryEventsBus.topics(): readonly string[]` — sorted topic names. +- `InMemoryEventsBus.reset(): void` — clear history; keep subscribers. +- `InMemoryEventsBus.dispose(): void` — clear history AND subscribers. + +## Implementation Notes + +The underlying `EventBus` is parameterised with the open `EventMap` +shape (`Record`) so the in-memory adapter can carry +any topic name without forcing the test to declare a typed map up +front. Recording happens BEFORE dispatch because the contract that +matters for tests is "this publish was attempted" — history that +drops on subscriber failure would silently hide test bugs. `emit` and +`publishAsync` share the same body; `emit` exists only so the bus +satisfies the structural `CapabilityEventBusLike` interface from +`@suaveplan/api-types`. diff --git a/docs/api-stack/api/api-events-in-memory/src/error-codes/error-codes.md b/docs/api-stack/api/api-events-in-memory/src/error-codes/error-codes.md new file mode 100644 index 0000000..0f8c8a3 --- /dev/null +++ b/docs/api-stack/api/api-events-in-memory/src/error-codes/error-codes.md @@ -0,0 +1,97 @@ +# `EVENTS_IN_MEMORY_CODES` — Error-code registry + + +_(no submodules)_ + + +## Purpose + +The error-code registry pins the two failure modes that the in-memory +events bus exposes to test code. Together they let test authors +distinguish "you bombarded the bus past the configured ring-buffer cap" +(`HISTORY_OVERFLOW`) from "you handed the factory malformed options" +(`INVALID_OPTIONS`). Both are raised as instances of +{@link EventsInMemoryError}, which extends `SuaveplanError` +so `instanceof` narrows the `code` field. + +The registry is built with `defineCodes` from `@suaveplan/error` so the +codes are typed as a const-string union; mistyped branches fail +TypeScript checks and the unused-code lint gate at `bun run check`. + +## Features + +- Stable `EVENTS_IN_MEMORY.*` namespace — codes never change without an + OpenSpec change so downstream tests can pin them. +- `EventsInMemoryError` extends `SuaveplanError`, giving cause-chain + traversal, Zod-validated wire format, and OTel span-event adapters + for free. +- `eventsInMemoryCode` is set on the public surface as a typed alias of + the base-class `code` field; legacy code paths that read + `error.eventsInMemoryCode` directly still narrow correctly. +- Two-code surface keeps the failure-mode budget small and auditable: + one for bounded-queue overflow, one for the input-validation + boundary. + +## Usage: Basic + +```ts +import { + EVENTS_IN_MEMORY_CODES, + EventsInMemoryError, +} from "@suaveplan/api-events-in-memory/error-codes"; + +try { + bus.publish("billing.invoice.created", { amount: 100 }); +} catch (error) { + if ( + error instanceof EventsInMemoryError && + error.code === EVENTS_IN_MEMORY_CODES.HISTORY_OVERFLOW + ) { + console.warn("history capped — call reset() between cases"); + } else { + throw error; + } +} +``` + +## Usage: Advanced + +Both codes carry `context` for forensic logs: + +```ts +import { + EVENTS_IN_MEMORY_CODES, + EventsInMemoryError, +} from "@suaveplan/api-events-in-memory/error-codes"; + +try { + bus.publish("x", payload); +} catch (error) { + if (error instanceof EventsInMemoryError) { + const ctx = error.context as + | { readonly topic: string; readonly limit: number } + | undefined; + console.error("[events-in-memory]", error.code, ctx); + } + throw error; +} +``` + +For schema-failure paths `error.cause` carries the raw `z.ZodError`, +preserving issue-level granularity for forensic dumps without leaking +the underlying Zod runtime through the package's public surface. + +## API Reference + +- `EVENTS_IN_MEMORY_CODES` — frozen `{ HISTORY_OVERFLOW, INVALID_OPTIONS }` mapping. +- `EventsInMemoryErrorCode` — union of `"EVENTS_IN_MEMORY.HISTORY_OVERFLOW" | "EVENTS_IN_MEMORY.INVALID_OPTIONS"`. +- `EventsInMemoryError extends SuaveplanError` — public constructor `(code, message, options?)`; exposes typed `eventsInMemoryCode` mirror of `code`. + +## Implementation Notes + +`defineCodes` prefixes every entry with the namespace (`EVENTS_IN_MEMORY.`) +so cross-package collisions are impossible. The class duplicates `code` +as `eventsInMemoryCode` because TypeScript's "narrowing by literal +field" works more reliably on the package-local alias than on the +generic base-class field when the same `SuaveplanError` is caught from +multiple packages in the same `try` block. diff --git a/docs/api-stack/api/api-events-in-memory/src/history/history.md b/docs/api-stack/api/api-events-in-memory/src/history/history.md new file mode 100644 index 0000000..086a8ce --- /dev/null +++ b/docs/api-stack/api/api-events-in-memory/src/history/history.md @@ -0,0 +1,97 @@ +# `History` + + +_(no submodules)_ + + +## Purpose + +`History` is the per-topic append-only payload store that backs +`bus.published(topic)`. Each `publish` invocation appends to the +matching topic's list; `published(topic)` snapshots that list (a copy, +so external mutation can't corrupt internal state); `reset()` empties +every topic at once. The class lives in its own module because it +carries the overflow policy independently of the bus wrapper — tests +can pin overflow behaviour without booting an `EventBus`. + +## Features + +- Per-topic FIFO arrays — payloads are returned in publish order. No + re-ordering, no de-duplication, no transformation. +- Strict-throw overflow policy: once a topic has `maxPerTopic` entries + the next `append` raises `EVENTS_IN_MEMORY.HISTORY_OVERFLOW` with the + topic name and cap in `context`. The alternative ("drop oldest") + would silently break `published(topic)`'s contract that "every + publish since `reset()` is queryable", so the package picks the + louder failure mode. +- `read(topic)` returns `readonly unknown[]` — empty array when the + topic has never been published, never `undefined`. Callers don't + branch. +- `reset()` is `O(topics)` — fast enough to call between every test + case without measurable overhead. +- `size()` + `topics()` diagnostics ease debugging "why is this test + flaky?" sessions without leaking the internal `Map`. + +## Usage: Basic + +```ts +import { History } from "@suaveplan/api-events-in-memory/history"; + +const history = new History(100); +history.append("billing.invoice.created", { invoiceId: "inv_1" }); +history.append("billing.invoice.created", { invoiceId: "inv_2" }); + +console.log(history.read("billing.invoice.created")); +// [{ invoiceId: "inv_1" }, { invoiceId: "inv_2" }] +``` + +## Usage: Advanced + +Pin overflow behaviour explicitly: + +```ts +import { History } from "@suaveplan/api-events-in-memory/history"; +import { + EVENTS_IN_MEMORY_CODES, + EventsInMemoryError, +} from "@suaveplan/api-events-in-memory/error-codes"; + +const history = new History(2); +history.append("x", 1); +history.append("x", 2); +try { + history.append("x", 3); +} catch (error) { + if ( + error instanceof EventsInMemoryError && + error.code === EVENTS_IN_MEMORY_CODES.HISTORY_OVERFLOW + ) { + const ctx = error.context as + | { readonly topic: string; readonly limit: number } + | undefined; + console.warn(`topic ${ctx?.topic} hit cap of ${ctx?.limit}`); + } +} + +// reset() clears every topic at once +history.reset(); +console.log(history.read("x")); // [] +``` + +## API Reference + +- `new History(maxPerTopic: number)` — construct an empty store. +- `append(topic, payload): void` — push payload; throws `HISTORY_OVERFLOW` at the cap. +- `read(topic): readonly unknown[]` — snapshot copy in publish order. +- `reset(): void` — drop every topic's history. +- `size(): number` — total payload count across topics (diagnostic). +- `topics(): readonly string[]` — sorted topic names (diagnostic). + +## Implementation Notes + +`read()` always returns a snapshot (`list.slice()`) so callers can +freeze the array, sort it, or hand it to assertion libraries without +mutating internal state. The throw-on-overflow policy is the design +doc's choice; the alternative drop-oldest could be added behind an +option in a later OpenSpec change, but doing so today would weaken the +`published(topic)` contract for every existing consumer. diff --git a/docs/api-stack/api/api-events-in-memory/src/options/options.md b/docs/api-stack/api/api-events-in-memory/src/options/options.md new file mode 100644 index 0000000..911e990 --- /dev/null +++ b/docs/api-stack/api/api-events-in-memory/src/options/options.md @@ -0,0 +1,80 @@ +# `InMemoryEventsBusOptions` + + +_(no submodules)_ + + +## Purpose + +The options module is the single boundary at which user-supplied +configuration enters the in-memory events bus. It owns the Zod schema, +the default for `maxHistoryPerTopic`, and the +`resolveInMemoryEventsBusOptions` helper that turns a partial caller +input into a fully-resolved internal options object. Keeping resolution +out of the factory avoids re-checking defaults on every internal call +and keeps the public Zod-validation surface in one place. + +## Features + +- Strict schema (`.strict()`) — typos in the options object surface as + `EVENTS_IN_MEMORY.INVALID_OPTIONS` rather than being silently + dropped. This is the difference between "the cap I set was ignored" + and "the cap key was misspelled" — the test author needs to know. +- Default `maxHistoryPerTopic = 1000` matches the design doc's + "guard against runaway tests" guidance — high enough for realistic + test suites, low enough that an accidental `while (true) publish(...)` + fails loudly. +- Public Zod-failures are repackaged as `EventsInMemoryError`. Callers + catch the package's own error type; `error.cause` still carries the + raw `z.ZodError` for forensic logs. +- `ResolvedInMemoryEventsBusOptions` exposes a concrete (non-optional) + shape downstream code can branch on without re-applying defaults. + +## Usage: Basic + +```ts +import { resolveInMemoryEventsBusOptions } from "@suaveplan/api-events-in-memory/options"; + +const resolved = resolveInMemoryEventsBusOptions(undefined); +console.log(resolved.maxHistoryPerTopic); // 1000 +``` + +## Usage: Advanced + +Combine a parsed JSON config blob with the schema directly when the +caller wants to surface validation issues at file-read time rather than +at bus-construction time: + +```ts +import { + inMemoryEventsBusOptionsSchema, + resolveInMemoryEventsBusOptions, +} from "@suaveplan/api-events-in-memory/options"; + +const fromFile: unknown = JSON.parse(readFileSync("./bus.json", "utf8")); +const result = inMemoryEventsBusOptionsSchema.safeParse(fromFile); +if (!result.success) { + throw new Error(`bus.json failed validation: ${result.error.message}`); +} +const resolved = resolveInMemoryEventsBusOptions(result.data); +``` + +`maxHistoryPerTopic` must be a positive integer; `0` and negatives are +rejected so callers can't accidentally disable history entirely. + +## API Reference + +- `DEFAULT_MAX_HISTORY_PER_TOPIC: 1000` — applied when callers omit the field. +- `InMemoryEventsBusOptions` — interface with `maxHistoryPerTopic?: number`. +- `inMemoryEventsBusOptionsSchema` — `z.ZodObject` with `.strict()`. +- `ResolvedInMemoryEventsBusOptions` — internal resolved shape (`maxHistoryPerTopic: number`). +- `resolveInMemoryEventsBusOptions(raw?)` — parses, applies defaults, raises `EventsInMemoryError(INVALID_OPTIONS)` on failure. + +## Implementation Notes + +The schema rejects extra keys with `.strict()` because the alternative +("permissive, ignore unknown") empirically masks typos for months +before anyone notices. The repackaging-to-`EventsInMemoryError` step is +the boundary at which the package commits to its own error namespace — +once a Zod error has crossed `resolveInMemoryEventsBusOptions`, no +caller should ever see a raw `z.ZodError` again. diff --git a/docs/api-stack/api/api-events-in-memory/src/testing/testing.md b/docs/api-stack/api/api-events-in-memory/src/testing/testing.md new file mode 100644 index 0000000..4555c76 --- /dev/null +++ b/docs/api-stack/api/api-events-in-memory/src/testing/testing.md @@ -0,0 +1,95 @@ +# `createInMemoryEventsBusHarness` + + +_(no submodules)_ + + +## Purpose + +The testing harness packages an {@link InMemoryEventsBus} with a +`waitFor` helper for tests that publish asynchronously and need to +assert on history once the publish has settled. It is the standard +shape downstream plugin tests will import to avoid hand-rolling a +poll-with-timeout loop for every assertion. Importing +`@suaveplan/api-events-in-memory/testing` returns a tightly-scoped +surface that won't leak production-only construction details into test +code. + +## Features + +- Fresh bus per harness — call `createInMemoryEventsBusHarness()` once + per test, `dispose()` at teardown; no shared state across cases. +- `waitFor(predicate, { timeoutMs, intervalMs })` polls until the + predicate holds or the timeout elapses. The default timeout (1 s) + and interval (5 ms) work for the overwhelming majority of unit + tests; override only when integrating with slower infra. +- Fast path: if the predicate already holds at call time the function + resolves on the next microtask without sleeping. +- Reject-on-timeout includes the requested `timeoutMs` in the message + so test failures are easy to triage. +- All options forwarded verbatim to {@link createInMemoryEventsBus}, so + the harness inherits the strict-throw history-overflow policy and + the Zod-validated options boundary. + +## Usage: Basic + +```ts +import { createInMemoryEventsBusHarness } from "@suaveplan/api-events-in-memory/testing"; + +const harness = createInMemoryEventsBusHarness(); +const { bus, waitFor } = harness; + +bus.on("user.signup", async () => { + await Promise.resolve(); + bus.publish("welcome.email.queued", { to: "u@example.com" }); +}); + +await bus.publishAsync("user.signup", { userId: "u1" }); +await waitFor((b) => b.published("welcome.email.queued").length === 1); + +console.log(bus.published("welcome.email.queued")); +harness.dispose(); +``` + +## Usage: Advanced + +Tighten the deadline for a fast unit test, or extend it for an +integration test that sits behind a real database: + +```ts +import { createInMemoryEventsBusHarness } from "@suaveplan/api-events-in-memory/testing"; + +const harness = createInMemoryEventsBusHarness({ maxHistoryPerTopic: 50 }); +try { + await harness.waitFor( + (bus) => bus.published("payment.captured").length >= 3, + { timeoutMs: 5000, intervalMs: 25 } + ); +} catch (error) { + console.error("payment.captured fan-out stalled:", error); + throw error; +} finally { + harness.dispose(); +} +``` + +`dispose()` is idempotent — calling it twice in `afterEach` after a +mid-test failure is safe. + +## API Reference + +- `createInMemoryEventsBusHarness(options?): InMemoryEventsBusHarness` — factory. +- `InMemoryEventsBusHarness.bus: InMemoryEventsBus` — the wrapped bus. +- `InMemoryEventsBusHarness.waitFor(predicate, options?): Promise` — poll-with-timeout. +- `InMemoryEventsBusHarness.dispose(): void` — tear down the bus. +- `WaitForPredicate = (bus: InMemoryEventsBus) => boolean`. +- `WaitForOptions = { timeoutMs?: number; intervalMs?: number }`. + +## Implementation Notes + +`waitFor` uses `setTimeout` rather than `setImmediate`/`queueMicrotask` +because real tests need to interleave with timers managed by the +runtime; busy-looping on microtasks starves them. The harness owns +`dispose` rather than asking the caller to call `bus.dispose()` +directly so that future versions can add additional resources +(meter providers, span recorders) without breaking the test surface. diff --git a/docs/api-stack/api/api-events-worker-proxy/README.md b/docs/api-stack/api/api-events-worker-proxy/README.md new file mode 100644 index 0000000..ea0f5df --- /dev/null +++ b/docs/api-stack/api/api-events-worker-proxy/README.md @@ -0,0 +1,90 @@ +# @suaveplan/api-events-worker-proxy - Worker-tier proxy over a main-process @suaveplan/events EventBus. The main side calls createEventBusProxyServer(port, bus) to expose the bus over a MessagePort via @suaveplan/api-worker-rpc; worker-tier plugins call createEventBusProxyClient(port) to obtain an EventBus-shaped surface that marshals on/once/off/emit/emitAsync across the port. Subscriptions become long-lived stream-* frames that deliver one stream-chunk per main-side event. Zod-validated payload codec rejects non-structured-clone-safe payloads with EVENTS_PROXY.UNSERIALISABLE_PAYLOAD. + +Worker-tier proxy over a main-process `@suaveplan/events` `EventBus`. + +The host (main process) owns one `EventBus` instance. Worker-tier +plugins want to publish to and subscribe from the same bus without +running the bus in every worker. This package marshals every +`on` / `once` / `off` / `emit` / `emitAsync` call across a +`MessagePort` via `@suaveplan/api-worker-rpc`, so worker-tier plugin +code compiles unchanged against an `EventBus`-shaped proxy surface. + +This is an adapter, not a new contract — the design doc (§5.2a) is +explicit that no abstract `api-events` contract package exists. The +host injects `@suaveplan/events` directly; this package is the +worker-side surface over that existing bus. + + +## Documentation tree + +- [error-codes](./src/error-codes/error-codes.md) — Defines the stable string registry of `EVENTS_PROXY.*` error codes raised by every failure path in `@suaveplan/api-even… + - [error-codes](./src/error-codes/error-codes.md) — Defines the stable string registry of `EVENTS_PROXY.*` error codes raised by every failure path in `@suaveplan/api-even… +- [main-side](./src/main-side/main-side.md) — Mounts a main-process `@suaveplan/events` `EventBus` on a `MessagePort` via the `@suaveplan/api-worker-rpc` server so w… + - [main-side](./src/main-side/main-side.md) — Mounts a main-process `@suaveplan/events` `EventBus` on a `MessagePort` via the `@suaveplan/api-worker-rpc` server so w… +- [payload-codec](./src/payload-codec/payload-codec.md) — Encodes and decodes the wire envelope used to ship a single event from the main-process `EventBus` across a `MessagePor… + - [payload-codec](./src/payload-codec/payload-codec.md) — Encodes and decodes the wire envelope used to ship a single event from the main-process `EventBus` across a `MessagePor… +- [testing](./src/testing/testing.md) — Re-usable test fixtures for `@suaveplan/api-events-worker-proxy`. Builds a real `EventBus`, a real Node.js `MessageChan… + - [testing](./src/testing/testing.md) — Re-usable test fixtures for `@suaveplan/api-events-worker-proxy`. Builds a real `EventBus`, a real Node.js `MessageChan… +- [worker-side](./src/worker-side/worker-side.md) — Builds a worker-side proxy that exposes an `EventBus`-shaped surface backed by a `PortLike` connected to a main-process… + - [worker-side](./src/worker-side/worker-side.md) — Builds a worker-side proxy that exposes an `EventBus`-shaped surface backed by a `PortLike` connected to a main-process… + + +## Install + +```bash +bun add @suaveplan/api-events-worker-proxy +``` + +## Main-side (host) + +```ts +import { EventBus } from "@suaveplan/events"; +import { createEventBusProxyServer } from "@suaveplan/api-events-worker-proxy/main-side"; +import { createInProcessPortPair } from "@suaveplan/api-worker-rpc"; + +const bus = new EventBus<{ "billing.invoice.created": { id: string } }>(); +const { clientPort, serverPort, close } = createInProcessPortPair(); +const server = createEventBusProxyServer(serverPort, bus); +// Hand `clientPort` to a worker; tear down with `server.dispose()` + close(). +``` + +## Worker-side + +```ts +import { createEventBusProxyClient } from "@suaveplan/api-events-worker-proxy/worker-side"; + +type Map = { "billing.invoice.created": { id: string } }; +const events = createEventBusProxyClient(port); +events.on("billing.invoice.created", ({ id }) => console.log("got", id)); +const result = await events.emitAsync("billing.invoice.created", { + id: "i_1", +}); +console.log(result.delivered); +``` + +## Exports + +- `./main-side` — `createEventBusProxyServer(port, bus)`. +- `./worker-side` — `createEventBusProxyClient(port)`. +- `./payload-codec` — Zod schema + structured-clone probe. +- `./error-codes` — `EVENTS_PROXY.*` codes + `EventsProxyError`. +- `./testing` — `createProxyPair` + `waitFor` for downstream tests. + +## Error codes + +- `EVENTS_PROXY.UNSERIALISABLE_PAYLOAD` — payload failed the + structured-clone safety probe (functions, class instances, cycles). +- `EVENTS_PROXY.SUBSCRIPTION_DROPPED` — subscription terminated + unexpectedly (server disposed, port closed mid-stream). +- `EVENTS_PROXY.BACKPRESSURE_EXCEEDED` — worker-side queue exceeded the + configured high-water mark. +- `EVENTS_PROXY.PROXY_DISPOSED` — method called after `dispose()`. + +## Docs + +- [`main-side`](./src/main-side/main-side.md) +- [`worker-side`](./src/worker-side/worker-side.md) +- [`payload-codec`](./src/payload-codec/payload-codec.md) +- [`error-codes`](./src/error-codes/error-codes.md) +- [`testing`](./src/testing/testing.md) + diff --git a/docs/api-stack/api/api-events-worker-proxy/src/error-codes/error-codes.md b/docs/api-stack/api/api-events-worker-proxy/src/error-codes/error-codes.md new file mode 100644 index 0000000..33457d9 --- /dev/null +++ b/docs/api-stack/api/api-events-worker-proxy/src/error-codes/error-codes.md @@ -0,0 +1,71 @@ +# `error-codes` + + +_(no submodules)_ + + +## Purpose + +Defines the stable string registry of `EVENTS_PROXY.*` error codes raised by every failure path in `@suaveplan/api-events-worker-proxy`, plus the concrete `EventsProxyError` subclass of `SuaveplanError` that carries them. + +Consumers branch on the string code (`error.code === EVENTS_PROXY_CODES.UNSERIALISABLE_PAYLOAD`) rather than on subclass identity, which keeps the wire format stable across versions and across the worker/main boundary where errors are reconstructed from their `{ code, message, details }` triple. + +## Features + +- Four canonical codes: `UNSERIALISABLE_PAYLOAD`, `SUBSCRIPTION_DROPPED`, `BACKPRESSURE_EXCEEDED`, `PROXY_DISPOSED`. +- Built via `defineCodes("EVENTS_PROXY", [...])` so every code emerges as the dotted string `"EVENTS_PROXY."`. +- `EventsProxyError` exposes a typed `eventsProxyCode` property in addition to the inherited `code` so type narrowing works both ways. +- Uses `SuaveplanErrorOptions` (with `cause` + `context`) verbatim — no bespoke options shape. + +## Usage: Basic + +```ts +import { + EVENTS_PROXY_CODES, + EventsProxyError, +} from "@suaveplan/api-events-worker-proxy/error-codes"; + +throw new EventsProxyError( + EVENTS_PROXY_CODES.UNSERIALISABLE_PAYLOAD, + "Refusing to marshal a payload containing a function", + { context: { path: "$.handler" } } +); +``` + +## Usage: Advanced + +```ts +import { + EVENTS_PROXY_CODES, + EventsProxyError, + type EventsProxyErrorCode, +} from "@suaveplan/api-events-worker-proxy/error-codes"; + +function classify(error: unknown): EventsProxyErrorCode | "unknown" { + if (error instanceof EventsProxyError) return error.eventsProxyCode; + return "unknown"; +} + +try { + // ...emit a payload across the proxy... +} catch (err) { + if ( + err instanceof EventsProxyError && + err.eventsProxyCode === EVENTS_PROXY_CODES.BACKPRESSURE_EXCEEDED + ) { + // Apply caller-side backoff before retrying. + } else { + throw err; + } +} +``` + +## API Reference + +- `EVENTS_PROXY_CODES` — `Readonly<{ UNSERIALISABLE_PAYLOAD: "EVENTS_PROXY.UNSERIALISABLE_PAYLOAD"; SUBSCRIPTION_DROPPED: "EVENTS_PROXY.SUBSCRIPTION_DROPPED"; BACKPRESSURE_EXCEEDED: "EVENTS_PROXY.BACKPRESSURE_EXCEEDED"; PROXY_DISPOSED: "EVENTS_PROXY.PROXY_DISPOSED"; }>`. +- `EventsProxyErrorCode` — union of the four dotted strings above. +- `EventsProxyError(code, message, options?)` — concrete subclass of `SuaveplanError`. `options.cause` records the upstream error; `options.context` records structured metadata (`path`, `subscriptionId`, etc.). + +## Implementation Notes + +The registry is intentionally small: every code captures a category of failure rather than a fine-grained sub-condition, and the structured `context` payload carries the discriminating detail. This keeps the wire surface stable as the codec evolves. The class duplicates the code into `eventsProxyCode` so that callers in TypeScript can narrow without importing the union type — useful for plugins that reconstruct errors from the wire envelope on the opposite side of the port. diff --git a/docs/api-stack/api/api-events-worker-proxy/src/main-side/main-side.md b/docs/api-stack/api/api-events-worker-proxy/src/main-side/main-side.md new file mode 100644 index 0000000..01c3d0c --- /dev/null +++ b/docs/api-stack/api/api-events-worker-proxy/src/main-side/main-side.md @@ -0,0 +1,61 @@ +# `main-side` + + +_(no submodules)_ + + +## Purpose + +Mounts a main-process `@suaveplan/events` `EventBus` on a `MessagePort` via the `@suaveplan/api-worker-rpc` server so worker-tier plugins can publish to and subscribe from the same shared bus. The host owns the `EventBus`; this module installs the RPC handlers and lifecycle. + +Three RPC methods are exposed: `emit`, `emitAsync`, and the streaming `subscribe`. Subscriptions return an `AsyncIterable` that yields one chunk per main-side event until the worker cancels (or `mode: "once"` ends after the first delivery). + +## Features + +- Wires `emit` / `emitAsync` / `subscribe` over the canonical worker-RPC protocol — no bespoke wire format. +- Per-subscription `highWaterMark` cap with `EVENTS_PROXY.BACKPRESSURE_EXCEEDED` rejection when the worker stops draining. +- Payloads are Zod-validated and structured-clone-probed on encode; unsafe payloads surface as `EVENTS_PROXY.UNSERIALISABLE_PAYLOAD` BEFORE they touch the port. +- `EventsProxyError` instances are serialised onto the wire by `api-worker-rpc`'s `errorToEnvelope` so the worker side reconstructs typed errors. +- `dispose()` shuts the underlying `WorkerRpcServer` down; in-flight `subscribe` streams emit `stream-end` via the goodbye flow. + +## Usage: Basic + +```ts +import { EventBus } from "@suaveplan/events"; +import { createEventBusProxyServer } from "@suaveplan/api-events-worker-proxy/main-side"; +import { createInProcessPortPair } from "@suaveplan/api-worker-rpc"; + +const bus = new EventBus<{ "billing.invoice.created": { id: string } }>(); +const { clientPort, serverPort, close } = createInProcessPortPair(); +const server = createEventBusProxyServer(serverPort, bus); +// Pass `clientPort` to a worker; tear down with `server.dispose()` + close(). +``` + +## Usage: Advanced + +```ts +import { EventBus } from "@suaveplan/events"; +import { createEventBusProxyServer } from "@suaveplan/api-events-worker-proxy/main-side"; +import { createInProcessPortPair } from "@suaveplan/api-worker-rpc"; + +type Map = { "drive.chunk.delivered": { chunkId: string } }; +const bus = new EventBus(); +const { clientPort, serverPort } = createInProcessPortPair(); +const server = createEventBusProxyServer(serverPort, bus); + +// In-process subscribers keep receiving events as usual. +bus.on("drive.chunk.delivered", ({ chunkId }) => + console.log("main-side observed", chunkId) +); + +process.on("beforeExit", () => server.dispose()); +``` + +## API Reference + +- `createEventBusProxyServer(port: PortLike, bus: EventBus): EventBusProxyServer`. +- `EventBusProxyServer` — `{ dispose(reason?: string): void; readonly activeSubscriptionCount: number; }`. + +## Implementation Notes + +The handlers object passed to `serveWorkerRpc` declares three methods. `emit` and `emitAsync` parse positional params (`[topic, payload, traceId?, timeoutMs?]`), decode the wire envelope with `decodeEnvelope`, and forward to `bus.emit` / `bus.emitAsync`. The streaming `subscribe` handler builds an `AsyncIterable` whose body subscribes to the bus, enqueues payloads on each event, and yields them on each iteration. Backpressure is enforced by checking `queue.length` against the worker-supplied high-water mark; over-budget events surface `BACKPRESSURE_EXCEEDED` and end the stream. Cancellation is wired through `AbortSignal`: the server's `cancel` frame triggers the per-call signal, which the iterator observes via `signal.aborted` plus a `wake()` callback so the pending `await` resolves immediately. The `unsubscribe` happens in the iterator's `finally` block so it runs on both normal completion and cancellation. diff --git a/docs/api-stack/api/api-events-worker-proxy/src/payload-codec/payload-codec.md b/docs/api-stack/api/api-events-worker-proxy/src/payload-codec/payload-codec.md new file mode 100644 index 0000000..d46f271 --- /dev/null +++ b/docs/api-stack/api/api-events-worker-proxy/src/payload-codec/payload-codec.md @@ -0,0 +1,73 @@ +# `payload-codec` + + +_(no submodules)_ + + +## Purpose + +Encodes and decodes the wire envelope used to ship a single event from the main-process `EventBus` across a `MessagePort` to a worker-tier subscriber. Includes a depth-bounded structured-clone safety probe so payloads that cannot survive the transfer are rejected at the source rather than producing opaque `DataCloneError` exceptions at runtime. + +The codec is intentionally conservative: anything beyond plain JSON-shaped data plus a small list of well-known cloneable host types (`Date`, `RegExp`, `Map`, `Set`, `ArrayBuffer`, typed arrays) is rejected with `EVENTS_PROXY.UNSERIALISABLE_PAYLOAD`. This matches the structured-clone algorithm but is checked synchronously and surfaces the offending path. + +## Features + +- `EventEnvelopeSchema` Zod schema for the wire frame (`{ topic, payload, traceId? }`). +- `encodeEnvelope(topic, payload, traceId?)` runs the probe, then constructs the envelope. Throws an `EventsProxyError` carrying the offending path on rejection. +- `decodeEnvelope(raw)` Zod-validates an inbound frame. +- `probeStructuredClone(value)` returns the offending path or `null`. Detects functions, symbols, `WeakMap`/`WeakSet`, class instances, cycles, and over-deep graphs (limit `MAX_PROBE_DEPTH = 64`). +- `DEFAULT_BACKPRESSURE_HIGH_WATER = 1024` — the default per-subscription queue cap. + +## Usage: Basic + +```ts +import { + encodeEnvelope, + decodeEnvelope, +} from "@suaveplan/api-events-worker-proxy/payload-codec"; + +const wire = encodeEnvelope("billing.invoice.created", { invoiceId: "i_1" }); +const decoded = decodeEnvelope(wire); +console.log(decoded.topic, decoded.payload); +``` + +## Usage: Advanced + +```ts +import { + probeStructuredClone, + encodeEnvelope, +} from "@suaveplan/api-events-worker-proxy/payload-codec"; +import { + EventsProxyError, + EVENTS_PROXY_CODES, +} from "@suaveplan/api-events-worker-proxy/error-codes"; + +const payload = { + invoiceId: "i_1", + whenIssued: new Date(), + handler: () => undefined, +}; +const offender = probeStructuredClone(payload); +if (offender !== null) { + throw new EventsProxyError( + EVENTS_PROXY_CODES.UNSERIALISABLE_PAYLOAD, + `payload rejected at ${offender}` + ); +} +const wire = encodeEnvelope("invoice.flagged", payload); +``` + +## API Reference + +- `EventEnvelopeSchema` — `z.object({ topic: z.string().min(1), traceId: z.string().optional(), payload: z.unknown() })`. +- `WireEventEnvelope` — `z.infer`. +- `encodeEnvelope(topic: string, payload: unknown, traceId?: string): WireEventEnvelope`. +- `decodeEnvelope(raw: unknown): WireEventEnvelope`. +- `probeStructuredClone(value: unknown): string | null` — returns the offending JSON-path-like string or `null`. +- `MAX_PROBE_DEPTH: number` — `64`. +- `DEFAULT_BACKPRESSURE_HIGH_WATER: number` — `1024`. + +## Implementation Notes + +The probe walks the object graph synchronously with a `WeakSet` cycle detector, accumulating the offending JSON path. It deliberately rejects class instances (`Object.getPrototypeOf(value) !== Object.prototype`) because the receiving side reconstructs them as plain objects, breaking `instanceof`. `Date`, `RegExp`, `Map`, `Set`, `ArrayBuffer`, and `ArrayBuffer.isView`-typed values are recognised explicitly because they ARE structured-clone safe even though they have non-`Object` prototypes. The depth bound of 64 is generous for legitimate payloads but cuts off pathological inputs. Cycles are detected by `WeakSet`; the probe reports the path that re-entered the visited set rather than recursing infinitely. diff --git a/docs/api-stack/api/api-events-worker-proxy/src/testing/testing.md b/docs/api-stack/api/api-events-worker-proxy/src/testing/testing.md new file mode 100644 index 0000000..1ee27ba --- /dev/null +++ b/docs/api-stack/api/api-events-worker-proxy/src/testing/testing.md @@ -0,0 +1,66 @@ +# `testing` + + +_(no submodules)_ + + +## Purpose + +Re-usable test fixtures for `@suaveplan/api-events-worker-proxy`. Builds a real `EventBus`, a real Node.js `MessageChannel`, and wires the proxy server + client over the channel so downstream tests can exercise the full transport with zero mocks. + +The exports here power the in-package conformance suite (`tests/conformance/run-events-bus-conformance.test.ts`) and are also consumed by plugin tests that want to verify their behaviour against the proxy surface specifically. + +## Features + +- `createProxyPair(options?)` — returns `{ bus, server, client, tearDown }`. The bus is a fresh `EventBus` instance; the server and client are mounted over the two ends of a Node `MessageChannel` returned by `createInProcessPortPair`. +- `tearDown()` calls `client.dispose()` (best-effort), then `server.dispose()`, then `pair.close()`; safe to call repeatedly. +- `waitFor(predicate, timeoutMs?)` — async-polls until the predicate returns `true` or the timeout elapses; bridges the sync/async gap when asserting that a worker-side listener has observed a bus emission. + +## Usage: Basic + +```ts +import { createProxyPair } from "@suaveplan/api-events-worker-proxy/testing"; + +type Map = { ping: number }; +const { bus, client, tearDown } = createProxyPair(); +let observed: number | undefined; +client.on("ping", (n) => { + observed = n; +}); +bus.emit("ping", 42); +// flush via waitFor or sleep, then assert observed === 42. +await tearDown(); +``` + +## Usage: Advanced + +```ts +import { + createProxyPair, + waitFor, +} from "@suaveplan/api-events-worker-proxy/testing"; + +type Map = { user: { id: string } }; +const { bus, client, tearDown } = createProxyPair({ + busOptions: { clock: () => 42 }, + highWaterMark: 8, +}); + +const observed: string[] = []; +client.on("user", ({ id }) => observed.push(id)); + +bus.emit("user", { id: "u_1" }); +await waitFor(() => observed.length === 1); + +await tearDown(); +``` + +## API Reference + +- `createProxyPair(options?: { busOptions?, highWaterMark? }): ProxyPairHandles`. +- `ProxyPairHandles` — `{ bus, server, client, tearDown }`. +- `waitFor(predicate: () => boolean, timeoutMs?: number): Promise`. Default timeout `2000ms`. + +## Implementation Notes + +The helper delegates to `@suaveplan/api-worker-rpc`'s `createInProcessPortPair` for the port plumbing, which wraps a Node `MessageChannel` in the canonical `PortLike` shape. `tearDown` swallows errors from `client.dispose()` because tests may already have torn the port down explicitly; `server.dispose()` is idempotent. `waitFor` polls on a 5ms interval — fine-grained enough to keep tests fast but coarse enough not to thrash the event loop. diff --git a/docs/api-stack/api/api-events-worker-proxy/src/worker-side/worker-side.md b/docs/api-stack/api/api-events-worker-proxy/src/worker-side/worker-side.md new file mode 100644 index 0000000..1cf2a8c --- /dev/null +++ b/docs/api-stack/api/api-events-worker-proxy/src/worker-side/worker-side.md @@ -0,0 +1,58 @@ +# `worker-side` + + +_(no submodules)_ + + +## Purpose + +Builds a worker-side proxy that exposes an `EventBus`-shaped surface backed by a `PortLike` connected to a main-process `createEventBusProxyServer`. Plugin code authored against `@suaveplan/events` `EventBus` compiles unchanged against this surface: `on` / `once` / `off` / `emit` / `emitAsync` are all present with the same parameter shapes. + +The proxy is intentionally not an `EventBus` instance — it is a structurally-equivalent value (see `EventBusProxyClient`). `use` and `clear` are deliberately absent because interceptors run main-side only, and clearing across worker boundaries would corrupt every other worker's subscriptions. + +## Features + +- `on(topic, listener)` and `once(topic, listener)` open a streaming RPC subscription via `@suaveplan/api-worker-rpc`'s `streamRequest`. Each main-side emission lands as one `stream-chunk` and is dispatched to the local listener. +- `off(topic, listener)` looks up the originating subscription and aborts its controller, sending a `cancel` frame to the main side. +- `emit` is fire-and-forget (synchronous return of `{ delivered: 0, errors: [] }`); `emitAsync` returns `{ delivered, errorCount }` after the main bus drains. +- Synchronous structured-clone probe inside `emit`/`emitAsync` rejects non-cloneable payloads with `EVENTS_PROXY.UNSERIALISABLE_PAYLOAD` before the call is dispatched. +- `dispose()` aborts every active subscription with `EVENTS_PROXY.SUBSCRIPTION_DROPPED`, closes the underlying client, and rejects in-flight calls. + +## Usage: Basic + +```ts +import { createEventBusProxyClient } from "@suaveplan/api-events-worker-proxy/worker-side"; + +type Map = { "billing.invoice.created": { id: string } }; +const events = createEventBusProxyClient(port); +events.on("billing.invoice.created", ({ id }) => console.log("got", id)); +const r = await events.emitAsync("billing.invoice.created", { id: "i_1" }); +console.log(r.delivered); +``` + +## Usage: Advanced + +```ts +import { createEventBusProxyClient } from "@suaveplan/api-events-worker-proxy/worker-side"; + +const events = createEventBusProxyClient(port, { + highWaterMark: 256, +}); + +const off = events.on("drive.chunk.delivered", async ({ chunkId }) => { + await processChunk(chunkId); +}); + +off(); +await events.dispose("worker exiting"); +``` + +## API Reference + +- `createEventBusProxyClient(port: PortLike, options?: CreateEventBusProxyClientOptions): EventBusProxyClient`. +- `EventBusProxyClient` — typed `on`/`once`/`off`/`emit`/`emitAsync`/`dispose`. +- `CreateEventBusProxyClientOptions` — `{ highWaterMark?: number }`. Default high-water mark is `DEFAULT_BACKPRESSURE_HIGH_WATER = 1024`. + +## Implementation Notes + +The proxy holds a `WorkerRpcClient` (raw) plus a `StreamDispatcher` so streaming subscriptions multiplex inbound `stream-chunk` frames. Each `subscribe`/`once` invocation calls `streamRequest("subscribe", [topic, mode, hwm], { signal })` to open a long-lived stream; the iterator's loop dispatches every chunk to the local listener and exits on the worker-supplied `AbortSignal`. The handle returned by `on` / `once` is a closure that aborts the signal, which propagates a `cancel` frame back to the main side and ends the underlying stream cleanly. `emit` calls the `emit` method via `client.call("emit", args)` but returns synchronously — the EventBus synchronous shape doesn't allow waiting for the real delivered count, so callers needing the real numbers must use `emitAsync`. Listener throws are swallowed inside the `runStream` consumer so a single bad listener can't break the message loop. diff --git a/docs/api-stack/api/api-graphql-apollo/README.md b/docs/api-stack/api/api-graphql-apollo/README.md new file mode 100644 index 0000000..07d4e97 --- /dev/null +++ b/docs/api-stack/api/api-graphql-apollo/README.md @@ -0,0 +1,69 @@ +# @suaveplan/api-graphql-apollo — Apollo Server GraphQL engine adapter for the Suaveplan API plugin system. Implements the GraphqlEngine contract from @suaveplan/api-graphql and passes runGraphqlEngineConformance with the same invariants as the Yoga sibling. Adds Apollo-specific persisted-query manifest support, optional Apollo Studio usage reporting, depth + complexity guards, federated multi-plugin schema merging, per-request DataLoader scoping, engine-agnostic OTel instruments, and graphql-ws subscription bridging. + +Stage-7 Apollo Server GraphQL engine adapter for the Suaveplan API +plugin system. Implements the `GraphqlEngine` contract from +`@suaveplan/api-graphql` and passes the conformance suite alongside +the Yoga sibling — switching engines is a host-config change. + + +## Documentation tree + +- [http](./src/endpoints/http.md) — `endpoints/http` mounts the two HTTP endpoints every GraphQL adapter must expose: `POST /graphql` for operation dispatc… +- [ui-proxy](./src/endpoints/ui-proxy.md) — `endpoints/ui-proxy` mounts the `/graphql/ui` endpoint. The Apollo engine never embeds Apollo's landing page — UI is op… +- [engine](./src/engine/apollo-engine.md) — `ApolloGraphqlEngine` is the concrete Apollo Server implementation of the `@suaveplan/api-graphql` engine contract. It… + - [apollo-engine](./src/engine/apollo-engine.md) — `ApolloGraphqlEngine` is the concrete Apollo Server implementation of the `@suaveplan/api-graphql` engine contract. It… +- [error-codes](./src/error-codes/error-codes.md) — `error-codes` defines the stable `GRAPHQL_APOLLO.*` namespace plus the `GraphqlApolloError` class consumed by every oth… + - [error-codes](./src/error-codes/error-codes.md) — `error-codes` defines the stable `GRAPHQL_APOLLO.*` namespace plus the `GraphqlApolloError` class consumed by every oth… +- [federation](./src/federation/federation.md) — `federation` is the engine's facade over the canonical `mergeSdl` function from `@suaveplan/api-graphql`. Apollo doesn'… + - [federation](./src/federation/federation.md) — `federation` is the engine's facade over the canonical `mergeSdl` function from `@suaveplan/api-graphql`. Apollo doesn'… +- [guards](./src/guards/depth-and-complexity.md) — `depth-and-complexity` walks a parsed `DocumentNode` and computes two coarse static metrics — the maximum selection-set… + - [depth-and-complexity](./src/guards/depth-and-complexity.md) — `depth-and-complexity` walks a parsed `DocumentNode` and computes two coarse static metrics — the maximum selection-set… +- [instruments](./src/instruments/instruments.md) — `instruments` owns the five OTel instrument names emitted by every GraphQL engine adapter in the foundation. Both `api-… + - [instruments](./src/instruments/instruments.md) — `instruments` owns the five OTel instrument names emitted by every GraphQL engine adapter in the foundation. Both `api-… +- [loaders](./src/loaders/loaders.md) — `loaders` defines the per-request DataLoader scope the engine creates around every incoming GraphQL operation. Two conc… + - [loaders](./src/loaders/loaders.md) — `loaders` defines the per-request DataLoader scope the engine creates around every incoming GraphQL operation. Two conc… +- [options](./src/options/options.md) — `options` owns the Zod-validated configuration surface accepted by `createApolloGraphqlEngine`. The schema mirrors the… + - [options](./src/options/options.md) — `options` owns the Zod-validated configuration surface accepted by `createApolloGraphqlEngine`. The schema mirrors the… +- [persisted-queries](./src/persisted-queries/persisted-queries.md) — `persisted-queries` implements Apollo's persisted-query manifest lookup — the ability for clients to send `{ id }` in p… + - [persisted-queries](./src/persisted-queries/persisted-queries.md) — `persisted-queries` implements Apollo's persisted-query manifest lookup — the ability for clients to send `{ id }` in p… +- [studio-reporting](./src/studio-reporting/studio-reporting.md) — `studio-reporting` materialises the configuration descriptor consumed by the engine when an operator opts in to Apollo… + - [studio-reporting](./src/studio-reporting/studio-reporting.md) — `studio-reporting` materialises the configuration descriptor consumed by the engine when an operator opts in to Apollo… +- [subscriptions](./src/subscriptions/subscriptions.md) — `subscriptions` runs a GraphQL subscription document against a wired schema, returning the `AsyncIterable + +## When to choose Apollo over Yoga + +- You want Apollo Studio usage reporting (`studioReporting` option). +- You ship persisted-query manifests built by Apollo's CLI / Rover. +- Your team already runs Apollo's federation tooling in adjacent + services. +- You need Apollo's plugin ecosystem (cost analyser, request + coalescer, custom cache plugin, …). + +Otherwise, Yoga is the faster default — fewer allocations per request, +slimmer dependency closure. + +## Modules + +- `engine` — `ApolloGraphqlEngine`, `createApolloGraphqlEngine`. +- `options` — Zod-validated `ApolloGraphqlOptions` schema. +- `error-codes` — `GRAPHQL_APOLLO.*` registry + `GraphqlApolloError`. +- `instruments` — engine-agnostic `graphql.*` OTel surface. +- `guards` — depth + complexity rejection helpers. +- `persisted-queries` — APQ manifest loader. +- `studio-reporting` — Apollo Studio descriptor bridge. +- `subscriptions` — `graphql-ws` runner. +- `loaders` — per-request DataLoader scope. +- `federation` — `mergeSdl` passthrough. +- `endpoints` — HTTP + UI proxy mounts. +- `testing` — `runApolloConformance` re-export. + +## Status + +Original. Owned by the `api-stack` super-category. +Passes the abstract conformance harness with the same invariants Yoga +satisfies — see `src/engine/apollo-engine.spec-conformance.test.ts`. + diff --git a/docs/api-stack/api/api-graphql-apollo/src/endpoints/http.md b/docs/api-stack/api/api-graphql-apollo/src/endpoints/http.md new file mode 100644 index 0000000..14b6714 --- /dev/null +++ b/docs/api-stack/api/api-graphql-apollo/src/endpoints/http.md @@ -0,0 +1,80 @@ +# `endpoints/http` — `POST /graphql` + `GET /graphql/sdl` + +## Purpose + +`endpoints/http` mounts the two HTTP endpoints every GraphQL adapter +must expose: `POST /graphql` for operation dispatch and +`GET /graphql/sdl` for schema introspection by external tooling. The +paths are driven by `ApolloGraphqlOptions` so operators can rename +them — useful for shops that namespace internal APIs under `/internal/`. + +The module is framework-agnostic in that it takes a `Router` from +`@suaveplan/api-router` and registers handlers via the router's verb +methods. Concrete router adapters (`api-router-hono`, +`api-router-in-memory`) consume the same `Router` interface. + +## Features + +- Mount paths driven by `ApolloGraphqlOptions.endpoint` / + `sdlEndpoint`. +- `executeQuery` handler accepts a `{ body, headers, context }` envelope + — the host's request pipeline decodes the HTTP frame into this shape + before dispatch. +- `sdl` handler returns the merged SDL synchronously. +- Returns a teardown function (currently no-op; reserved for hot + reload). +- Empty `headers` default — handlers that the host invokes without an + explicit map see `{}` rather than `undefined`. + +## Usage: Basic + +```ts +import { Router } from "@suaveplan/api-router"; +import { mountGraphqlHttpEndpoints } from "@suaveplan/api-graphql-apollo/endpoints"; +import { parseApolloGraphqlOptions } from "@suaveplan/api-graphql-apollo/options"; + +const router = new Router(); +mountGraphqlHttpEndpoints({ + router, + options: parseApolloGraphqlOptions(), + executeQuery: async (r) => ({ data: { ok: true } }), + sdl: () => "type Query { ok: Boolean! }", +}); +``` + +## Usage: Advanced + +Drive the executeQuery handler through the engine instead of a stub +so the router calls into Apollo Server's lifecycle on every POST: + +```ts +import { createApolloGraphqlEngine } from "@suaveplan/api-graphql-apollo"; + +const engine = createApolloGraphqlEngine(); +engine.buildSchema(registry); +mountGraphqlHttpEndpoints({ + router, + options, + executeQuery: async ({ body, context }) => { + const req = body as { query: string; variables?: Record }; + return await engine.executeQuery(req, context as RequestContext); + }, + sdl: () => engine.sdl() ?? "", +}); +``` + +## API Reference + +- `GraphqlHttpHandler` — `(req: { body, headers, context }) → Promise`. +- `GraphqlSdlHandler` — `() → string`. +- `MountHttpEndpointsArgs` — `{ router, options, executeQuery, sdl }`. +- `mountGraphqlHttpEndpoints(args): () → void` — returns teardown. + +## Implementation Notes + +The handler returns a free-form `Record` because the +host's transport adapter serialises the response to wire form. The +SDL handler is synchronous on purpose; SDL is computed once at +`buildSchema` time and held in memory thereafter. The teardown +closure is a no-op today but exists so callers do not need to rewrite +their host-wiring code when hot reload lands. diff --git a/docs/api-stack/api/api-graphql-apollo/src/endpoints/ui-proxy.md b/docs/api-stack/api/api-graphql-apollo/src/endpoints/ui-proxy.md new file mode 100644 index 0000000..3541fd5 --- /dev/null +++ b/docs/api-stack/api/api-graphql-apollo/src/endpoints/ui-proxy.md @@ -0,0 +1,74 @@ +# `endpoints/ui-proxy` — `/graphql/ui` proxy + +## Purpose + +`endpoints/ui-proxy` mounts the `/graphql/ui` endpoint. The Apollo +engine never embeds Apollo's landing page — UI is opt-in via a +separate package (GraphiQL, Altair, …), identical to Yoga's stance. +When no UI plugin is wired the endpoint returns `404` with a short +text body explaining the policy; when a plugin is wired the endpoint +forwards its `render()` output verbatim. + +This module is deliberately framework-agnostic: it accepts a +`@suaveplan/api-router` `Router` and a UI plugin descriptor with a +`render()` method. The host wires whichever GraphiQL / Altair package +it prefers without the engine becoming aware of the choice. + +## Features + +- 404 by default — no Apollo landing page leakage. +- Custom mime type — UI plugins that ship binary (e.g. WASM) bodies + can override the default `text/html`. +- Driven by `ApolloGraphqlOptions.uiEndpoint` — operator can rename + the path. +- Returns a teardown handle reserved for future hot reload. + +## Usage: Basic + +```ts +import { Router } from "@suaveplan/api-router"; +import { mountGraphqlUiProxy } from "@suaveplan/api-graphql-apollo/endpoints"; +import { parseApolloGraphqlOptions } from "@suaveplan/api-graphql-apollo/options"; + +const router = new Router(); +mountGraphqlUiProxy({ + router, + options: parseApolloGraphqlOptions(), + ui: null, +}); +// GET /graphql/ui → 404 +``` + +## Usage: Advanced + +Wire a GraphiQL-style UI plugin so the same router serves the +playground at `/graphql/ui`: + +```ts +mountGraphqlUiProxy({ + router, + options, + ui: { + render: () => + ` + +

+ + `, + }, +}); +``` + +## API Reference + +- `GraphqlUiPlugin` — `{ render(): string; contentType?: string }`. +- `UiProxyResponse` — `{ status: 200 | 404; body: string; contentType: string }`. +- `mountGraphqlUiProxy(args): () → void`. + +## Implementation Notes + +The UI plugin contract is intentionally minimal — `render()` returns +a string and the proxy serves it. Future evolution (CSP nonces, +per-tenant configuration) lives in the UI plugin itself, not in this +module. The 404 response body is `text/plain` so curl users see a +human-readable explanation rather than an empty page. diff --git a/docs/api-stack/api/api-graphql-apollo/src/engine/apollo-engine.md b/docs/api-stack/api/api-graphql-apollo/src/engine/apollo-engine.md new file mode 100644 index 0000000..1fa90ec --- /dev/null +++ b/docs/api-stack/api/api-graphql-apollo/src/engine/apollo-engine.md @@ -0,0 +1,105 @@ +# `engine/apollo-engine` — `ApolloGraphqlEngine` + + +_(no submodules)_ + + +## Purpose + +`ApolloGraphqlEngine` is the concrete Apollo Server implementation of +the `@suaveplan/api-graphql` engine contract. It owns the Apollo +Server instance, the merged executable schema, the persisted-query +manifest plumbing, the request-time depth and complexity guards, and +the OTel instrument emission. The factory `createApolloGraphqlEngine` +hands out fresh instances; the class is `new`-able for tests and +power users that want subclass overrides. + +Every operation pivots on three lifecycle calls: `buildSchema` once +at boot (or on hot reload), `executeQuery` per request, `dispose` at +shutdown. Schema rebuild gracefully tears down the prior Apollo +instance only when its startup has completed — a half-started server +is left alone, which is safe because the new server replaces the +slot. + +## Features + +- Implements every `GraphqlEngine` method — `buildSchema`, + `executeQuery`, `executeSubscription`, `dispose`. +- Pluggable `instruments`, `persistedQueries`, `apolloPlugins` + dependencies — sane defaults, full override. +- Depth + complexity guards run BEFORE Apollo sees the document so + the engine rejects pathological queries cheaply. +- `requestTimeoutMs` enforced via a race against a `setTimeout`- + driven rejection — the timer is `unref`'d so it never holds the + event loop open. +- `attachResolvers` resolves SDL-declared fields against the + registry's resolver maps; unknown types and unknown fields are + silently skipped so plugin authors can register superset maps + without runtime breakage. +- Introspection denial layered above Apollo's + `introspection: false` flag so the engine raises a typed error + before Apollo even validates the document. + +## Usage: Basic + +```ts +import { createGraphqlRegistry } from "@suaveplan/api-graphql"; +import { createApolloGraphqlEngine } from "@suaveplan/api-graphql-apollo"; + +const engine = createApolloGraphqlEngine(); +const registry = createGraphqlRegistry(); +registry.addTypes("type Query { ping: String! }"); +registry.addResolvers({ Query: { ping: () => "pong" } }); +engine.buildSchema(registry); +const result = await engine.executeQuery( + { query: "{ ping }" }, + requestContext +); +await engine.dispose(); +``` + +## Usage: Advanced + +Wire persisted queries, custom instruments, a 5-second timeout, and a +custom Apollo plugin for cache control: + +```ts +import { createApolloGraphqlEngine } from "@suaveplan/api-graphql-apollo"; +import { createInstruments } from "@suaveplan/api-graphql-apollo/instruments"; +import { createPersistedQueryManifest } from "@suaveplan/api-graphql-apollo/persisted-queries"; + +const instruments = createInstruments(); +const persistedQueries = createPersistedQueryManifest([ + ["abc123", "{ ping }"], +]); +const engine = createApolloGraphqlEngine({ + instruments, + persistedQueries, + apolloPlugins: [cacheControlPlugin], + options: { requestTimeoutMs: 5000, maxQueryDepth: 12 }, +}); +``` + +## API Reference + +- `class ApolloGraphqlEngine implements GraphqlEngine`. + - `constructor(args?: CreateApolloGraphqlEngineArgs)` + - `buildSchema(registry): MergedSchema` + - `executeQuery(req, ctx): Promise` + - `executeSubscription(req, ctx): AsyncIterable` + - `dispose(): Promise` + - `sdl(): string | null` +- `createApolloGraphqlEngine(args?): ApolloGraphqlEngine`. +- `raceWithTimeout(p, ms): Promise` — exported for unit testing. + +## Implementation Notes + +`startInBackgroundHandlingStartupErrorsByLoggingAndFailingAllRequests` +was rejected in favour of an explicit `start()` Promise because the +former turns a startup failure into per-request rejections we cannot +discriminate cleanly. The current implementation awaits the start +promise inside `executeQuery` and again inside `dispose` so a failed +start never leaves the engine in a half-stopped state. The +`raceWithTimeout` helper is exported so a focused unit test can +exercise both the resolve and reject branches without standing up an +Apollo Server. diff --git a/docs/api-stack/api/api-graphql-apollo/src/error-codes/error-codes.md b/docs/api-stack/api/api-graphql-apollo/src/error-codes/error-codes.md new file mode 100644 index 0000000..a492482 --- /dev/null +++ b/docs/api-stack/api/api-graphql-apollo/src/error-codes/error-codes.md @@ -0,0 +1,86 @@ +# `error-codes` — `GRAPHQL_APOLLO.*` registry + + +_(no submodules)_ + + +## Purpose + +`error-codes` defines the stable `GRAPHQL_APOLLO.*` namespace plus the +`GraphqlApolloError` class consumed by every other module in the +`@suaveplan/api-graphql-apollo` package. It sits in the same shape as the +sibling `@suaveplan/api-graphql` registry so callers can write a single +`instanceof SuaveplanError` discriminator and narrow further on +`error.code`. + +The registry covers ten codes — request-document parse and validation +failures, depth and complexity guard rejections, schema-build failures +inside Apollo, the missing-transport case for subscriptions, request +timeouts, introspection-denied responses, persisted-query lookup misses, +and the resolver-attach catch-all. Every code is thrown by a production +path; the conformance harness enforces that empirically. + +## Features + +- Frozen `defineCodes("GRAPHQL_APOLLO", […])` registry — no untyped string + ever escapes the package. +- `GraphqlApolloError` exposes the code via both the inherited `error.code` + and a narrowed `graphqlApolloCode` field; either narrows downstream code + to the union of ten possible values. +- Constructor preserves `cause` and `context` per the `SuaveplanError` + contract — wrappers can attach the raw `cause: Error` for crash dumps. +- The class sets `this.name = "GraphqlApolloError"` so logs surface the + concrete subclass. + +## Usage: Basic + +```ts +import { + GRAPHQL_APOLLO_CODES, + GraphqlApolloError, +} from "@suaveplan/api-graphql-apollo/error-codes"; + +throw new GraphqlApolloError( + GRAPHQL_APOLLO_CODES.PARSE_FAILED, + "request document failed to parse" +); +``` + +## Usage: Advanced + +Attach a cause and a context payload that the OTel span recorder will +attach as event attributes: + +```ts +import { GraphqlApolloError } from "@suaveplan/api-graphql-apollo/error-codes"; + +try { + JSON.parse(maybeJson); +} catch (cause) { + throw new GraphqlApolloError( + "GRAPHQL_APOLLO.PARSE_FAILED", + "persisted-query manifest is not valid JSON", + { cause: cause as Error, context: { path: "./pq.json" } } + ); +} +``` + +## API Reference + +- `GRAPHQL_APOLLO_CODES` — frozen object mapping each short name to its + fully-qualified code string. +- `GraphqlApolloErrorCode` — union of every code value resolved through + `GRAPHQL_APOLLO_CODES`. +- `class GraphqlApolloError extends SuaveplanError`. + - `constructor(code, message, options?)` + - `graphqlApolloCode` — convenience accessor pre-narrowed to the + `GraphqlApolloErrorCode` union. + +## Implementation Notes + +The codes intentionally mirror the design-doc §10.5 list. Adding a new +code requires (a) appending it to the `defineCodes` array, (b) wiring at +least one production throw site, and (c) extending the conformance +checklist. The `name` field is set so structured logs see +`GraphqlApolloError` rather than the generic `SuaveplanError`. The class +extends the abstract `SuaveplanError` directly — no intermediate base. diff --git a/docs/api-stack/api/api-graphql-apollo/src/federation/federation.md b/docs/api-stack/api/api-graphql-apollo/src/federation/federation.md new file mode 100644 index 0000000..d5a6dd5 --- /dev/null +++ b/docs/api-stack/api/api-graphql-apollo/src/federation/federation.md @@ -0,0 +1,70 @@ +# `federation` — multi-plugin SDL merger + + +_(no submodules)_ + + +## Purpose + +`federation` is the engine's facade over the canonical `mergeSdl` +function from `@suaveplan/api-graphql`. Apollo doesn't see federated +plugin contributions directly — the engine collects every plugin's +SDL via the abstract `GraphqlRegistry`, federates them through this +module, and feeds the merged SDL to `buildSchema()`. Collision +detection, namespace wrapping, and strict-mode policy come for free +because all three are owned by the abstract merger. + +The module is intentionally a one-line passthrough; it exists so the +package surface signals "yes, Apollo federates the same way Yoga +does — `GRAPHQL.SCHEMA_COLLISION` is the canonical code on either +engine". + +## Features + +- 1:1 delegation to `@suaveplan/api-graphql.mergeSdl` — no shape + change, no behaviour change. +- Same collision semantics as Yoga — `GRAPHQL.SCHEMA_COLLISION` is + raised, NOT a `GRAPHQL_APOLLO.*` code. +- Strict-mode propagation — `strictNamespace: true` requires every + plugin to declare a `graphql.namespace`. +- Returns the canonical `MergedSchema` shape so engine internals stay + assignable to the abstract contract. + +## Usage: Basic + +```ts +import { federateForApollo } from "@suaveplan/api-graphql-apollo/federation"; + +const merged = federateForApollo([ + { plugin: "billing", typeDefs: ["type Query { invoice: String! }"] }, + { plugin: "users", typeDefs: ["extend type Query { me: String! }"] }, +]); +console.log(merged.sdl); +``` + +## Usage: Advanced + +Enable strict-mode federation across all plugins to enforce a +namespace contract before the host even compiles: + +```ts +import { federateForApollo } from "@suaveplan/api-graphql-apollo/federation"; + +federateForApollo(contributions, { strictNamespace: true }); +// → throws GRAPHQL.NAMESPACE_REQUIRED if any plugin omitted namespace +``` + +## API Reference + +- `federateForApollo(contributions, options?): MergedSchema` + - delegates to `@suaveplan/api-graphql.mergeSdl`. + +## Implementation Notes + +The function exists primarily so the package's TypeScript exports +expose a `federateForApollo` symbol that mirrors the sibling +`federateForYoga` (when the Yoga adapter lands). The behavioural +contract is owned by the abstract `mergeSdl`. Tests verify that +`GRAPHQL.SCHEMA_COLLISION` and `GRAPHQL.NAMESPACE_REQUIRED` are raised +through this wrapper — concrete proof that Apollo and Yoga agree on +the federation contract. diff --git a/docs/api-stack/api/api-graphql-apollo/src/guards/depth-and-complexity.md b/docs/api-stack/api/api-graphql-apollo/src/guards/depth-and-complexity.md new file mode 100644 index 0000000..7904976 --- /dev/null +++ b/docs/api-stack/api/api-graphql-apollo/src/guards/depth-and-complexity.md @@ -0,0 +1,75 @@ +# `guards/depth-and-complexity` — query-shape rejection + + +_(no submodules)_ + + +## Purpose + +`depth-and-complexity` walks a parsed `DocumentNode` and computes two +coarse static metrics — the maximum selection-set nesting depth and the +total field-count cost. The engine consults both before handing the +document to Apollo Server; queries that exceed `maxQueryDepth` or +`maxQueryComplexity` are rejected with the corresponding +`GRAPHQL_APOLLO.DEPTH_EXCEEDED` / `COMPLEXITY_EXCEEDED` codes. + +The walk follows fragment spreads through their definitions and includes +inline-fragment subselections, so a clever query that hides depth or +cost behind a deeply nested fragment cannot bypass the guards. The +heuristic matches the Yoga sibling so the two engines reject the same +query set under identical limits. + +## Features + +- Depth counter increments per nested `selectionSet`, never on fragment + spreads or inline fragments themselves (matches conventional + depth-limiter implementations). +- Complexity counter adds 1 per selected field, plus the recursive cost + of its subselection, plus the expansion of fragment spreads. Missing + fragment spreads contribute zero. +- `assertDepthAndComplexity` evaluates depth first; the more localised + failure wins so operators see the rule they triggered. +- Pure-functional — no instance state, no `this`. Safe to call from any + request lifecycle phase. + +## Usage: Basic + +```ts +import { parse } from "graphql"; +import { assertDepthAndComplexity } from "@suaveplan/api-graphql-apollo/guards"; + +const doc = parse("{ a { b { c } } }"); +assertDepthAndComplexity(doc, { maxDepth: 10, maxComplexity: 1000 }); +``` + +## Usage: Advanced + +Run the metrics in isolation to feed an OTel histogram before the engine +even routes the document: + +```ts +import { parse } from "graphql"; +import { + maxQueryDepth, + queryComplexity, +} from "@suaveplan/api-graphql-apollo/guards"; + +const doc = parse(req.body.query); +metrics.histogram("graphql.depth").record(maxQueryDepth(doc)); +metrics.histogram("graphql.complexity").record(queryComplexity(doc)); +``` + +## API Reference + +- `maxQueryDepth(doc: DocumentNode): number` +- `queryComplexity(doc: DocumentNode): number` +- `assertDepthAndComplexity(doc, { maxDepth, maxComplexity }): void` — + throws `GraphqlApolloError` on first violation. + +## Implementation Notes + +Fragment definitions are collected up-front into a `Map` so spread +resolution is O(1). Inline fragments share the parent depth — they do +not add a level. The complexity heuristic intentionally undercounts +list multiplicity; production deployments wire a richer estimator via a +host-supplied `costExtension` (out of scope for the foundation engine). diff --git a/docs/api-stack/api/api-graphql-apollo/src/instruments/instruments.md b/docs/api-stack/api/api-graphql-apollo/src/instruments/instruments.md new file mode 100644 index 0000000..cd96601 --- /dev/null +++ b/docs/api-stack/api/api-graphql-apollo/src/instruments/instruments.md @@ -0,0 +1,76 @@ +# `instruments` — engine-agnostic OTel surface + + +_(no submodules)_ + + +## Purpose + +`instruments` owns the five OTel instrument names emitted by every GraphQL +engine adapter in the foundation. Both `api-graphql-apollo` and +`api-graphql-yoga` MUST emit the same set so operator dashboards survive +an engine swap with zero rename work. The names are stable strings (not +generated identifiers); flipping the host's `engine` slot from Yoga to +Apollo or back keeps the time-series continuous. + +The module also ships an in-memory `GraphqlInstruments` implementation +used by unit tests — `createInstruments()` returns a recorder that pushes +to plain arrays so tests can assert exact request counts, schema rebuild +counts, etc. Production hosts pass their own implementation backed by +`@opentelemetry/sdk-metrics`. + +## Features + +- `GRAPHQL_INSTRUMENT_NAMES` frozen object — five canonical + `graphql.*` names. +- `createInstruments()` — zero-arg factory returning an in-memory + recorder with `snapshot()` for assertions. +- Counter + histogram surface: `incRequests`, `recordRequestDurationMs`, + `recordResolverDurationMs`, `incSubscriptionsActive` / + `decSubscriptionsActive`, `incSchemaRebuilds`. +- Snapshot is a deep copy — tests can compare without worrying about + later mutation aliasing the saved value. + +## Usage: Basic + +```ts +import { createInstruments } from "@suaveplan/api-graphql-apollo/instruments"; + +const ins = createInstruments(); +ins.incRequests({ operation: "ping" }); +ins.recordRequestDurationMs(42); +ins.snapshot(); +// → { requestsTotal: 1, requestDurationMs: [42], … } +``` + +## Usage: Advanced + +Plug an OTel-backed instrument set into the engine and assert the +expected metrics are emitted across a workload: + +```ts +import { createApolloGraphqlEngine } from "@suaveplan/api-graphql-apollo"; +import { createInstruments } from "@suaveplan/api-graphql-apollo/instruments"; + +const ins = createInstruments(); +const engine = createApolloGraphqlEngine({ instruments: ins }); +// … buildSchema + executeQuery … +const snap = ins.snapshot(); +console.log(snap.requestsTotal, snap.schemaRebuildsTotal); +``` + +## API Reference + +- `GRAPHQL_INSTRUMENT_NAMES.requestsTotal` (etc.) — exact metric names. +- `GraphqlInstruments` — interface implemented by the in-memory recorder + and by production OTel adapters. +- `InstrumentSnapshot` — read-only snapshot returned by `snapshot()`. +- `createInstruments(): GraphqlInstruments` — in-memory factory. + +## Implementation Notes + +The recorder is deliberately a closure over four primitives + two arrays +— no Map allocations on the hot path. The arrays are copied at snapshot +time so callers cannot mutate the live counters. Engine-agnostic naming +is enforced by the engine-swap integration test in `tests/integration/` +which asserts the metric-name set is identical across Apollo and Yoga. diff --git a/docs/api-stack/api/api-graphql-apollo/src/loaders/loaders.md b/docs/api-stack/api/api-graphql-apollo/src/loaders/loaders.md new file mode 100644 index 0000000..5d19709 --- /dev/null +++ b/docs/api-stack/api/api-graphql-apollo/src/loaders/loaders.md @@ -0,0 +1,75 @@ +# `loaders` — per-request DataLoader scope + + +_(no submodules)_ + + +## Purpose + +`loaders` defines the per-request DataLoader scope the engine creates +around every incoming GraphQL operation. Two concurrent requests +receive distinct loader instances; the cache never leaks across +request boundaries even though both requests draw from the same set of +loader factories registered on the abstract `GraphqlRegistry`. + +The module is deliberately the thinnest possible wrapper around the +`LoaderFactory.create()` surface owned by `@suaveplan/api-types/graphql`. +The engine calls `createRequestLoaderScope()` once per request; resolvers +that need a loader call `scope.get(name, factory)`; the engine disposes +the scope at request end. + +## Features + +- One scope per request — distinct cache per request guaranteed. +- Loader lazily instantiated on first `get(name, factory)` call; + subsequent calls reuse the instance. +- `dispose()` blocks subsequent `get()` calls so a buggy late resolver + cannot resurrect a freed cache. +- Zero runtime dependencies — pure JS, fits in ~40 lines. + +## Usage: Basic + +```ts +import { createRequestLoaderScope } from "@suaveplan/api-graphql-apollo/loaders"; + +const scope = createRequestLoaderScope(); +const userLoader = scope.get("users", userLoaderFactory); +const user = await userLoader.load("u_42"); +scope.dispose(); +``` + +## Usage: Advanced + +Wire the scope into a resolver context object so resolvers consume +loaders by name through the request context: + +```ts +import { createRequestLoaderScope } from "@suaveplan/api-graphql-apollo/loaders"; + +function makeContext(): RequestContext { + const scope = createRequestLoaderScope(); + return { + loaders: { + users: () => scope.get("users", userLoaderFactory), + orders: () => scope.get("orders", orderLoaderFactory), + }, + finalize: () => scope.dispose(), + } as unknown as RequestContext; +} +``` + +## API Reference + +- `RequestLoaderScope`: + - `get(name, factory): { load }` + - `dispose(): void` + - `size(): number` +- `createRequestLoaderScope(): RequestLoaderScope`. + +## Implementation Notes + +The scope is a closure over a `Map` plus a +`disposed` boolean. Throwing on `get` after `dispose` surfaces the +late-resolver bug at the call site instead of silently producing +inconsistent reads. The size accessor is provided so OTel histograms +can record loader-fanout per request. diff --git a/docs/api-stack/api/api-graphql-apollo/src/options/options.md b/docs/api-stack/api/api-graphql-apollo/src/options/options.md new file mode 100644 index 0000000..bec54a9 --- /dev/null +++ b/docs/api-stack/api/api-graphql-apollo/src/options/options.md @@ -0,0 +1,83 @@ +# `options` — `ApolloGraphqlOptions` + + +_(no submodules)_ + + +## Purpose + +`options` owns the Zod-validated configuration surface accepted by +`createApolloGraphqlEngine`. The schema mirrors the Yoga sibling's options +1:1 so an operator can swap engines without touching the host wiring — +defaults agree, paths agree, depth and complexity limits agree, and the +persisted-query path / Studio reporting fields are the Apollo-specific +additions layered on top. + +Inputs cross the Zod boundary once at engine construction time; downstream +code consumes the fully resolved `ApolloGraphqlOptions` shape and never +re-validates. Configuration failures throw `GRAPHQL_APOLLO.PARSE_FAILED` +so caller-visible input errors share a single error code with the +request-document parse path. + +## Features + +- Endpoint paths default to `/graphql`, `/graphql/sdl`, `/graphql/ws`, + `/graphql/ui` — identical to Yoga. +- `introspection: false` by default; flipping the flag wires Apollo's + schema introspection on AND lets the engine skip the + `INTROSPECTION_DENIED` guard. +- `maxQueryDepth` and `maxQueryComplexity` mirror the Yoga defaults + (`10`, `1000`). +- `requestTimeoutMs` defaults to `30_000`; the engine wraps every + `executeOperation` call in a timeout race. +- Persisted-query manifest path is optional; the engine wires the + manifest loader only when `persistedQueriesPath` is set. +- `studioReporting` opt-in — the engine returns `null` from + `createStudioReporting()` when omitted. + +## Usage: Basic + +```ts +import { parseApolloGraphqlOptions } from "@suaveplan/api-graphql-apollo/options"; + +const opts = parseApolloGraphqlOptions({}); +// opts.endpoint === "/graphql" +``` + +## Usage: Advanced + +Wire persisted queries plus Apollo Studio reporting plus a custom error +formatter: + +```ts +import { parseApolloGraphqlOptions } from "@suaveplan/api-graphql-apollo/options"; + +const opts = parseApolloGraphqlOptions({ + persistedQueriesPath: "./pq.json", + studioReporting: { + apiKey: process.env.APOLLO_KEY ?? "", + graphRef: "supergraph@current", + }, + formatError: (err) => ({ msg: String(err), redacted: true }), + requestTimeoutMs: 5_000, +}); +``` + +## API Reference + +- `apolloGraphqlOptionsSchema` — the underlying Zod schema (exported for + introspection / OpenAPI registration). +- `parseApolloGraphqlOptions(input?) → ApolloGraphqlOptions` — throws + `GraphqlApolloError("GRAPHQL_APOLLO.PARSE_FAILED")` on validation + failure. +- `ApolloGraphqlOptions` — fully-resolved options type (every field + required, every default applied). +- `ApolloGraphqlOptionsInput` — input type (every field optional). + +## Implementation Notes + +The schema uses `z.string().startsWith("/")` for every endpoint path — +operator typos like `endpoint: "graphql"` (no leading slash) surface +synchronously at boot. The `formatError` field is `z.custom<(err) => …>` +because Zod has no first-class function type; the custom guard rejects +non-functions with the same `GRAPHQL_APOLLO.PARSE_FAILED` code. diff --git a/docs/api-stack/api/api-graphql-apollo/src/persisted-queries/persisted-queries.md b/docs/api-stack/api/api-graphql-apollo/src/persisted-queries/persisted-queries.md new file mode 100644 index 0000000..fe44a23 --- /dev/null +++ b/docs/api-stack/api/api-graphql-apollo/src/persisted-queries/persisted-queries.md @@ -0,0 +1,74 @@ +# `persisted-queries` — APQ manifest support + + +_(no submodules)_ + + +## Purpose + +`persisted-queries` implements Apollo's persisted-query manifest lookup +— the ability for clients to send `{ id }` in place of `{ query }` and +have the engine resolve the id against a build-time-generated manifest. +The feature is Apollo-specific (Yoga uses a different protocol variant) +so the loader lives in this adapter and not in the abstract +`api-graphql` core. + +The module exposes three entry points: a filesystem loader, an +in-memory parser for callers that already have the JSON text, and a +direct-from-entries factory for tests. Lookups against an unknown id +raise `GRAPHQL_APOLLO.PERSISTED_QUERY_NOT_FOUND`; malformed input +raises `GRAPHQL_APOLLO.PARSE_FAILED` so callers see a single +configuration-failure code for any manifest shape error. + +## Features + +- File loader uses `node:fs/promises.readFile` — async-safe in the host + start-up sequence. +- JSON parser validates the manifest is an object of `string → string` + before returning; non-string values raise `PARSE_FAILED`. +- Direct factory accepts any `Iterable<[id, query]>` — useful in tests. +- Manifest is frozen on construction; the only mutation surface is + `lookup(id)` (reads) and `has(id)` (existence check). +- `entries` accessor returns the frozen map for callers that need to + diff manifests across deploys. + +## Usage: Basic + +```ts +import { loadPersistedQueryManifest } from "@suaveplan/api-graphql-apollo/persisted-queries"; + +const manifest = await loadPersistedQueryManifest("./pq.json"); +const query = manifest.lookup("abc123"); +``` + +## Usage: Advanced + +Build a manifest from an in-process source (e.g. a KV-store fetch) and +wire it into the engine for runtime lookup: + +```ts +import { createApolloGraphqlEngine } from "@suaveplan/api-graphql-apollo"; +import { createPersistedQueryManifest } from "@suaveplan/api-graphql-apollo/persisted-queries"; + +const entries = await kv.list("pq:"); +const manifest = createPersistedQueryManifest( + entries.map((e) => [e.key.slice(3), e.value as string]) +); +const engine = createApolloGraphqlEngine({ persistedQueries: manifest }); +``` + +## API Reference + +- `PersistedQueryManifest` — `{ entries, lookup, has }`. +- `loadPersistedQueryManifest(path: string): Promise` +- `parsePersistedQueryManifest(raw: string): PersistedQueryManifest` +- `createPersistedQueryManifest(entries): PersistedQueryManifest` + +## Implementation Notes + +Manifest entries are stored in a `Map` — O(1) lookup, +deterministic iteration order. The `entries` field returns a new `Map` +constructed from the underlying entries on every access so callers +cannot mutate the live state. The loader maps every filesystem and JSON +failure to `GRAPHQL_APOLLO.PARSE_FAILED` so wire-level diagnostics show +a single code regardless of failure mode. diff --git a/docs/api-stack/api/api-graphql-apollo/src/studio-reporting/studio-reporting.md b/docs/api-stack/api/api-graphql-apollo/src/studio-reporting/studio-reporting.md new file mode 100644 index 0000000..21dd7f5 --- /dev/null +++ b/docs/api-stack/api/api-graphql-apollo/src/studio-reporting/studio-reporting.md @@ -0,0 +1,78 @@ +# `studio-reporting` — Apollo Studio bridge + + +_(no submodules)_ + + +## Purpose + +`studio-reporting` materialises the configuration descriptor consumed +by the engine when an operator opts in to Apollo Studio usage +reporting. The module is deliberately small: it validates the supplied +`apiKey` / `graphRef` pair, returns a frozen descriptor, and lets the +engine forward the descriptor to Apollo's `ApolloServerPluginUsageReporting` +without leaking the SDK weight into the dependency closure of shops +that do not use Studio. + +When the operator does not supply a configuration, the factory returns +`null` and the engine instantiates Apollo Server without the reporting +plugin — the request hot path pays nothing for the unused feature. + +## Features + +- Optional configuration — the factory short-circuits to `null` when + the caller passes `undefined`. +- Frozen descriptor — the returned object is immutable so downstream + code cannot mutate the API-key surface. +- Pluggable — production callers can pre-emptively swap the descriptor + for a mock plugin in a staging environment. +- zero dependency on the Apollo Studio plugin package — the + bridge is data-only. + +## Usage: Basic + +```ts +import { createStudioReporting } from "@suaveplan/api-graphql-apollo/studio-reporting"; + +const d = createStudioReporting({ + apiKey: process.env.APOLLO_KEY ?? "", + graphRef: "supergraph@current", +}); +``` + +## Usage: Advanced + +Conditionally enable reporting per environment without forking the +engine wire-up code: + +```ts +import { createApolloGraphqlEngine } from "@suaveplan/api-graphql-apollo"; +import { createStudioReporting } from "@suaveplan/api-graphql-apollo/studio-reporting"; + +const studio = createStudioReporting( + process.env.APOLLO_KEY === undefined + ? undefined + : { + apiKey: process.env.APOLLO_KEY, + graphRef: "supergraph@" + (process.env.STAGE ?? "current"), + } +); +const engine = createApolloGraphqlEngine({ + apolloPlugins: studio === null ? [] : [/* wire Studio plugin from descriptor */], +}); +``` + +## API Reference + +- `StudioReportingConfig` — `{ apiKey, graphRef }`. +- `StudioReportingDescriptor` — `{ enabled: true, apiKey, graphRef }`. +- `createStudioReporting(config | undefined) → StudioReportingDescriptor | null`. + +## Implementation Notes + +The descriptor is `Object.freeze`d so callers cannot mutate it after +construction. The factory is the only entry point — there is no +mutable runtime state. The actual Studio plugin is dynamically loaded +by callers that want to wire it; this avoids pulling +`@apollo/server-plugin-usage-reporting` into the dependency closure +when the feature is off. diff --git a/docs/api-stack/api/api-graphql-apollo/src/subscriptions/subscriptions.md b/docs/api-stack/api/api-graphql-apollo/src/subscriptions/subscriptions.md new file mode 100644 index 0000000..8850ec4 --- /dev/null +++ b/docs/api-stack/api/api-graphql-apollo/src/subscriptions/subscriptions.md @@ -0,0 +1,81 @@ +# `subscriptions` — `graphql-ws` bridge + + +_(no submodules)_ + + +## Purpose + +`subscriptions` runs a GraphQL subscription document against a wired +schema, returning the `AsyncIterable` the engine +forwards over the host's `api-ws` transport. Subscriptions ride +`graphql-ws` semantically; this module is the framework-agnostic core +that the engine's transport adapter wraps. + +When the host has not wired an `api-ws` engine, the +`assertSubscriptionTransport` guard raises +`GRAPHQL_APOLLO.SUBSCRIPTION_TRANSPORT_UNAVAILABLE` so that the missing +infrastructure surfaces at the first subscription frame — not later +when a publish silently never reaches a subscriber. + +## Features + +- Direct `graphql.subscribe()` delegation — no extra framing. +- Accepts both `DocumentNode` and SDL string for the operation. +- Wraps a single-result rejection in a one-shot AsyncIterable so the + caller's frame loop sees one error frame and closes cleanly. +- Transport guard raises a typed `GraphqlApolloError` with the + `SUBSCRIPTION_TRANSPORT_UNAVAILABLE` code. +- Validates the document contains a subscription operation — non- + subscription operations raise + `GRAPHQL_APOLLO.VALIDATION_FAILED`. + +## Usage: Basic + +```ts +import { runSubscription } from "@suaveplan/api-graphql-apollo/subscriptions"; + +const iter = await runSubscription({ + schema, + document: "subscription { ticks }", + contextValue: { tenantId: "t_1" }, +}); +for await (const frame of iter) { + console.log(frame); +} +``` + +## Usage: Advanced + +Pair the runtime guard with the host's `api-ws` wiring so subscription +frames are rejected at the wire boundary when the transport is not +configured: + +```ts +import { + assertSubscriptionTransport, + runSubscription, +} from "@suaveplan/api-graphql-apollo/subscriptions"; + +const transport = host.adapters.ws ?? null; +assertSubscriptionTransport(transport); +const iter = await runSubscription({ schema, document, contextValue }); +``` + +## API Reference + +- `SubscriptionTransport` — `{ protocol: "graphql-ws" }`. +- `assertSubscriptionTransport(transport | null)` — throws + `GraphqlApolloError` on miss. +- `runSubscription({ schema, document, variableValues?, + operationName?, contextValue })`. + +## Implementation Notes + +When `graphql.subscribe()` returns a single `ExecutionResult` (e.g. +the subscribe field threw synchronously), the helper wraps it in a +single-iteration AsyncIterable so callers' frame loops handle the +error path identically to the streaming path. The validation step +sniffs the document for any `OPERATION_DEFINITION` of kind +`subscription`; documents that contain only query/mutation operations +reject with `VALIDATION_FAILED`. diff --git a/docs/api-stack/api/api-graphql-apollo/src/testing/conformance.md b/docs/api-stack/api/api-graphql-apollo/src/testing/conformance.md new file mode 100644 index 0000000..abc0de5 --- /dev/null +++ b/docs/api-stack/api/api-graphql-apollo/src/testing/conformance.md @@ -0,0 +1,62 @@ +# `testing/conformance` — Apollo-bound conformance harness + + +_(no submodules)_ + + +## Purpose + +`testing/conformance` is the re-export of `runGraphqlEngineConformance` +from `@suaveplan/api-graphql/testing`, pre-bound to the Apollo factory. +Consumers call `runApolloConformance()` and the harness exercises the +abstract `GraphqlEngine` contract against the concrete Apollo adapter. +Both `api-graphql-apollo` and `api-graphql-yoga` MUST pass the same +invariants — operator behaviour is engine-agnostic at the contract +boundary. + +The module also re-exports the unmodified `runGraphqlEngineConformance` +so downstream packages that want to run the harness against a +*different* factory (e.g. a federated subgraph composing Apollo + a +custom transport) keep a single import surface. + +## Features + +- One-line invocation — `runApolloConformance()` runs every scenario. +- Pre-bound factory — callers do not need to know Apollo's + construction args. +- Labelled — the second-positional `label` parameter shows up in + test output so split CI logs are unambiguous. +- Re-exports `runGraphqlEngineConformance` for advanced callers. + +## Usage: Basic + +```ts +import { runApolloConformance } from "@suaveplan/api-graphql-apollo/testing"; + +runApolloConformance(); +``` + +## Usage: Advanced + +Run the conformance suite under a custom label so two adapter variants +appear distinctly in CI output: + +```ts +import { runApolloConformance } from "@suaveplan/api-graphql-apollo/testing"; + +runApolloConformance("apollo (persisted-queries)"); +runApolloConformance("apollo (no-persisted-queries)"); +``` + +## API Reference + +- `runApolloConformance(label?: string): void`. +- `runGraphqlEngineConformance(opts): void` — unchanged re-export. + +## Implementation Notes + +The Apollo-bound factory yields a fresh engine per scenario so each +invariant exercises a clean lifecycle. The `makeRequestContext` slot +is the cast `{} as RequestContext` — sufficient for the abstract +contract because the harness never touches context fields beyond +hand-off. Tests that need a richer context construct one explicitly. diff --git a/docs/api-stack/api/api-graphql-ui-altair/README.md b/docs/api-stack/api/api-graphql-ui-altair/README.md new file mode 100644 index 0000000..5450ad5 --- /dev/null +++ b/docs/api-stack/api/api-graphql-ui-altair/README.md @@ -0,0 +1,97 @@ +# @suaveplan/api-graphql-ui-altair — Altair GraphQL UI plugin for the Suaveplan API plugin system. Mounts the Altair shell at GET /graphql/ui via createAltairUi(opts), serves bundled (no-CDN) assets from a hashed static map, embeds graphqlEndpoint / subscriptionEndpoint / initialQuery / initialHeaders / initialEnvironments into the shell, attaches a strict CSP (no script 'unsafe-inline'), increments graphql.ui.requests_total{ ui: "altair" } via an injectable MeterProvider, and refuses endpoint collisions with the GRAPHQL_UI_ALTAIR_ENDPOINT_COLLISION code. Structural sibling of api-graphql-ui-graphiql. + +Altair GraphQL UI plugin for the Suaveplan API plugin +system. Structural sibling of `@suaveplan/api-graphql-ui-graphiql`. + + +## Documentation tree + +- [assets](./src/assets/assets.md) — `assets` ships the Altair shell as a static-asset map keyed by logical filename. Every entry carries a content-type, th… + - [assets](./src/assets/assets.md) — `assets` ships the Altair shell as a static-asset map keyed by logical filename. Every entry carries a content-type, th… +- [error-codes](./src/error-codes/error-codes.md) — `error-codes` is the package's single source of truth for the two stable error codes the Altair UI plugin emits. Centra… + - [error-codes](./src/error-codes/error-codes.md) — `error-codes` is the package's single source of truth for the two stable error codes the Altair UI plugin emits. Centra… +- [factory](./src/factory/create-altair-ui.md) — `factory/create-altair-ui` is the package's public entry point. `createAltairUi(opts)` validates the caller's options a… + - [create-altair-ui](./src/factory/create-altair-ui.md) — `factory/create-altair-ui` is the package's public entry point. `createAltairUi(opts)` validates the caller's options a… +- [headers](./src/headers/csp.md) — `headers/csp` produces the Content-Security-Policy and the two ancillary security headers (`X-Content-Type-Options`, `R… + - [csp](./src/headers/csp.md) — `headers/csp` produces the Content-Security-Policy and the two ancillary security headers (`X-Content-Type-Options`, `R… +- [html](./src/html/render-shell.md) — `html/render-shell` produces the single HTML document the Altair UI plugin serves at ``. The shell mounts a… + - [render-shell](./src/html/render-shell.md) — `html/render-shell` produces the single HTML document the Altair UI plugin serves at ``. The shell mounts a… +- [instruments](./src/instruments/instruments.md) — `instruments` owns the package's single OpenTelemetry counter, `graphql.ui.requests_total`, labelled with the constant… + - [instruments](./src/instruments/instruments.md) — `instruments` owns the package's single OpenTelemetry counter, `graphql.ui.requests_total`, labelled with the constant… +- [options](./src/options/options.md) — `options` owns the Zod-validated configuration surface every consumer of the Altair UI plugin passes through. The schem… + - [options](./src/options/options.md) — `options` owns the Zod-validated configuration surface every consumer of the Altair UI plugin passes through. The schem… + + +## What this package is + +- **Opt-in.** The host serves nothing at `/graphql/ui` unless this + plugin (or its GraphiQL sibling) is wired against the router. +- **Bundled assets only — no CDN.** Every asset the HTML shell loads + ships inside this package's `dist/` output. The plugin works in + air-gapped, offline-first environments. +- **Alternative to GraphiQL, not co-existing.** Operators wire one or + the other against `/graphql/ui`. Both at once is refused by host + config (the engine adapters return 404 there when neither is wired). + +## Quick start + +```ts +import { createAltairUi } from "@suaveplan/api-graphql-ui-altair"; +import { Router } from "@suaveplan/api-router"; + +const router = new Router(); +const altair = createAltairUi(); +altair.mount(router); + +// router.match("GET", "/graphql/ui") resolves to the Altair HTML handler. +``` + +## Configuration + +```ts +createAltairUi({ + uiEndpoint: "/graphql/ui", // default + graphqlEndpoint: "/graphql", // default + subscriptionEndpoint: "/graphql/ws", // default + theme: "system", // "light" | "dark" | "system" + initialQuery: "", + initialHeaders: { "x-tenant": "acme" }, + initialEnvironments: { + production: { + url: "https://api.example.com/graphql", + subscriptionsEndpoint: "wss://api.example.com/graphql", + headers: { "x-env": "prod" }, + variables: { region: "us-east-1" }, + }, + }, +}); +``` + +## Security posture + +- Strict Content-Security-Policy on every HTML response. +- `script-src 'self'` — no inline scripts. +- `style-src 'self' 'unsafe-inline'` — required for the Altair shell. +- `frame-ancestors 'none'` — clickjacking defence. +- `X-Content-Type-Options: nosniff`, `Referrer-Policy: no-referrer`. +- Static assets carry `Cache-Control: public, max-age=31536000, immutable`. + +## Observability + +Emits one OTel counter: `graphql.ui.requests_total` with label +`ui="altair"`. The metric name is deliberately identical to the +GraphiQL sibling so dashboards can sum across both UIs by dropping +the `ui` label. + +## Error codes + +- `GRAPHQL_UI_ALTAIR.ASSET_MISSING` — request for a static asset the + bundled registry doesn't recognise (404). +- `GRAPHQL_UI_ALTAIR.ENDPOINT_COLLISION` — `mount()` called against a + router that already serves `GET ` (typically the + GraphiQL sibling is wired against the same path). + +## License + +MIT + diff --git a/docs/api-stack/api/api-graphql-ui-altair/src/assets/assets.md b/docs/api-stack/api/api-graphql-ui-altair/src/assets/assets.md new file mode 100644 index 0000000..0ecff65 --- /dev/null +++ b/docs/api-stack/api/api-graphql-ui-altair/src/assets/assets.md @@ -0,0 +1,85 @@ +# `assets` — Bundled asset registry, resolver, CDN-clean check + + +_(no submodules)_ + + +## Purpose + +`assets` ships the Altair shell as a static-asset map keyed by logical +filename. Every entry carries a content-type, the payload bytes, and a +short SHA-256 hash derived once at module init so cache-bust URLs are +stable across deploys with unchanged payloads. The shell is shipped +inline (no FS reads at request time, no CDN fetches) which preserves +the Altair plugin's hermetic-bundle guarantee — the package can boot in +air-gapped, offline-first environments and still serve a usable UI. + +## Features + +- Default registry: `altair.js` + `altair.css`. +- `defineAsset(name, contentType, body)` returns a frozen `BundledAsset`. +- `resolveAsset(registry, uiEndpointBase, name)` produces a + `ResolvedAsset` with a hash-busted URL. +- Missing names throw `GraphqlUiAltairError` (`ASSET_MISSING`). +- `findExternalHostReferences` is the CDN-clean conformance check. +- Hash derivation is SHA-256, truncated to 16 hex chars — same + cardinality as a `git rev-parse --short=16`. + +## Usage: Basic + +```ts +import { + buildDefaultAssetRegistry, + resolveAsset, +} from "@suaveplan/api-graphql-ui-altair/assets"; + +const registry = buildDefaultAssetRegistry(); +const jsAsset = resolveAsset(registry, "/graphql/ui", "altair.js"); +console.log(jsAsset.url); // /graphql/ui/assets//altair.js +``` + +## Usage: Advanced + +```ts +import { + buildDefaultAssetRegistry, + defineAsset, + findExternalHostReferences, +} from "@suaveplan/api-graphql-ui-altair/assets"; + +// Extend the registry with an operator-specific asset. +const registry = new Map(buildDefaultAssetRegistry()); +registry.set( + "logo.svg", + defineAsset( + "logo.svg", + "image/svg+xml", + '' + ) +); + +const offenders = findExternalHostReferences(registry); +if (offenders.length > 0) { + throw new Error("CDN leak: " + offenders.join(", ")); +} +``` + +## API Reference + +- `BundledAsset` — `{ name, contentType, body, hash }`. +- `ResolvedAsset extends BundledAsset` — adds `url`. +- `defineAsset(name, contentType, body): BundledAsset`. +- `buildDefaultAssetRegistry(): ReadonlyMap`. +- `resolveAsset(registry, uiEndpointBase, name): ResolvedAsset` — throws + `GraphqlUiAltairError` (`ASSET_MISSING`) on misses. +- `findExternalHostReferences(registry): readonly string[]`. + +## Implementation Notes + +The asset bodies are held as JavaScript template literals so the build +emits them as plain string constants — no FS access at boot, no +`process.cwd()` dependence. The hash is computed via `node:crypto` to +match the same hashing the rest of the project's static-asset +pipeline uses; the truncation to 16 hex chars is intentional — a +collision in a single deploy's asset set is vanishingly unlikely and +the shorter URL is easier on the eyes in production logs. diff --git a/docs/api-stack/api/api-graphql-ui-altair/src/error-codes/error-codes.md b/docs/api-stack/api/api-graphql-ui-altair/src/error-codes/error-codes.md new file mode 100644 index 0000000..8e08aef --- /dev/null +++ b/docs/api-stack/api/api-graphql-ui-altair/src/error-codes/error-codes.md @@ -0,0 +1,83 @@ +# `error-codes` — `GRAPHQL_UI_ALTAIR.*` registry + + +_(no submodules)_ + + +## Purpose + +`error-codes` is the package's single source of truth for the two stable +error codes the Altair UI plugin emits. Centralising the codes here lets +the factory, the asset map, and any downstream observability tooling +import the literal strings from one location — no string-typos, no +divergence between the wire format and the registry. The registry is +frozen at module init and validated against the umbrella `defineCodes` +contract from `@suaveplan/error` so accidental drift is caught at type +check time, not at runtime. + +## Features + +- Two codes: `GRAPHQL_UI_ALTAIR.ASSET_MISSING`, + `GRAPHQL_UI_ALTAIR.ENDPOINT_COLLISION`. +- Concrete `GraphqlUiAltairError` class extending `SuaveplanError`. +- `altairCode` narrows to `GraphqlUiAltairErrorCode` for exhaustive + switch statements. +- Compatible with the umbrella redaction + i18n + OTel span-event + adapters shipped by `@suaveplan/error`. + +## Usage: Basic + +```ts +import { + GRAPHQL_UI_ALTAIR_CODES, + GraphqlUiAltairError, +} from "@suaveplan/api-graphql-ui-altair/error-codes"; + +throw new GraphqlUiAltairError( + GRAPHQL_UI_ALTAIR_CODES.ASSET_MISSING, + "Asset not present in bundled map", + { context: { path: "/graphql/ui/assets/missing.js" } } +); +``` + +## Usage: Advanced + +```ts +import { + GRAPHQL_UI_ALTAIR_CODES, + GraphqlUiAltairError, +} from "@suaveplan/api-graphql-ui-altair/error-codes"; + +function handle(err: unknown): number { + if (err instanceof GraphqlUiAltairError) { + switch (err.altairCode) { + case GRAPHQL_UI_ALTAIR_CODES.ASSET_MISSING: + return 404; + case GRAPHQL_UI_ALTAIR_CODES.ENDPOINT_COLLISION: + return 409; + } + } + return 500; +} +``` + +## API Reference + +- `GRAPHQL_UI_ALTAIR_CODES` — frozen record `{ ASSET_MISSING, ENDPOINT_COLLISION }`. +- `GraphqlUiAltairErrorCode` — discriminated union of the two literal + strings. +- `class GraphqlUiAltairError extends SuaveplanError` + — owns the `altairCode` accessor. + +## Implementation Notes + +`defineCodes("GRAPHQL_UI_ALTAIR", ...)` produces the prefixed literal +strings — agents must not hand-build the strings to avoid prefix drift. +The error class delegates entirely to `SuaveplanError` for context +serialisation, cause chains, and the wire-format adapter; the only +local responsibility is preserving `altairCode` for `instanceof` +narrowing in operator-facing error handlers. The two-code surface is +intentionally minimal: the asset path is the only failure mode at HTTP +boundary, and endpoint collision is the only failure mode at mount +boundary. Adding a code requires an OpenSpec change so the registry +shape never drifts silently between the spec and the runtime. diff --git a/docs/api-stack/api/api-graphql-ui-altair/src/factory/create-altair-ui.md b/docs/api-stack/api/api-graphql-ui-altair/src/factory/create-altair-ui.md new file mode 100644 index 0000000..a5e8656 --- /dev/null +++ b/docs/api-stack/api/api-graphql-ui-altair/src/factory/create-altair-ui.md @@ -0,0 +1,88 @@ +# `factory/create-altair-ui` — Altair UI plugin factory + + +_(no submodules)_ + + +## Purpose + +`factory/create-altair-ui` is the package's public entry point. +`createAltairUi(opts)` validates the caller's options against the Zod +schema, builds the asset registry and OTel instruments, and returns a +`RouterPlugin` whose `mount(router)` method registers `GET ` +plus the hashed-asset routes against any `Router` instance. Endpoint +collisions are detected up-front via `router.collidesWith` and reject +the mount with a typed `GRAPHQL_UI_ALTAIR.ENDPOINT_COLLISION` error +before any route is written — partial mounts are impossible. + +## Features + +- Zero-config call: `createAltairUi()` works out of the box. +- Returns a frozen `RouterPlugin` with `name`, `options`, `mount`, + `renderHtml`, and `renderAsset` members. +- HTML response always carries the strict CSP + ancillary security + headers. +- Asset response carries `Cache-Control: public, max-age=31536000, immutable`. +- Asset misses (wrong hash, wrong name) throw `GraphqlUiAltairError` + with code `ASSET_MISSING`. +- Endpoint collisions throw `GraphqlUiAltairError` with code + `ENDPOINT_COLLISION` before any route is registered. +- Injectable internals (`assetRegistry`, `instruments`) for integration + tests and operators wanting custom asset bundles. + +## Usage: Basic + +```ts +import { createAltairUi } from "@suaveplan/api-graphql-ui-altair/factory"; +import { Router } from "@suaveplan/api-router"; + +const router = new Router(); +const altair = createAltairUi(); +altair.mount(router); + +// router.match("GET", "/graphql/ui") now resolves to the HTML handler. +``` + +## Usage: Advanced + +```ts +import { createAltairUi } from "@suaveplan/api-graphql-ui-altair/factory"; +import { createAltairInstruments } from "@suaveplan/api-graphql-ui-altair/instruments"; +import { MeterProvider } from "@opentelemetry/sdk-metrics"; +import { Router } from "@suaveplan/api-router"; + +const meterProvider = new MeterProvider(); +const instruments = createAltairInstruments({ meterProvider }); + +const router = new Router(); +const altair = createAltairUi( + { + uiEndpoint: "/dev/altair", + graphqlEndpoint: "/api/graphql", + theme: "dark", + initialEnvironments: { + production: { + url: "https://api.example.com/graphql", + headers: { "x-tenant": "acme" }, + }, + }, + }, + { instruments } +); +altair.mount(router); +``` + +## API Reference + +- `createAltairUi(input?: AltairUiOptionsInput, internals?: CreateAltairUiInternals): RouterPlugin`. +- `RouterPlugin` — `{ name, options, mount(router), renderHtml(), renderAsset(hash, name) }`. +- `CreateAltairUiInternals` — `{ assetRegistry?, instruments? }`. + +## Implementation Notes + +The factory composes five lower-level modules — options, assets, html, +headers, instruments — and exposes their behaviour behind one +ergonomic entry point. The `RouterPlugin.options` field is the parsed, +defaulted bundle (not the caller's raw input) so downstream code reads +the same value the renderer wrote. Frozen-everything posture means +operators cannot accidentally mutate the plugin between `mount` calls. diff --git a/docs/api-stack/api/api-graphql-ui-altair/src/headers/csp.md b/docs/api-stack/api/api-graphql-ui-altair/src/headers/csp.md new file mode 100644 index 0000000..37bb195 --- /dev/null +++ b/docs/api-stack/api/api-graphql-ui-altair/src/headers/csp.md @@ -0,0 +1,78 @@ +# `headers/csp` — Strict CSP for the Altair shell + + +_(no submodules)_ + + +## Purpose + +`headers/csp` produces the Content-Security-Policy and the two ancillary +security headers (`X-Content-Type-Options`, `Referrer-Policy`) the +Altair plugin attaches to its HTML response. The policy is deliberately +strict — no `'unsafe-inline'` on `script-src` — so a regression that +sneaks an inline script into the shell template breaks loud at policy +enforcement, not at audit time. The same posture is used by the +GraphiQL sibling so dashboards and auditors can compare both packages +on equal terms. + +## Features + +- Single `Content-Security-Policy` string with eight directives. +- `'unsafe-inline'` is permitted ONLY on `style-src` — required for + Altair's shell styling, never for scripts. +- `frame-ancestors 'none'` denies embedding (clickjacking defence). +- Ancillary headers: `X-Content-Type-Options: nosniff`, + `Referrer-Policy: no-referrer`. +- Header bundle returned frozen so downstream middleware can't mutate + it by accident. + +## Usage: Basic + +```ts +import { buildAltairResponseHeaders } from "@suaveplan/api-graphql-ui-altair/headers"; + +const headers = buildAltairResponseHeaders(); +// headers["Content-Security-Policy"] === "default-src 'self'; ..." +``` + +## Usage: Advanced + +```ts +import { + ALTAIR_CSP_HEADER_NAME, + ALTAIR_CSP_HEADER_VALUE, + buildAltairResponseHeaders, +} from "@suaveplan/api-graphql-ui-altair/headers"; + +// Drop onto a Fetch-style Response. +function respond(body: string): Response { + const headers = new Headers(buildAltairResponseHeaders()); + headers.set("Content-Type", "text/html; charset=utf-8"); + return new Response(body, { status: 200, headers }); +} + +// Direct access for static header injection (e.g. CDN edge config). +console.log(`${ALTAIR_CSP_HEADER_NAME}: ${ALTAIR_CSP_HEADER_VALUE}`); +``` + +## API Reference + +- `buildAltairResponseHeaders(): Readonly>` +- `ALTAIR_CSP_HEADER_NAME: "Content-Security-Policy"` literal. +- `ALTAIR_CSP_HEADER_VALUE: string` — the eight-directive policy. + +## Implementation Notes + +The CSP value is assembled as a constant string at module init — there +are no parameters today (a nonce'd variant would land here if the +shell template were converted off inline `