@antasphere/chassis-server 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +82 -0
- package/dist/accounts/deletion.d.ts +163 -0
- package/dist/accounts/deletion.d.ts.map +1 -0
- package/dist/accounts/deletion.js +360 -0
- package/dist/accounts/deletion.js.map +1 -0
- package/dist/accounts/erasure-log.d.ts +66 -0
- package/dist/accounts/erasure-log.d.ts.map +1 -0
- package/dist/accounts/erasure-log.js +117 -0
- package/dist/accounts/erasure-log.js.map +1 -0
- package/dist/accounts/index.d.ts +6 -0
- package/dist/accounts/index.d.ts.map +1 -0
- package/dist/accounts/index.js +6 -0
- package/dist/accounts/index.js.map +1 -0
- package/dist/accounts/mint-refusal.d.ts +47 -0
- package/dist/accounts/mint-refusal.d.ts.map +1 -0
- package/dist/accounts/mint-refusal.js +59 -0
- package/dist/accounts/mint-refusal.js.map +1 -0
- package/dist/accounts/signup-duplicate.d.ts +14 -0
- package/dist/accounts/signup-duplicate.d.ts.map +1 -0
- package/dist/accounts/signup-duplicate.js +25 -0
- package/dist/accounts/signup-duplicate.js.map +1 -0
- package/dist/accounts/superadmin.d.ts +27 -0
- package/dist/accounts/superadmin.d.ts.map +1 -0
- package/dist/accounts/superadmin.js +46 -0
- package/dist/accounts/superadmin.js.map +1 -0
- package/dist/api/apikeys.d.ts +14 -0
- package/dist/api/apikeys.d.ts.map +1 -0
- package/dist/api/apikeys.js +124 -0
- package/dist/api/apikeys.js.map +1 -0
- package/dist/api/audit.d.ts +4 -0
- package/dist/api/audit.d.ts.map +1 -0
- package/dist/api/audit.js +75 -0
- package/dist/api/audit.js.map +1 -0
- package/dist/api/break-glass.d.ts +48 -0
- package/dist/api/break-glass.d.ts.map +1 -0
- package/dist/api/break-glass.js +217 -0
- package/dist/api/break-glass.js.map +1 -0
- package/dist/api/cli-auth.d.ts +84 -0
- package/dist/api/cli-auth.d.ts.map +1 -0
- package/dist/api/cli-auth.js +177 -0
- package/dist/api/cli-auth.js.map +1 -0
- package/dist/api/create-api.d.ts +123 -0
- package/dist/api/create-api.d.ts.map +1 -0
- package/dist/api/create-api.js +1165 -0
- package/dist/api/create-api.js.map +1 -0
- package/dist/api/demo-passes.d.ts +45 -0
- package/dist/api/demo-passes.d.ts.map +1 -0
- package/dist/api/demo-passes.js +143 -0
- package/dist/api/demo-passes.js.map +1 -0
- package/dist/api/errors.d.ts +5 -0
- package/dist/api/errors.d.ts.map +1 -0
- package/dist/api/errors.js +5 -0
- package/dist/api/errors.js.map +1 -0
- package/dist/api/export.d.ts +63 -0
- package/dist/api/export.d.ts.map +1 -0
- package/dist/api/export.js +393 -0
- package/dist/api/export.js.map +1 -0
- package/dist/api/files.d.ts +40 -0
- package/dist/api/files.d.ts.map +1 -0
- package/dist/api/files.js +150 -0
- package/dist/api/files.js.map +1 -0
- package/dist/api/index.d.ts +17 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +17 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/invitations.d.ts +50 -0
- package/dist/api/invitations.d.ts.map +1 -0
- package/dist/api/invitations.js +313 -0
- package/dist/api/invitations.js.map +1 -0
- package/dist/api/members.d.ts +25 -0
- package/dist/api/members.d.ts.map +1 -0
- package/dist/api/members.js +522 -0
- package/dist/api/members.js.map +1 -0
- package/dist/api/onboarding.d.ts +26 -0
- package/dist/api/onboarding.d.ts.map +1 -0
- package/dist/api/onboarding.js +23 -0
- package/dist/api/onboarding.js.map +1 -0
- package/dist/api/openapi-doc.d.ts +21 -0
- package/dist/api/openapi-doc.d.ts.map +1 -0
- package/dist/api/openapi-doc.js +25 -0
- package/dist/api/openapi-doc.js.map +1 -0
- package/dist/api/projects.d.ts +24 -0
- package/dist/api/projects.d.ts.map +1 -0
- package/dist/api/projects.js +624 -0
- package/dist/api/projects.js.map +1 -0
- package/dist/api/scope-routes.d.ts +12 -0
- package/dist/api/scope-routes.d.ts.map +1 -0
- package/dist/api/scope-routes.js +2 -0
- package/dist/api/scope-routes.js.map +1 -0
- package/dist/api/sso-connect.d.ts +70 -0
- package/dist/api/sso-connect.d.ts.map +1 -0
- package/dist/api/sso-connect.js +164 -0
- package/dist/api/sso-connect.js.map +1 -0
- package/dist/api/sso-logout.d.ts +41 -0
- package/dist/api/sso-logout.d.ts.map +1 -0
- package/dist/api/sso-logout.js +34 -0
- package/dist/api/sso-logout.js.map +1 -0
- package/dist/api/teams.d.ts +43 -0
- package/dist/api/teams.d.ts.map +1 -0
- package/dist/api/teams.js +447 -0
- package/dist/api/teams.js.map +1 -0
- package/dist/api/workspaces.d.ts +114 -0
- package/dist/api/workspaces.d.ts.map +1 -0
- package/dist/api/workspaces.js +462 -0
- package/dist/api/workspaces.js.map +1 -0
- package/dist/apikeys/index.d.ts +3 -0
- package/dist/apikeys/index.d.ts.map +1 -0
- package/dist/apikeys/index.js +3 -0
- package/dist/apikeys/index.js.map +1 -0
- package/dist/apikeys/peppers.d.ts +53 -0
- package/dist/apikeys/peppers.d.ts.map +1 -0
- package/dist/apikeys/peppers.js +97 -0
- package/dist/apikeys/peppers.js.map +1 -0
- package/dist/apikeys/service.d.ts +56 -0
- package/dist/apikeys/service.d.ts.map +1 -0
- package/dist/apikeys/service.js +196 -0
- package/dist/apikeys/service.js.map +1 -0
- package/dist/app.d.ts +65 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +142 -0
- package/dist/app.js.map +1 -0
- package/dist/audit/filters.d.ts +38 -0
- package/dist/audit/filters.d.ts.map +1 -0
- package/dist/audit/filters.js +97 -0
- package/dist/audit/filters.js.map +1 -0
- package/dist/audit/index.d.ts +3 -0
- package/dist/audit/index.d.ts.map +1 -0
- package/dist/audit/index.js +3 -0
- package/dist/audit/index.js.map +1 -0
- package/dist/audit/service.d.ts +65 -0
- package/dist/audit/service.d.ts.map +1 -0
- package/dist/audit/service.js +103 -0
- package/dist/audit/service.js.map +1 -0
- package/dist/boot.d.ts +8 -0
- package/dist/boot.d.ts.map +1 -0
- package/dist/boot.js +822 -0
- package/dist/boot.js.map +1 -0
- package/dist/constant-time.d.ts +3 -0
- package/dist/constant-time.d.ts.map +1 -0
- package/dist/constant-time.js +10 -0
- package/dist/constant-time.js.map +1 -0
- package/dist/email/driver.d.ts +16 -0
- package/dist/email/driver.d.ts.map +1 -0
- package/dist/email/driver.js +136 -0
- package/dist/email/driver.js.map +1 -0
- package/dist/email/index.d.ts +4 -0
- package/dist/email/index.d.ts.map +1 -0
- package/dist/email/index.js +4 -0
- package/dist/email/index.js.map +1 -0
- package/dist/email/shell.d.ts +72 -0
- package/dist/email/shell.d.ts.map +1 -0
- package/dist/email/shell.js +146 -0
- package/dist/email/shell.js.map +1 -0
- package/dist/email/templates.d.ts +83 -0
- package/dist/email/templates.d.ts.map +1 -0
- package/dist/email/templates.js +96 -0
- package/dist/email/templates.js.map +1 -0
- package/dist/entitlements/check.d.ts +140 -0
- package/dist/entitlements/check.d.ts.map +1 -0
- package/dist/entitlements/check.js +276 -0
- package/dist/entitlements/check.js.map +1 -0
- package/dist/entitlements/clock-skew.d.ts +27 -0
- package/dist/entitlements/clock-skew.d.ts.map +1 -0
- package/dist/entitlements/clock-skew.js +58 -0
- package/dist/entitlements/clock-skew.js.map +1 -0
- package/dist/entitlements/gate.d.ts +113 -0
- package/dist/entitlements/gate.d.ts.map +1 -0
- package/dist/entitlements/gate.js +430 -0
- package/dist/entitlements/gate.js.map +1 -0
- package/dist/entitlements/hub-machine-token.d.ts +83 -0
- package/dist/entitlements/hub-machine-token.d.ts.map +1 -0
- package/dist/entitlements/hub-machine-token.js +175 -0
- package/dist/entitlements/hub-machine-token.js.map +1 -0
- package/dist/entitlements/hub-subject.d.ts +32 -0
- package/dist/entitlements/hub-subject.d.ts.map +1 -0
- package/dist/entitlements/hub-subject.js +68 -0
- package/dist/entitlements/hub-subject.js.map +1 -0
- package/dist/entitlements/index.d.ts +9 -0
- package/dist/entitlements/index.d.ts.map +1 -0
- package/dist/entitlements/index.js +9 -0
- package/dist/entitlements/index.js.map +1 -0
- package/dist/entitlements/poster.d.ts +81 -0
- package/dist/entitlements/poster.d.ts.map +1 -0
- package/dist/entitlements/poster.js +169 -0
- package/dist/entitlements/poster.js.map +1 -0
- package/dist/entitlements/profiles.d.ts +121 -0
- package/dist/entitlements/profiles.d.ts.map +1 -0
- package/dist/entitlements/profiles.js +212 -0
- package/dist/entitlements/profiles.js.map +1 -0
- package/dist/entitlements/slot.d.ts +33 -0
- package/dist/entitlements/slot.d.ts.map +1 -0
- package/dist/entitlements/slot.js +75 -0
- package/dist/entitlements/slot.js.map +1 -0
- package/dist/env.d.ts +293 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +383 -0
- package/dist/env.js.map +1 -0
- package/dist/files/http.d.ts +23 -0
- package/dist/files/http.d.ts.map +1 -0
- package/dist/files/http.js +66 -0
- package/dist/files/http.js.map +1 -0
- package/dist/files/index.d.ts +5 -0
- package/dist/files/index.d.ts.map +1 -0
- package/dist/files/index.js +5 -0
- package/dist/files/index.js.map +1 -0
- package/dist/files/serve.d.ts +43 -0
- package/dist/files/serve.d.ts.map +1 -0
- package/dist/files/serve.js +71 -0
- package/dist/files/serve.js.map +1 -0
- package/dist/files/service.d.ts +69 -0
- package/dist/files/service.d.ts.map +1 -0
- package/dist/files/service.js +188 -0
- package/dist/files/service.js.map +1 -0
- package/dist/files/spool.d.ts +21 -0
- package/dist/files/spool.d.ts.map +1 -0
- package/dist/files/spool.js +47 -0
- package/dist/files/spool.js.map +1 -0
- package/dist/identity/better-auth.d.ts +3927 -0
- package/dist/identity/better-auth.d.ts.map +1 -0
- package/dist/identity/better-auth.js +896 -0
- package/dist/identity/better-auth.js.map +1 -0
- package/dist/identity/demo-pass-plugin.d.ts +29 -0
- package/dist/identity/demo-pass-plugin.d.ts.map +1 -0
- package/dist/identity/demo-pass-plugin.js +88 -0
- package/dist/identity/demo-pass-plugin.js.map +1 -0
- package/dist/identity/demo-pass-rules.d.ts +84 -0
- package/dist/identity/demo-pass-rules.d.ts.map +1 -0
- package/dist/identity/demo-pass-rules.js +223 -0
- package/dist/identity/demo-pass-rules.js.map +1 -0
- package/dist/identity/demo-pass.d.ts +159 -0
- package/dist/identity/demo-pass.d.ts.map +1 -0
- package/dist/identity/demo-pass.js +319 -0
- package/dist/identity/demo-pass.js.map +1 -0
- package/dist/identity/hub-grant.d.ts +182 -0
- package/dist/identity/hub-grant.d.ts.map +1 -0
- package/dist/identity/hub-grant.js +594 -0
- package/dist/identity/hub-grant.js.map +1 -0
- package/dist/identity/hub-jwt.d.ts +22 -0
- package/dist/identity/hub-jwt.d.ts.map +1 -0
- package/dist/identity/hub-jwt.js +77 -0
- package/dist/identity/hub-jwt.js.map +1 -0
- package/dist/identity/hub-live-gate.d.ts +17 -0
- package/dist/identity/hub-live-gate.d.ts.map +1 -0
- package/dist/identity/hub-live-gate.js +146 -0
- package/dist/identity/hub-live-gate.js.map +1 -0
- package/dist/identity/hub-logout.d.ts +88 -0
- package/dist/identity/hub-logout.d.ts.map +1 -0
- package/dist/identity/hub-logout.js +158 -0
- package/dist/identity/hub-logout.js.map +1 -0
- package/dist/identity/hub-projection.d.ts +103 -0
- package/dist/identity/hub-projection.d.ts.map +1 -0
- package/dist/identity/hub-projection.js +130 -0
- package/dist/identity/hub-projection.js.map +1 -0
- package/dist/identity/hub-reconcile.d.ts +151 -0
- package/dist/identity/hub-reconcile.d.ts.map +1 -0
- package/dist/identity/hub-reconcile.js +400 -0
- package/dist/identity/hub-reconcile.js.map +1 -0
- package/dist/identity/hub-sso.d.ts +363 -0
- package/dist/identity/hub-sso.d.ts.map +1 -0
- package/dist/identity/hub-sso.js +536 -0
- package/dist/identity/hub-sso.js.map +1 -0
- package/dist/identity/hub-user-client.d.ts +222 -0
- package/dist/identity/hub-user-client.d.ts.map +1 -0
- package/dist/identity/hub-user-client.js +406 -0
- package/dist/identity/hub-user-client.js.map +1 -0
- package/dist/identity/index.d.ts +13 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/index.js +13 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/identity/oauth-jwt.d.ts +32 -0
- package/dist/identity/oauth-jwt.d.ts.map +1 -0
- package/dist/identity/oauth-jwt.js +122 -0
- package/dist/identity/oauth-jwt.js.map +1 -0
- package/dist/identity/resolve-membership.d.ts +28 -0
- package/dist/identity/resolve-membership.d.ts.map +1 -0
- package/dist/identity/resolve-membership.js +69 -0
- package/dist/identity/resolve-membership.js.map +1 -0
- package/dist/identity/signing-key.d.ts +49 -0
- package/dist/identity/signing-key.d.ts.map +1 -0
- package/dist/identity/signing-key.js +144 -0
- package/dist/identity/signing-key.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/invitations/index.d.ts +2 -0
- package/dist/invitations/index.d.ts.map +1 -0
- package/dist/invitations/index.js +2 -0
- package/dist/invitations/index.js.map +1 -0
- package/dist/invitations/service.d.ts +36 -0
- package/dist/invitations/service.d.ts.map +1 -0
- package/dist/invitations/service.js +122 -0
- package/dist/invitations/service.js.map +1 -0
- package/dist/jobs/index.d.ts +3 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js +3 -0
- package/dist/jobs/index.js.map +1 -0
- package/dist/jobs/pgboss.d.ts +119 -0
- package/dist/jobs/pgboss.d.ts.map +1 -0
- package/dist/jobs/pgboss.js +521 -0
- package/dist/jobs/pgboss.js.map +1 -0
- package/dist/jobs/timers.d.ts +127 -0
- package/dist/jobs/timers.d.ts.map +1 -0
- package/dist/jobs/timers.js +228 -0
- package/dist/jobs/timers.js.map +1 -0
- package/dist/logger.d.ts +17 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +64 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp/errors.d.ts +37 -0
- package/dist/mcp/errors.d.ts.map +1 -0
- package/dist/mcp/errors.js +77 -0
- package/dist/mcp/errors.js.map +1 -0
- package/dist/mcp/http.d.ts +35 -0
- package/dist/mcp/http.d.ts.map +1 -0
- package/dist/mcp/http.js +80 -0
- package/dist/mcp/http.js.map +1 -0
- package/dist/mcp/index.d.ts +8 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +8 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/inputs.d.ts +19 -0
- package/dist/mcp/inputs.d.ts.map +1 -0
- package/dist/mcp/inputs.js +28 -0
- package/dist/mcp/inputs.js.map +1 -0
- package/dist/mcp/projects.d.ts +31 -0
- package/dist/mcp/projects.d.ts.map +1 -0
- package/dist/mcp/projects.js +315 -0
- package/dist/mcp/projects.js.map +1 -0
- package/dist/mcp/server.d.ts +52 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +93 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/teams.d.ts +7 -0
- package/dist/mcp/teams.d.ts.map +1 -0
- package/dist/mcp/teams.js +62 -0
- package/dist/mcp/teams.js.map +1 -0
- package/dist/mcp/tool-kit.d.ts +67 -0
- package/dist/mcp/tool-kit.d.ts.map +1 -0
- package/dist/mcp/tool-kit.js +74 -0
- package/dist/mcp/tool-kit.js.map +1 -0
- package/dist/members/removal.d.ts +95 -0
- package/dist/members/removal.d.ts.map +1 -0
- package/dist/members/removal.js +143 -0
- package/dist/members/removal.js.map +1 -0
- package/dist/middleware/auth-body.d.ts +25 -0
- package/dist/middleware/auth-body.d.ts.map +1 -0
- package/dist/middleware/auth-body.js +55 -0
- package/dist/middleware/auth-body.js.map +1 -0
- package/dist/middleware/auth-context.d.ts +170 -0
- package/dist/middleware/auth-context.d.ts.map +1 -0
- package/dist/middleware/auth-context.js +251 -0
- package/dist/middleware/auth-context.js.map +1 -0
- package/dist/middleware/body-cap.d.ts +17 -0
- package/dist/middleware/body-cap.d.ts.map +1 -0
- package/dist/middleware/body-cap.js +31 -0
- package/dist/middleware/body-cap.js.map +1 -0
- package/dist/middleware/body-refusal.d.ts +20 -0
- package/dist/middleware/body-refusal.d.ts.map +1 -0
- package/dist/middleware/body-refusal.js +5 -0
- package/dist/middleware/body-refusal.js.map +1 -0
- package/dist/middleware/cross-site.d.ts +61 -0
- package/dist/middleware/cross-site.d.ts.map +1 -0
- package/dist/middleware/cross-site.js +59 -0
- package/dist/middleware/cross-site.js.map +1 -0
- package/dist/middleware/hub-managed.d.ts +45 -0
- package/dist/middleware/hub-managed.d.ts.map +1 -0
- package/dist/middleware/hub-managed.js +56 -0
- package/dist/middleware/hub-managed.js.map +1 -0
- package/dist/middleware/idempotency.d.ts +14 -0
- package/dist/middleware/idempotency.d.ts.map +1 -0
- package/dist/middleware/idempotency.js +222 -0
- package/dist/middleware/idempotency.js.map +1 -0
- package/dist/middleware/index.d.ts +12 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +12 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/json-depth.d.ts +32 -0
- package/dist/middleware/json-depth.d.ts.map +1 -0
- package/dist/middleware/json-depth.js +80 -0
- package/dist/middleware/json-depth.js.map +1 -0
- package/dist/middleware/no-store.d.ts +21 -0
- package/dist/middleware/no-store.d.ts.map +1 -0
- package/dist/middleware/no-store.js +32 -0
- package/dist/middleware/no-store.js.map +1 -0
- package/dist/middleware/oauth-public.d.ts +16 -0
- package/dist/middleware/oauth-public.d.ts.map +1 -0
- package/dist/middleware/oauth-public.js +50 -0
- package/dist/middleware/oauth-public.js.map +1 -0
- package/dist/middleware/rate-limit.d.ts +182 -0
- package/dist/middleware/rate-limit.d.ts.map +1 -0
- package/dist/middleware/rate-limit.js +277 -0
- package/dist/middleware/rate-limit.js.map +1 -0
- package/dist/middleware/request-id.d.ts +10 -0
- package/dist/middleware/request-id.d.ts.map +1 -0
- package/dist/middleware/request-id.js +42 -0
- package/dist/middleware/request-id.js.map +1 -0
- package/dist/middleware/scopes.d.ts +33 -0
- package/dist/middleware/scopes.d.ts.map +1 -0
- package/dist/middleware/scopes.js +139 -0
- package/dist/middleware/scopes.js.map +1 -0
- package/dist/middleware/security-headers.d.ts +53 -0
- package/dist/middleware/security-headers.d.ts.map +1 -0
- package/dist/middleware/security-headers.js +96 -0
- package/dist/middleware/security-headers.js.map +1 -0
- package/dist/observability/index.d.ts +3 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +3 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/metrics.d.ts +17 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/metrics.js +82 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/observability/otel.d.ts +20 -0
- package/dist/observability/otel.d.ts.map +1 -0
- package/dist/observability/otel.js +54 -0
- package/dist/observability/otel.js.map +1 -0
- package/dist/pagination.d.ts +57 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +90 -0
- package/dist/pagination.js.map +1 -0
- package/dist/platform/edition.d.ts +57 -0
- package/dist/platform/edition.d.ts.map +1 -0
- package/dist/platform/edition.js +90 -0
- package/dist/platform/edition.js.map +1 -0
- package/dist/platform/entitlements.d.ts +26 -0
- package/dist/platform/entitlements.d.ts.map +1 -0
- package/dist/platform/entitlements.js +28 -0
- package/dist/platform/entitlements.js.map +1 -0
- package/dist/platform/events.d.ts +87 -0
- package/dist/platform/events.d.ts.map +1 -0
- package/dist/platform/events.js +32 -0
- package/dist/platform/events.js.map +1 -0
- package/dist/platform/index.d.ts +8 -0
- package/dist/platform/index.d.ts.map +1 -0
- package/dist/platform/index.js +8 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/local-identity.d.ts +39 -0
- package/dist/platform/local-identity.d.ts.map +1 -0
- package/dist/platform/local-identity.js +87 -0
- package/dist/platform/local-identity.js.map +1 -0
- package/dist/platform/registry.d.ts +23 -0
- package/dist/platform/registry.d.ts.map +1 -0
- package/dist/platform/registry.js +5 -0
- package/dist/platform/registry.js.map +1 -0
- package/dist/platform/usage.d.ts +11 -0
- package/dist/platform/usage.d.ts.map +1 -0
- package/dist/platform/usage.js +12 -0
- package/dist/platform/usage.js.map +1 -0
- package/dist/platform/workspaces.d.ts +25 -0
- package/dist/platform/workspaces.d.ts.map +1 -0
- package/dist/platform/workspaces.js +44 -0
- package/dist/platform/workspaces.js.map +1 -0
- package/dist/projects/access.d.ts +40 -0
- package/dist/projects/access.d.ts.map +1 -0
- package/dist/projects/access.js +133 -0
- package/dist/projects/access.js.map +1 -0
- package/dist/projects/index.d.ts +2 -0
- package/dist/projects/index.d.ts.map +1 -0
- package/dist/projects/index.js +2 -0
- package/dist/projects/index.js.map +1 -0
- package/dist/route-label.d.ts +23 -0
- package/dist/route-label.d.ts.map +1 -0
- package/dist/route-label.js +29 -0
- package/dist/route-label.js.map +1 -0
- package/dist/routes/health.d.ts +30 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +54 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/index.d.ts +3 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +3 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/wellknown.d.ts +11 -0
- package/dist/routes/wellknown.d.ts.map +1 -0
- package/dist/routes/wellknown.js +45 -0
- package/dist/routes/wellknown.js.map +1 -0
- package/dist/secret.d.ts +30 -0
- package/dist/secret.d.ts.map +1 -0
- package/dist/secret.js +97 -0
- package/dist/secret.js.map +1 -0
- package/dist/setup-transport.d.ts +23 -0
- package/dist/setup-transport.d.ts.map +1 -0
- package/dist/setup-transport.js +52 -0
- package/dist/setup-transport.js.map +1 -0
- package/dist/state.d.ts +21 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +4 -0
- package/dist/state.js.map +1 -0
- package/dist/storage/driver.d.ts +38 -0
- package/dist/storage/driver.d.ts.map +1 -0
- package/dist/storage/driver.js +14 -0
- package/dist/storage/driver.js.map +1 -0
- package/dist/storage/factory.d.ts +4 -0
- package/dist/storage/factory.d.ts.map +1 -0
- package/dist/storage/factory.js +20 -0
- package/dist/storage/factory.js.map +1 -0
- package/dist/storage/index.d.ts +4 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +4 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/local.d.ts +21 -0
- package/dist/storage/local.d.ts.map +1 -0
- package/dist/storage/local.js +88 -0
- package/dist/storage/local.js.map +1 -0
- package/dist/storage/s3.d.ts +29 -0
- package/dist/storage/s3.d.ts.map +1 -0
- package/dist/storage/s3.js +82 -0
- package/dist/storage/s3.js.map +1 -0
- package/dist/testing/fake-hub.d.ts +425 -0
- package/dist/testing/fake-hub.d.ts.map +1 -0
- package/dist/testing/fake-hub.js +1074 -0
- package/dist/testing/fake-hub.js.map +1 -0
- package/dist/testing/helpers.d.ts +124 -0
- package/dist/testing/helpers.d.ts.map +1 -0
- package/dist/testing/helpers.js +174 -0
- package/dist/testing/helpers.js.map +1 -0
- package/dist/testing/index.d.ts +12 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +12 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/setup-origins.d.ts +21 -0
- package/dist/testing/setup-origins.d.ts.map +1 -0
- package/dist/testing/setup-origins.js +57 -0
- package/dist/testing/setup-origins.js.map +1 -0
- package/dist/testing/sso-helpers.d.ts +43 -0
- package/dist/testing/sso-helpers.d.ts.map +1 -0
- package/dist/testing/sso-helpers.js +159 -0
- package/dist/testing/sso-helpers.js.map +1 -0
- package/dist/tool-definition.d.ts +382 -0
- package/dist/tool-definition.d.ts.map +1 -0
- package/dist/tool-definition.js +46 -0
- package/dist/tool-definition.js.map +1 -0
- package/dist/util/index.d.ts +8 -0
- package/dist/util/index.d.ts.map +1 -0
- package/dist/util/index.js +8 -0
- package/dist/util/index.js.map +1 -0
- package/package.json +161 -0
- package/src/accounts/deletion.ts +389 -0
- package/src/accounts/erasure-log.ts +140 -0
- package/src/accounts/index.ts +5 -0
- package/src/accounts/mint-refusal.ts +67 -0
- package/src/accounts/signup-duplicate.ts +21 -0
- package/src/accounts/superadmin.ts +46 -0
- package/src/api/apikeys.ts +147 -0
- package/src/api/audit.ts +83 -0
- package/src/api/break-glass.ts +294 -0
- package/src/api/cli-auth.ts +308 -0
- package/src/api/create-api.ts +1403 -0
- package/src/api/demo-passes.ts +207 -0
- package/src/api/errors.ts +13 -0
- package/src/api/export.ts +482 -0
- package/src/api/files.ts +200 -0
- package/src/api/index.ts +29 -0
- package/src/api/invitations.ts +396 -0
- package/src/api/members.ts +617 -0
- package/src/api/onboarding.ts +50 -0
- package/src/api/openapi-doc.ts +34 -0
- package/src/api/projects.ts +788 -0
- package/src/api/scope-routes.ts +12 -0
- package/src/api/sso-connect.ts +246 -0
- package/src/api/sso-logout.ts +76 -0
- package/src/api/teams.ts +575 -0
- package/src/api/workspaces.ts +649 -0
- package/src/apikeys/index.ts +2 -0
- package/src/apikeys/peppers.ts +118 -0
- package/src/apikeys/service.ts +223 -0
- package/src/app.ts +228 -0
- package/src/audit/filters.ts +101 -0
- package/src/audit/index.ts +9 -0
- package/src/audit/service.ts +154 -0
- package/src/boot.ts +953 -0
- package/src/constant-time.ts +9 -0
- package/src/email/driver.ts +139 -0
- package/src/email/index.ts +26 -0
- package/src/email/shell.ts +201 -0
- package/src/email/templates.ts +184 -0
- package/src/entitlements/check.ts +435 -0
- package/src/entitlements/clock-skew.ts +58 -0
- package/src/entitlements/gate.ts +636 -0
- package/src/entitlements/hub-machine-token.ts +205 -0
- package/src/entitlements/hub-subject.ts +77 -0
- package/src/entitlements/index.ts +37 -0
- package/src/entitlements/poster.ts +265 -0
- package/src/entitlements/profiles.ts +303 -0
- package/src/entitlements/slot.ts +105 -0
- package/src/env.ts +456 -0
- package/src/files/http.ts +77 -0
- package/src/files/index.ts +4 -0
- package/src/files/serve.ts +115 -0
- package/src/files/service.ts +209 -0
- package/src/files/spool.ts +58 -0
- package/src/identity/better-auth.ts +1103 -0
- package/src/identity/demo-pass-plugin.ts +121 -0
- package/src/identity/demo-pass-rules.ts +229 -0
- package/src/identity/demo-pass.ts +390 -0
- package/src/identity/hub-grant.ts +704 -0
- package/src/identity/hub-jwt.ts +78 -0
- package/src/identity/hub-live-gate.ts +167 -0
- package/src/identity/hub-logout.ts +174 -0
- package/src/identity/hub-projection.ts +251 -0
- package/src/identity/hub-reconcile.ts +572 -0
- package/src/identity/hub-sso.ts +696 -0
- package/src/identity/hub-user-client.ts +554 -0
- package/src/identity/index.ts +56 -0
- package/src/identity/oauth-jwt.ts +128 -0
- package/src/identity/resolve-membership.ts +104 -0
- package/src/identity/signing-key.ts +164 -0
- package/src/index.ts +65 -0
- package/src/invitations/index.ts +1 -0
- package/src/invitations/service.ts +171 -0
- package/src/jobs/index.ts +25 -0
- package/src/jobs/pgboss.ts +594 -0
- package/src/jobs/timers.ts +287 -0
- package/src/logger.ts +67 -0
- package/src/mcp/errors.ts +111 -0
- package/src/mcp/http.ts +129 -0
- package/src/mcp/index.ts +28 -0
- package/src/mcp/inputs.ts +33 -0
- package/src/mcp/projects.ts +480 -0
- package/src/mcp/server.ts +174 -0
- package/src/mcp/teams.ts +97 -0
- package/src/mcp/tool-kit.ts +148 -0
- package/src/members/removal.ts +216 -0
- package/src/middleware/auth-body.ts +58 -0
- package/src/middleware/auth-context.ts +384 -0
- package/src/middleware/body-cap.ts +33 -0
- package/src/middleware/body-refusal.ts +23 -0
- package/src/middleware/cross-site.ts +122 -0
- package/src/middleware/hub-managed.ts +61 -0
- package/src/middleware/idempotency.ts +264 -0
- package/src/middleware/index.ts +33 -0
- package/src/middleware/json-depth.ts +74 -0
- package/src/middleware/no-store.ts +30 -0
- package/src/middleware/oauth-public.ts +54 -0
- package/src/middleware/rate-limit.ts +432 -0
- package/src/middleware/request-id.ts +54 -0
- package/src/middleware/scopes.ts +150 -0
- package/src/middleware/security-headers.ts +129 -0
- package/src/observability/index.ts +2 -0
- package/src/observability/metrics.ts +102 -0
- package/src/observability/otel.ts +79 -0
- package/src/pagination.ts +118 -0
- package/src/platform/edition.ts +140 -0
- package/src/platform/entitlements.ts +47 -0
- package/src/platform/events.ts +71 -0
- package/src/platform/index.ts +7 -0
- package/src/platform/local-identity.ts +90 -0
- package/src/platform/registry.ts +28 -0
- package/src/platform/usage.ts +13 -0
- package/src/platform/workspaces.ts +41 -0
- package/src/projects/access.ts +160 -0
- package/src/projects/index.ts +7 -0
- package/src/route-label.ts +29 -0
- package/src/routes/health.ts +79 -0
- package/src/routes/index.ts +2 -0
- package/src/routes/wellknown.ts +67 -0
- package/src/secret.ts +115 -0
- package/src/setup-transport.ts +46 -0
- package/src/state.ts +23 -0
- package/src/storage/driver.ts +48 -0
- package/src/storage/factory.ts +34 -0
- package/src/storage/index.ts +3 -0
- package/src/storage/local.ts +93 -0
- package/src/storage/s3.ts +109 -0
- package/src/testing/fake-hub.ts +1316 -0
- package/src/testing/helpers.ts +254 -0
- package/src/testing/index.ts +11 -0
- package/src/testing/setup-origins.ts +58 -0
- package/src/testing/sso-helpers.ts +178 -0
- package/src/tool-definition.ts +463 -0
- package/src/util/index.ts +17 -0
- package/test/fixtures/onboarding-backfill.sql +13 -0
- package/test/fixtures/operator-user-id-backfill.sql +18 -0
- package/test/host/dr-lib.sh +253 -0
- package/test/host/drizzle/0000_chassis_baseline.sql +438 -0
- package/test/host/drizzle/0001_last_owner_guard.sql +42 -0
- package/test/host/drizzle/meta/0000_snapshot.json +3566 -0
- package/test/host/drizzle/meta/_journal.json +20 -0
- package/test/host/drizzle.config.ts +17 -0
- package/test/host/identity.ts +41 -0
- package/test/host/minimal-host.ts +35 -0
- package/test/host/minimal-tool.ts +123 -0
- package/test/integration/account-oracle-uniformity.test.ts +284 -0
- package/test/integration/account-recovery.test.ts +236 -0
- package/test/integration/account.test.ts +120 -0
- package/test/integration/api-quota.test.ts +208 -0
- package/test/integration/apikey-expiry.test.ts +178 -0
- package/test/integration/apikey-pepper-rotation.test.ts +190 -0
- package/test/integration/boot-posture.test.ts +169 -0
- package/test/integration/break-glass.test.ts +484 -0
- package/test/integration/cloud-lifecycle.test.ts +233 -0
- package/test/integration/credential-boundaries.test.ts +195 -0
- package/test/integration/default-workspace.test.ts +414 -0
- package/test/integration/demo-pass-rules.test.ts +332 -0
- package/test/integration/demo-pass.test.ts +1222 -0
- package/test/integration/dr-verify-real-dump.test.ts +154 -0
- package/test/integration/edition.test.ts +868 -0
- package/test/integration/email-change.test.ts +394 -0
- package/test/integration/empty-tool.test.ts +267 -0
- package/test/integration/entitlements-null-hook.test.ts +187 -0
- package/test/integration/entitlements.test.ts +693 -0
- package/test/integration/export-entries.test.ts +321 -0
- package/test/integration/files.test.ts +320 -0
- package/test/integration/first-boot-claim.test.ts +131 -0
- package/test/integration/gdpr.test.ts +532 -0
- package/test/integration/helpers.ts +29 -0
- package/test/integration/hub-grant.test.ts +505 -0
- package/test/integration/hub-live-gate.test.ts +612 -0
- package/test/integration/hub-managed-membership.test.ts +559 -0
- package/test/integration/hub-org-selector.test.ts +281 -0
- package/test/integration/hub-reconcile.test.ts +646 -0
- package/test/integration/hub-sso.test.ts +704 -0
- package/test/integration/hub-teams.test.ts +771 -0
- package/test/integration/idempotency.test.ts +261 -0
- package/test/integration/invite-verification.test.ts +210 -0
- package/test/integration/last-owner-race.test.ts +263 -0
- package/test/integration/m9-fixes.test.ts +290 -0
- package/test/integration/mcp-projects.test.ts +463 -0
- package/test/integration/member-removal-race.test.ts +466 -0
- package/test/integration/member-removal.test.ts +794 -0
- package/test/integration/oauth-mcp.test.ts +477 -0
- package/test/integration/oauth-workspace.test.ts +371 -0
- package/test/integration/observability.test.ts +183 -0
- package/test/integration/onboarding.test.ts +268 -0
- package/test/integration/orphan-purge.test.ts +451 -0
- package/test/integration/pagination.test.ts +344 -0
- package/test/integration/platform-core.test.ts +305 -0
- package/test/integration/platform.test.ts +246 -0
- package/test/integration/pool-survives-restart.test.ts +80 -0
- package/test/integration/projects-cloud.test.ts +193 -0
- package/test/integration/projects.test.ts +1310 -0
- package/test/integration/security-fixes.test.ts +190 -0
- package/test/integration/setup-transport.test.ts +118 -0
- package/test/integration/signin-wall.test.ts +103 -0
- package/test/integration/signing-key-rotation.test.ts +349 -0
- package/test/integration/sso-helpers.ts +15 -0
- package/test/integration/sso-logout.test.ts +283 -0
- package/test/integration/teams-cloud.test.ts +194 -0
- package/test/integration/teams.test.ts +551 -0
- package/test/integration/timers.test.ts +377 -0
- package/test/integration/two-factor.test.ts +301 -0
- package/test/integration/usage-window.test.ts +161 -0
- package/test/integration/workspace-create-cloud.test.ts +523 -0
- package/test/integration/workspace-create.test.ts +510 -0
- package/test/integration/workspace-scoping.test.ts +530 -0
- package/test/integration/zz-adv-replay-owner.test.ts +205 -0
- package/test/unit/apikey-peppers.test.ts +110 -0
- package/test/unit/apikey-prefix.test.ts +34 -0
- package/test/unit/audit-filters.test.ts +135 -0
- package/test/unit/auth-origins.test.ts +92 -0
- package/test/unit/body-cap.test.ts +84 -0
- package/test/unit/clock-skew.test.ts +68 -0
- package/test/unit/cross-site.test.ts +166 -0
- package/test/unit/declared-credits.test.ts +13 -0
- package/test/unit/demo-pass-rules.test.ts +192 -0
- package/test/unit/email-driver.test.ts +127 -0
- package/test/unit/end-pool.test.ts +181 -0
- package/test/unit/entitlement-check.test.ts +492 -0
- package/test/unit/entitlement-gate.test.ts +1333 -0
- package/test/unit/entitlement-profiles.test.ts +289 -0
- package/test/unit/erasure-log.test.ts +72 -0
- package/test/unit/error-mapping.test.ts +89 -0
- package/test/unit/export-entries.test.ts +85 -0
- package/test/unit/export-sanitize.test.ts +27 -0
- package/test/unit/files-head-route.test.ts +155 -0
- package/test/unit/files-http.test.ts +97 -0
- package/test/unit/head-rewrite.test.ts +72 -0
- package/test/unit/hub-create-org.test.ts +181 -0
- package/test/unit/hub-jwt.test.ts +93 -0
- package/test/unit/hub-sso-params.test.ts +39 -0
- package/test/unit/hub-subject.test.ts +83 -0
- package/test/unit/idempotency-crypto.test.ts +45 -0
- package/test/unit/json-depth.test.ts +88 -0
- package/test/unit/logger-redaction.test.ts +66 -0
- package/test/unit/mcp-errors.test.ts +110 -0
- package/test/unit/mcp-inputs.test.ts +106 -0
- package/test/unit/mcp-project-hints.test.ts +26 -0
- package/test/unit/no-store.test.ts +49 -0
- package/test/unit/no-tool-migration-filename.test.ts +70 -0
- package/test/unit/observability.test.ts +64 -0
- package/test/unit/openapi-doc.test.ts +93 -0
- package/test/unit/rate-limit-consume-on.test.ts +76 -0
- package/test/unit/rate-limit.test.ts +39 -0
- package/test/unit/readyz-storage.test.ts +157 -0
- package/test/unit/request-quota.test.ts +146 -0
- package/test/unit/scopes.test.ts +66 -0
- package/test/unit/security-headers.test.ts +131 -0
- package/test/unit/serve-content-type.test.ts +74 -0
- package/test/unit/setup-transport.test.ts +29 -0
- package/test/unit/storage-local.test.ts +53 -0
- package/test/unit/superadmin.test.ts +32 -0
- package/test/unit/timers.test.ts +287 -0
- package/test/unit/tool-definition-guards.test.ts +166 -0
- package/test/unit/tool-entitlements-guard.test.ts +168 -0
- package/test/unit/usage-poster.test.ts +542 -0
- package/test/unit/usage-window.test.ts +48 -0
- package/test/unit/workspace-create-audit.test.ts +48 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import {
|
|
2
|
+
entitlementProfileSchema,
|
|
3
|
+
type EntitlementProfile,
|
|
4
|
+
type EntitlementTier,
|
|
5
|
+
type ToolEntitlements
|
|
6
|
+
} from '@antasphere/chassis-contract';
|
|
7
|
+
import type { Logger } from '../logger.js';
|
|
8
|
+
import type { HubMachineToken } from './hub-machine-token.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* An account's entitlement profile, resolved: the plan, every declared limit
|
|
12
|
+
* with the value that applies (the hub's override when it sent one, the
|
|
13
|
+
* tool's declared value for the tier otherwise), and the features on.
|
|
14
|
+
*/
|
|
15
|
+
export interface ResolvedProfile {
|
|
16
|
+
plan: EntitlementTier;
|
|
17
|
+
/** null = unlimited (a tier's null, or a hub `true`); 0 = nothing allowed (a hub `false`). */
|
|
18
|
+
limits: Record<string, number | null>;
|
|
19
|
+
features: ReadonlySet<string>;
|
|
20
|
+
/** Where the plan came from: the hub, the last known answer, or the default. */
|
|
21
|
+
source: 'hub' | 'stale' | 'default';
|
|
22
|
+
/**
|
|
23
|
+
* The hub's upgrade page for the organization (`org`, `tool`, `plan` on it),
|
|
24
|
+
* when the hub sent one with the plan served here; null when the plan is
|
|
25
|
+
* the default (never answered, or past the stale window) or the hub is
|
|
26
|
+
* older than phase 2. The gate appends `key` and `requiredPlan`.
|
|
27
|
+
*/
|
|
28
|
+
upgradeUrl: string | null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface EntitlementProfileDials {
|
|
32
|
+
/** How long a hub answer is served without asking again (§7: 30 s per account). */
|
|
33
|
+
ttlMs: number;
|
|
34
|
+
/**
|
|
35
|
+
* How long the LAST KNOWN plan is kept when the hub stops answering, before
|
|
36
|
+
* falling to `free` (the federation gate's own posture on hub_unavailable:
|
|
37
|
+
* 15 minutes). A pro account is not refused above the free cap on every
|
|
38
|
+
* hub blip.
|
|
39
|
+
*/
|
|
40
|
+
staleMs: number;
|
|
41
|
+
/** Hub request budget (the read runs off the request path; this bounds the background fetch). */
|
|
42
|
+
timeoutMs: number;
|
|
43
|
+
/**
|
|
44
|
+
* How long a request waits for the FIRST read of an account nobody asked
|
|
45
|
+
* the hub about yet (PRDCT-2633). A warm cache never waits: a fresh entry
|
|
46
|
+
* is served, a stale one is served while a refresh runs behind it. A cold
|
|
47
|
+
* account waits at most this long, then gets the default (`free`) while the
|
|
48
|
+
* read finishes in the background — so a pro account is judged right on
|
|
49
|
+
* its first request whenever the hub answers in time. Every request for a
|
|
50
|
+
* cold account that arrives while that first read is in flight waits up
|
|
51
|
+
* to this budget too (each against the one flight), bounded overall by
|
|
52
|
+
* `timeoutMs`, after which the miss is cached and served at once.
|
|
53
|
+
*/
|
|
54
|
+
coldWaitMs: number;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const DEFAULT_PROFILE_DIALS: EntitlementProfileDials = {
|
|
58
|
+
ttlMs: 30_000,
|
|
59
|
+
staleMs: 15 * 60_000,
|
|
60
|
+
timeoutMs: 5_000,
|
|
61
|
+
coldWaitMs: 1_500
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export interface EntitlementProfilesOptions {
|
|
65
|
+
issuerUrl: string;
|
|
66
|
+
token: HubMachineToken;
|
|
67
|
+
logger: Logger;
|
|
68
|
+
dials?: Partial<EntitlementProfileDials> | undefined;
|
|
69
|
+
fetchImpl?: typeof fetch | undefined;
|
|
70
|
+
now?: (() => number) | undefined;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface CacheEntry {
|
|
74
|
+
plan: EntitlementTier;
|
|
75
|
+
/** The hub's overrides as sent: a number, or a boolean switch (`true` unlimited, `false` nothing). */
|
|
76
|
+
hubLimits: Record<string, number | boolean>;
|
|
77
|
+
hubFeatures: string[] | null;
|
|
78
|
+
/** The hub's upgrade page for the organization, when it sent one. */
|
|
79
|
+
hubUpgradeUrl: string | null;
|
|
80
|
+
/** When the hub last answered. */
|
|
81
|
+
answeredAtMs: number;
|
|
82
|
+
/** Until when this entry is served without a hub call. */
|
|
83
|
+
freshUntilMs: number;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* The per-account plan on the cloud edition, read from the hub's
|
|
88
|
+
* `GET /usage/entitlements?accountRef=` with the machine token and cached
|
|
89
|
+
* 30 s per account. Resolution against the tool's declared tier values
|
|
90
|
+
* (`resolve`): the hub's rows win over the defaults whenever it sent them.
|
|
91
|
+
*
|
|
92
|
+
* The read is OFF the request path (PRDCT-2633, stale-while-revalidate):
|
|
93
|
+
* a fresh entry is served as it is; an entry past its TTL is served at once
|
|
94
|
+
* and refreshed behind the request, single-flight per account; only an
|
|
95
|
+
* account the cache has never seen waits, and at most `coldWaitMs`. A hub
|
|
96
|
+
* that is slow but alive therefore costs a metered request nothing once the
|
|
97
|
+
* account is known.
|
|
98
|
+
*
|
|
99
|
+
* Failure posture: a hub that does not answer (a 404 from an older hub, a
|
|
100
|
+
* 5xx, a timeout) keeps the last known plan for `staleMs`, then `free`; an
|
|
101
|
+
* account the hub never answered for is `free` from the start. Every failure
|
|
102
|
+
* is cached for `ttlMs` too, so a request storm never becomes a hub storm.
|
|
103
|
+
*/
|
|
104
|
+
export class EntitlementProfiles {
|
|
105
|
+
private readonly url: string;
|
|
106
|
+
private readonly fetchImpl: typeof fetch;
|
|
107
|
+
private readonly now: () => number;
|
|
108
|
+
private readonly dials: EntitlementProfileDials;
|
|
109
|
+
private readonly cache = new Map<string, CacheEntry>();
|
|
110
|
+
private readonly inflight = new Map<string, Promise<void>>();
|
|
111
|
+
/** How many reads reached the hub — a test seam. */
|
|
112
|
+
hubReads = 0;
|
|
113
|
+
|
|
114
|
+
constructor(private readonly opts: EntitlementProfilesOptions) {
|
|
115
|
+
this.url = opts.issuerUrl.replace(/\/+$/, '') + '/api/v1/usage/entitlements';
|
|
116
|
+
this.fetchImpl = opts.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
117
|
+
this.now = opts.now ?? Date.now;
|
|
118
|
+
this.dials = { ...DEFAULT_PROFILE_DIALS, ...opts.dials };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** The account's profile, resolved against what the tool declares. */
|
|
122
|
+
async get(accountRef: string, tool: ToolEntitlements): Promise<ResolvedProfile> {
|
|
123
|
+
const entry = await this.entry(accountRef);
|
|
124
|
+
return resolve(tool, entry, this.now(), this.dials.staleMs);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** Forget every cached answer (a test seam). */
|
|
128
|
+
clear(): void {
|
|
129
|
+
this.cache.clear();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Wait for every background refresh in flight (a test seam). */
|
|
133
|
+
async settle(): Promise<void> {
|
|
134
|
+
await Promise.all([...this.inflight.values()]);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private async entry(accountRef: string): Promise<CacheEntry | null> {
|
|
138
|
+
const cached = this.cache.get(accountRef);
|
|
139
|
+
if (cached && cached.freshUntilMs > this.now()) return cached;
|
|
140
|
+
let flight = this.inflight.get(accountRef);
|
|
141
|
+
if (!flight) {
|
|
142
|
+
flight = this.refresh(accountRef, cached ?? null).finally(() => {
|
|
143
|
+
this.inflight.delete(accountRef);
|
|
144
|
+
});
|
|
145
|
+
this.inflight.set(accountRef, flight);
|
|
146
|
+
}
|
|
147
|
+
// Stale: served now, the refresh runs behind the request.
|
|
148
|
+
if (cached) return cached;
|
|
149
|
+
// Cold: wait for the first read, but never longer than the cold budget.
|
|
150
|
+
await withinBudget(flight, this.dials.coldWaitMs);
|
|
151
|
+
return this.cache.get(accountRef) ?? null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private async refresh(accountRef: string, previous: CacheEntry | null): Promise<void> {
|
|
155
|
+
this.hubReads += 1;
|
|
156
|
+
this.sweep();
|
|
157
|
+
const answered = await this.read(accountRef);
|
|
158
|
+
const now = this.now();
|
|
159
|
+
if (answered) {
|
|
160
|
+
// Which features list is the truth. A hub that answers at least one
|
|
161
|
+
// limit key serves its real rows for this tool (phase 2, PRDCT-2663):
|
|
162
|
+
// its `features` is then authoritative AS IT IS, an empty list
|
|
163
|
+
// included, so a per-account override that switches a feature off is
|
|
164
|
+
// felt. A hub that answers no limit at all is a phase-1 hub (or a tool
|
|
165
|
+
// it has not seeded yet), whose empty lists mean "the tool applies its
|
|
166
|
+
// own tier defaults for the plan named here": there a non-empty list
|
|
167
|
+
// still overrides and an empty one leaves the declared tier values.
|
|
168
|
+
const authoritative = Object.keys(answered.limits).length > 0;
|
|
169
|
+
this.cache.set(accountRef, {
|
|
170
|
+
plan: answered.plan,
|
|
171
|
+
hubLimits: answered.limits,
|
|
172
|
+
hubFeatures: authoritative || answered.features.length > 0 ? answered.features : null,
|
|
173
|
+
hubUpgradeUrl: answered.upgradeUrl ?? null,
|
|
174
|
+
answeredAtMs: now,
|
|
175
|
+
freshUntilMs: now + this.dials.ttlMs
|
|
176
|
+
});
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
// Keep the last answer (its `answeredAtMs` decides staleness), or record
|
|
180
|
+
// a miss so the next request within the TTL does not ask again.
|
|
181
|
+
this.cache.set(
|
|
182
|
+
accountRef,
|
|
183
|
+
previous
|
|
184
|
+
? { ...previous, freshUntilMs: now + this.dials.ttlMs }
|
|
185
|
+
: {
|
|
186
|
+
plan: 'free',
|
|
187
|
+
hubLimits: {},
|
|
188
|
+
hubFeatures: null,
|
|
189
|
+
hubUpgradeUrl: null,
|
|
190
|
+
answeredAtMs: 0,
|
|
191
|
+
freshUntilMs: now + this.dials.ttlMs
|
|
192
|
+
}
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Keep the cache bounded on a long-lived replica: once it holds more than
|
|
198
|
+
* `SWEEP_ABOVE` accounts, drop every entry that is neither fresh nor
|
|
199
|
+
* inside its stale window (nothing would be served from it any more).
|
|
200
|
+
*/
|
|
201
|
+
private sweep(): void {
|
|
202
|
+
if (this.cache.size <= SWEEP_ABOVE) return;
|
|
203
|
+
const now = this.now();
|
|
204
|
+
for (const [key, entry] of this.cache) {
|
|
205
|
+
const servable =
|
|
206
|
+
entry.freshUntilMs > now || (entry.answeredAtMs > 0 && entry.answeredAtMs + this.dials.staleMs > now);
|
|
207
|
+
if (!servable) this.cache.delete(key);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** One hub read; null on any failure (logged, never thrown). */
|
|
212
|
+
private async read(accountRef: string): Promise<EntitlementProfile | null> {
|
|
213
|
+
let token: string;
|
|
214
|
+
try {
|
|
215
|
+
token = await this.opts.token.get();
|
|
216
|
+
} catch (err) {
|
|
217
|
+
this.opts.logger.warn({ err }, 'entitlements: no machine token — the last known plan applies');
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
let res: Response;
|
|
221
|
+
try {
|
|
222
|
+
res = await this.fetchImpl(`${this.url}?accountRef=${encodeURIComponent(accountRef)}`, {
|
|
223
|
+
method: 'GET',
|
|
224
|
+
headers: { accept: 'application/json', authorization: `Bearer ${token}` },
|
|
225
|
+
signal: AbortSignal.timeout(this.dials.timeoutMs)
|
|
226
|
+
});
|
|
227
|
+
} catch (err) {
|
|
228
|
+
this.opts.logger.warn({ err }, 'entitlements: hub unreachable — the last known plan applies');
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
if (res.status === 401) this.opts.token.invalidate();
|
|
232
|
+
if (!res.ok) {
|
|
233
|
+
this.opts.logger.warn(
|
|
234
|
+
{ status: res.status },
|
|
235
|
+
'entitlements: hub answered non-2xx — the last known plan applies'
|
|
236
|
+
);
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
const parsed = entitlementProfileSchema.safeParse(await res.json().catch(() => null));
|
|
240
|
+
if (!parsed.success) {
|
|
241
|
+
this.opts.logger.warn('entitlements: hub answered a malformed profile — the last known plan applies');
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
return parsed.data;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/** The plan a fresh instance assumes, and the resolution every edition path shares. */
|
|
249
|
+
export function resolve(
|
|
250
|
+
tool: ToolEntitlements,
|
|
251
|
+
entry: CacheEntry | null,
|
|
252
|
+
nowMs: number,
|
|
253
|
+
staleMs: number
|
|
254
|
+
): ResolvedProfile {
|
|
255
|
+
const known = entry && entry.answeredAtMs > 0;
|
|
256
|
+
const stale = known && entry.answeredAtMs + staleMs <= nowMs;
|
|
257
|
+
const plan: EntitlementTier = known && !stale ? entry.plan : 'free';
|
|
258
|
+
const source: ResolvedProfile['source'] =
|
|
259
|
+
!known || stale ? 'default' : entry.freshUntilMs > nowMs ? 'hub' : 'stale';
|
|
260
|
+
const limits: Record<string, number | null> = {};
|
|
261
|
+
for (const [key, tiers] of Object.entries(tool.limits)) {
|
|
262
|
+
const override = known && !stale ? entry.hubLimits[key] : undefined;
|
|
263
|
+
limits[key] = override !== undefined ? limitValue(override) : tiers[plan];
|
|
264
|
+
}
|
|
265
|
+
const features = new Set<string>();
|
|
266
|
+
const hubFeatures = known && !stale ? entry.hubFeatures : null;
|
|
267
|
+
for (const [key, tiers] of Object.entries(tool.features)) {
|
|
268
|
+
if (hubFeatures ? hubFeatures.includes(key) : tiers[plan]) features.add(key);
|
|
269
|
+
}
|
|
270
|
+
const upgradeUrl = known && !stale ? entry.hubUpgradeUrl : null;
|
|
271
|
+
return { plan, limits, features, source, upgradeUrl };
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* A hub limit value as the gate compares it (PRDCT-2636): the hub's contract
|
|
276
|
+
* allows a boolean beside a number — `true` switches the limit off
|
|
277
|
+
* (unlimited, null), `false` allows nothing (0).
|
|
278
|
+
*/
|
|
279
|
+
function limitValue(value: number | boolean): number | null {
|
|
280
|
+
if (value === true) return null;
|
|
281
|
+
if (value === false) return 0;
|
|
282
|
+
return value;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/** How many accounts the cache may hold before a refresh sweeps the unservable entries. */
|
|
286
|
+
const SWEEP_ABOVE = 5_000;
|
|
287
|
+
|
|
288
|
+
/** Resolve when `flight` settles or `ms` elapse, whichever first; the timer never outlives the wait. */
|
|
289
|
+
function withinBudget(flight: Promise<void>, ms: number): Promise<void> {
|
|
290
|
+
return new Promise((resolve) => {
|
|
291
|
+
const timer = setTimeout(resolve, ms);
|
|
292
|
+
timer.unref?.(); // a pending wait must never keep the process alive
|
|
293
|
+
void flight.finally(() => {
|
|
294
|
+
clearTimeout(timer);
|
|
295
|
+
resolve();
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/** The profile of an account nobody asked the hub about: the tool's `free` tier. */
|
|
301
|
+
export function defaultProfile(tool: ToolEntitlements): ResolvedProfile {
|
|
302
|
+
return resolve(tool, null, 0, 0);
|
|
303
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import {
|
|
2
|
+
declareRouteEntitlements,
|
|
3
|
+
ENTITLEMENT_TIERS,
|
|
4
|
+
featureKeyOf,
|
|
5
|
+
toolEntitlementsSchema,
|
|
6
|
+
type RouteEntitlementDeclarations,
|
|
7
|
+
type ToolEntitlements
|
|
8
|
+
} from '@antasphere/chassis-contract';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* What the tool's `entitlements` slot returns (the billing rail spec, §7 and
|
|
12
|
+
* §8b): the three lists `GET /instance` shows (the priced actions with their
|
|
13
|
+
* default credits, the limits and the features per tier) plus the route
|
|
14
|
+
* declarations the gate enforces. A function of the environment, so an oss
|
|
15
|
+
* value can be the operator's env cap.
|
|
16
|
+
*/
|
|
17
|
+
export interface ToolEntitlementDeclaration extends ToolEntitlements {
|
|
18
|
+
routes: RouteEntitlementDeclarations;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** A tool that declares nothing: no route is gated, discovery shows empty lists. */
|
|
22
|
+
export const EMPTY_TOOL_ENTITLEMENTS: ToolEntitlementDeclaration = {
|
|
23
|
+
actions: [],
|
|
24
|
+
limits: {},
|
|
25
|
+
features: {},
|
|
26
|
+
routes: declareRouteEntitlements([])
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The boot-time guard of the slot: every key a route declares must be
|
|
31
|
+
* declared with its values, and a metered route's unit must be the action's.
|
|
32
|
+
* A route that meters an action the price book does not know, or a limit no
|
|
33
|
+
* tier has a value for, is a declaration that could never be enforced or
|
|
34
|
+
* priced — it stops the boot, naming the route.
|
|
35
|
+
*
|
|
36
|
+
* Two checks run on the three lists themselves. First, they are parsed
|
|
37
|
+
* through the contract's `toolEntitlementsSchema`: a limit key missing a
|
|
38
|
+
* tier would otherwise resolve as unlimited in `profiles.ts` while
|
|
39
|
+
* `requiredPlanFor` reports no plan for it, so a malformed declaration stops
|
|
40
|
+
* the boot naming the first issue's path. Second, the ceiling: a limit whose
|
|
41
|
+
* `oss` value is a number is the operator's own ceiling, the instance's hard
|
|
42
|
+
* cap, and no tier may advertise more (nor `null`, unlimited) under it.
|
|
43
|
+
* Discovery once advertised a paid tier the handlers' mid-stream cap could
|
|
44
|
+
* never serve (PRDCT-2653); the boot now refuses the advertisement. A limit
|
|
45
|
+
* whose `oss` is `null` has no ceiling.
|
|
46
|
+
*/
|
|
47
|
+
export function assertToolEntitlements(decl: ToolEntitlementDeclaration): void {
|
|
48
|
+
const parsed = toolEntitlementsSchema.safeParse({
|
|
49
|
+
actions: decl.actions,
|
|
50
|
+
limits: decl.limits,
|
|
51
|
+
features: decl.features
|
|
52
|
+
});
|
|
53
|
+
if (!parsed.success) {
|
|
54
|
+
const issue = parsed.error.issues[0];
|
|
55
|
+
const path = issue ? issue.path.map((p) => String(p)).join('.') : '';
|
|
56
|
+
throw new Error(
|
|
57
|
+
`tool definition: entitlements declaration is malformed: ${path}: ${issue?.message ?? 'invalid'}`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
for (const [key, limit] of Object.entries(decl.limits)) {
|
|
61
|
+
const ceiling = limit.oss;
|
|
62
|
+
if (typeof ceiling !== 'number') continue;
|
|
63
|
+
for (const tier of ENTITLEMENT_TIERS) {
|
|
64
|
+
const value = limit[tier];
|
|
65
|
+
if (typeof value !== 'number' || value > ceiling) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`tool definition: entitlements.limits.${key}.${tier} (${String(value)}) is above the instance ceiling (oss ${ceiling}): a plan value the instance cannot serve must not be advertised`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const actions = new Map(decl.actions.map((a) => [a.key, a]));
|
|
73
|
+
const seenActions = new Set<string>();
|
|
74
|
+
for (const a of decl.actions) {
|
|
75
|
+
if (seenActions.has(a.key))
|
|
76
|
+
throw new Error(`tool definition: entitlements.actions declares ${a.key} twice`);
|
|
77
|
+
seenActions.add(a.key);
|
|
78
|
+
}
|
|
79
|
+
for (const [key, entry] of decl.routes) {
|
|
80
|
+
if (entry.meter) {
|
|
81
|
+
const action = actions.get(entry.meter.key);
|
|
82
|
+
if (!action) {
|
|
83
|
+
throw new Error(
|
|
84
|
+
`tool definition: route ${key} meters "${entry.meter.key}", which entitlements.actions does not declare`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
if (action.unit !== entry.meter.unit) {
|
|
88
|
+
throw new Error(
|
|
89
|
+
`tool definition: route ${key} meters "${entry.meter.key}" in ${entry.meter.unit}, the action is priced per ${action.unit}`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (entry.limit && !(entry.limit.key in decl.limits)) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
`tool definition: route ${key} checks the limit "${entry.limit.key}", which entitlements.limits does not declare`
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
const feature = featureKeyOf(entry);
|
|
99
|
+
if (feature && !(feature in decl.features)) {
|
|
100
|
+
throw new Error(
|
|
101
|
+
`tool definition: route ${key} needs the feature "${feature}", which entitlements.features does not declare`
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|