@urateam/core 0.1.4 → 0.1.9
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/dist/__tests__/agent-profiles.test.d.ts +2 -0
- package/dist/__tests__/agent-profiles.test.d.ts.map +1 -0
- package/dist/__tests__/agent-profiles.test.js +120 -0
- package/dist/__tests__/agent-profiles.test.js.map +1 -0
- package/dist/__tests__/audit/audit-e2e.test.d.ts +2 -0
- package/dist/__tests__/audit/audit-e2e.test.d.ts.map +1 -0
- package/dist/__tests__/audit/audit-e2e.test.js +56 -0
- package/dist/__tests__/audit/audit-e2e.test.js.map +1 -0
- package/dist/__tests__/audit/csv.test.d.ts +2 -0
- package/dist/__tests__/audit/csv.test.d.ts.map +1 -0
- package/dist/__tests__/audit/csv.test.js +134 -0
- package/dist/__tests__/audit/csv.test.js.map +1 -0
- package/dist/__tests__/audit/events.test.d.ts +2 -0
- package/dist/__tests__/audit/events.test.d.ts.map +1 -0
- package/dist/__tests__/audit/events.test.js +45 -0
- package/dist/__tests__/audit/events.test.js.map +1 -0
- package/dist/__tests__/audit/policy-events.test.d.ts +2 -0
- package/dist/__tests__/audit/policy-events.test.d.ts.map +1 -0
- package/dist/__tests__/audit/policy-events.test.js +49 -0
- package/dist/__tests__/audit/policy-events.test.js.map +1 -0
- package/dist/__tests__/audit/projection.test.d.ts +2 -0
- package/dist/__tests__/audit/projection.test.d.ts.map +1 -0
- package/dist/__tests__/audit/projection.test.js +76 -0
- package/dist/__tests__/audit/projection.test.js.map +1 -0
- package/dist/__tests__/audit/rbac-events.test.d.ts +2 -0
- package/dist/__tests__/audit/rbac-events.test.d.ts.map +1 -0
- package/dist/__tests__/audit/rbac-events.test.js +56 -0
- package/dist/__tests__/audit/rbac-events.test.js.map +1 -0
- package/dist/__tests__/audit/reader.test.d.ts +2 -0
- package/dist/__tests__/audit/reader.test.d.ts.map +1 -0
- package/dist/__tests__/audit/reader.test.js +133 -0
- package/dist/__tests__/audit/reader.test.js.map +1 -0
- package/dist/__tests__/audit/retention.test.d.ts +2 -0
- package/dist/__tests__/audit/retention.test.d.ts.map +1 -0
- package/dist/__tests__/audit/retention.test.js +48 -0
- package/dist/__tests__/audit/retention.test.js.map +1 -0
- package/dist/__tests__/audit/sso-events.test.d.ts +2 -0
- package/dist/__tests__/audit/sso-events.test.d.ts.map +1 -0
- package/dist/__tests__/audit/sso-events.test.js +49 -0
- package/dist/__tests__/audit/sso-events.test.js.map +1 -0
- package/dist/__tests__/audit/writer.test.d.ts +2 -0
- package/dist/__tests__/audit/writer.test.d.ts.map +1 -0
- package/dist/__tests__/audit/writer.test.js +67 -0
- package/dist/__tests__/audit/writer.test.js.map +1 -0
- package/dist/__tests__/audit-immutability.test.d.ts +2 -0
- package/dist/__tests__/audit-immutability.test.d.ts.map +1 -0
- package/dist/__tests__/audit-immutability.test.js +61 -0
- package/dist/__tests__/audit-immutability.test.js.map +1 -0
- package/dist/__tests__/audit-types.test.d.ts +2 -0
- package/dist/__tests__/audit-types.test.d.ts.map +1 -0
- package/dist/__tests__/audit-types.test.js +35 -0
- package/dist/__tests__/audit-types.test.js.map +1 -0
- package/dist/__tests__/auth/session-store.test.d.ts +2 -0
- package/dist/__tests__/auth/session-store.test.d.ts.map +1 -0
- package/dist/__tests__/auth/session-store.test.js +65 -0
- package/dist/__tests__/auth/session-store.test.js.map +1 -0
- package/dist/__tests__/auth/sso-config.test.d.ts +2 -0
- package/dist/__tests__/auth/sso-config.test.d.ts.map +1 -0
- package/dist/__tests__/auth/sso-config.test.js +75 -0
- package/dist/__tests__/auth/sso-config.test.js.map +1 -0
- package/dist/__tests__/auth/sso-feature-flag.test.d.ts +2 -0
- package/dist/__tests__/auth/sso-feature-flag.test.d.ts.map +1 -0
- package/dist/__tests__/auth/sso-feature-flag.test.js +33 -0
- package/dist/__tests__/auth/sso-feature-flag.test.js.map +1 -0
- package/dist/__tests__/auth/user-role-round-trip.test.d.ts +2 -0
- package/dist/__tests__/auth/user-role-round-trip.test.d.ts.map +1 -0
- package/dist/__tests__/auth/user-role-round-trip.test.js +30 -0
- package/dist/__tests__/auth/user-role-round-trip.test.js.map +1 -0
- package/dist/__tests__/auth/user-store.test.d.ts +2 -0
- package/dist/__tests__/auth/user-store.test.d.ts.map +1 -0
- package/dist/__tests__/auth/user-store.test.js +119 -0
- package/dist/__tests__/auth/user-store.test.js.map +1 -0
- package/dist/__tests__/auth/workos-client.test.d.ts +2 -0
- package/dist/__tests__/auth/workos-client.test.d.ts.map +1 -0
- package/dist/__tests__/auth/workos-client.test.js +17 -0
- package/dist/__tests__/auth/workos-client.test.js.map +1 -0
- package/dist/__tests__/auto-merge.test.js +2 -1
- package/dist/__tests__/auto-merge.test.js.map +1 -1
- package/dist/__tests__/cost/aggregate.test.d.ts +2 -0
- package/dist/__tests__/cost/aggregate.test.d.ts.map +1 -0
- package/dist/__tests__/cost/aggregate.test.js +358 -0
- package/dist/__tests__/cost/aggregate.test.js.map +1 -0
- package/dist/__tests__/cost/csv.test.d.ts +2 -0
- package/dist/__tests__/cost/csv.test.d.ts.map +1 -0
- package/dist/__tests__/cost/csv.test.js +109 -0
- package/dist/__tests__/cost/csv.test.js.map +1 -0
- package/dist/__tests__/cost/per-run.test.d.ts +2 -0
- package/dist/__tests__/cost/per-run.test.d.ts.map +1 -0
- package/dist/__tests__/cost/per-run.test.js +64 -0
- package/dist/__tests__/cost/per-run.test.js.map +1 -0
- package/dist/__tests__/cost/rates.test.d.ts +2 -0
- package/dist/__tests__/cost/rates.test.d.ts.map +1 -0
- package/dist/__tests__/cost/rates.test.js +47 -0
- package/dist/__tests__/cost/rates.test.js.map +1 -0
- package/dist/__tests__/cost/rollup.test.d.ts +2 -0
- package/dist/__tests__/cost/rollup.test.d.ts.map +1 -0
- package/dist/__tests__/cost/rollup.test.js +187 -0
- package/dist/__tests__/cost/rollup.test.js.map +1 -0
- package/dist/__tests__/cost-defensive.test.d.ts +2 -0
- package/dist/__tests__/cost-defensive.test.d.ts.map +1 -0
- package/dist/__tests__/cost-defensive.test.js +123 -0
- package/dist/__tests__/cost-defensive.test.js.map +1 -0
- package/dist/__tests__/cost-integration.test.d.ts +2 -0
- package/dist/__tests__/cost-integration.test.d.ts.map +1 -0
- package/dist/__tests__/cost-integration.test.js +80 -0
- package/dist/__tests__/cost-integration.test.js.map +1 -0
- package/dist/__tests__/cost-license.test.d.ts +2 -0
- package/dist/__tests__/cost-license.test.d.ts.map +1 -0
- package/dist/__tests__/cost-license.test.js +23 -0
- package/dist/__tests__/cost-license.test.js.map +1 -0
- package/dist/__tests__/cost-types.test.d.ts +2 -0
- package/dist/__tests__/cost-types.test.d.ts.map +1 -0
- package/dist/__tests__/cost-types.test.js +65 -0
- package/dist/__tests__/cost-types.test.js.map +1 -0
- package/dist/__tests__/db-audit-schema.test.d.ts +2 -0
- package/dist/__tests__/db-audit-schema.test.d.ts.map +1 -0
- package/dist/__tests__/db-audit-schema.test.js +35 -0
- package/dist/__tests__/db-audit-schema.test.js.map +1 -0
- package/dist/__tests__/db-cost-rollups-schema.test.d.ts +2 -0
- package/dist/__tests__/db-cost-rollups-schema.test.d.ts.map +1 -0
- package/dist/__tests__/db-cost-rollups-schema.test.js +28 -0
- package/dist/__tests__/db-cost-rollups-schema.test.js.map +1 -0
- package/dist/__tests__/db-rbac-schema.test.d.ts +2 -0
- package/dist/__tests__/db-rbac-schema.test.d.ts.map +1 -0
- package/dist/__tests__/db-rbac-schema.test.js +32 -0
- package/dist/__tests__/db-rbac-schema.test.js.map +1 -0
- package/dist/__tests__/db-sso-schema.test.d.ts +2 -0
- package/dist/__tests__/db-sso-schema.test.d.ts.map +1 -0
- package/dist/__tests__/db-sso-schema.test.js +48 -0
- package/dist/__tests__/db-sso-schema.test.js.map +1 -0
- package/dist/__tests__/executor.test.js +3 -1
- package/dist/__tests__/executor.test.js.map +1 -1
- package/dist/__tests__/extract-handoff.test.js +109 -0
- package/dist/__tests__/extract-handoff.test.js.map +1 -1
- package/dist/__tests__/helpers/license.d.ts +3 -0
- package/dist/__tests__/helpers/license.d.ts.map +1 -0
- package/dist/__tests__/helpers/license.js +74 -0
- package/dist/__tests__/helpers/license.js.map +1 -0
- package/dist/__tests__/license-audit-event.test.d.ts +2 -0
- package/dist/__tests__/license-audit-event.test.d.ts.map +1 -0
- package/dist/__tests__/license-audit-event.test.js +60 -0
- package/dist/__tests__/license-audit-event.test.js.map +1 -0
- package/dist/__tests__/license-end-to-end.test.d.ts +2 -0
- package/dist/__tests__/license-end-to-end.test.d.ts.map +1 -0
- package/dist/__tests__/license-end-to-end.test.js +75 -0
- package/dist/__tests__/license-end-to-end.test.js.map +1 -0
- package/dist/__tests__/license-public-key.test.d.ts +2 -0
- package/dist/__tests__/license-public-key.test.d.ts.map +1 -0
- package/dist/__tests__/license-public-key.test.js +18 -0
- package/dist/__tests__/license-public-key.test.js.map +1 -0
- package/dist/__tests__/license.test.js +195 -32
- package/dist/__tests__/license.test.js.map +1 -1
- package/dist/__tests__/pm-action-audit-events.test.d.ts +2 -0
- package/dist/__tests__/pm-action-audit-events.test.d.ts.map +1 -0
- package/dist/__tests__/pm-action-audit-events.test.js +185 -0
- package/dist/__tests__/pm-action-audit-events.test.js.map +1 -0
- package/dist/__tests__/pm-approvals.test.js +1 -1
- package/dist/__tests__/pm-approvals.test.js.map +1 -1
- package/dist/__tests__/pm-audit-retention-step.test.d.ts +2 -0
- package/dist/__tests__/pm-audit-retention-step.test.d.ts.map +1 -0
- package/dist/__tests__/pm-audit-retention-step.test.js +126 -0
- package/dist/__tests__/pm-audit-retention-step.test.js.map +1 -0
- package/dist/__tests__/pm-budget-alerts.test.d.ts +2 -0
- package/dist/__tests__/pm-budget-alerts.test.d.ts.map +1 -0
- package/dist/__tests__/pm-budget-alerts.test.js +128 -0
- package/dist/__tests__/pm-budget-alerts.test.js.map +1 -0
- package/dist/__tests__/pm-budget-refused-event.test.d.ts +2 -0
- package/dist/__tests__/pm-budget-refused-event.test.d.ts.map +1 -0
- package/dist/__tests__/pm-budget-refused-event.test.js +141 -0
- package/dist/__tests__/pm-budget-refused-event.test.js.map +1 -0
- package/dist/__tests__/pm-budget.test.js +138 -42
- package/dist/__tests__/pm-budget.test.js.map +1 -1
- package/dist/__tests__/pm-cost-rollup-step.test.d.ts +2 -0
- package/dist/__tests__/pm-cost-rollup-step.test.d.ts.map +1 -0
- package/dist/__tests__/pm-cost-rollup-step.test.js +113 -0
- package/dist/__tests__/pm-cost-rollup-step.test.js.map +1 -0
- package/dist/__tests__/pm-scheduler.test.js +48 -21
- package/dist/__tests__/pm-scheduler.test.js.map +1 -1
- package/dist/__tests__/pm-slack.test.js +37 -0
- package/dist/__tests__/pm-slack.test.js.map +1 -1
- package/dist/__tests__/pm-sso-prune-step.test.d.ts +2 -0
- package/dist/__tests__/pm-sso-prune-step.test.d.ts.map +1 -0
- package/dist/__tests__/pm-sso-prune-step.test.js +103 -0
- package/dist/__tests__/pm-sso-prune-step.test.js.map +1 -0
- package/dist/__tests__/pm-types.test.js +130 -1
- package/dist/__tests__/pm-types.test.js.map +1 -1
- package/dist/__tests__/policy/auto-merge-reviewer-gate.test.d.ts +2 -0
- package/dist/__tests__/policy/auto-merge-reviewer-gate.test.d.ts.map +1 -0
- package/dist/__tests__/policy/auto-merge-reviewer-gate.test.js +50 -0
- package/dist/__tests__/policy/auto-merge-reviewer-gate.test.js.map +1 -0
- package/dist/__tests__/policy/cost-gate.test.d.ts +2 -0
- package/dist/__tests__/policy/cost-gate.test.d.ts.map +1 -0
- package/dist/__tests__/policy/cost-gate.test.js +27 -0
- package/dist/__tests__/policy/cost-gate.test.js.map +1 -0
- package/dist/__tests__/policy/evaluate.test.d.ts +2 -0
- package/dist/__tests__/policy/evaluate.test.d.ts.map +1 -0
- package/dist/__tests__/policy/evaluate.test.js +105 -0
- package/dist/__tests__/policy/evaluate.test.js.map +1 -0
- package/dist/__tests__/policy/override.test.d.ts +2 -0
- package/dist/__tests__/policy/override.test.d.ts.map +1 -0
- package/dist/__tests__/policy/override.test.js +26 -0
- package/dist/__tests__/policy/override.test.js.map +1 -0
- package/dist/__tests__/policy/path-gate.test.d.ts +2 -0
- package/dist/__tests__/policy/path-gate.test.d.ts.map +1 -0
- package/dist/__tests__/policy/path-gate.test.js +31 -0
- package/dist/__tests__/policy/path-gate.test.js.map +1 -0
- package/dist/__tests__/policy/pr-reviewer-wiring.test.d.ts +2 -0
- package/dist/__tests__/policy/pr-reviewer-wiring.test.d.ts.map +1 -0
- package/dist/__tests__/policy/pr-reviewer-wiring.test.js +24 -0
- package/dist/__tests__/policy/pr-reviewer-wiring.test.js.map +1 -0
- package/dist/__tests__/policy/reviewer-gate.test.d.ts +2 -0
- package/dist/__tests__/policy/reviewer-gate.test.d.ts.map +1 -0
- package/dist/__tests__/policy/reviewer-gate.test.js +125 -0
- package/dist/__tests__/policy/reviewer-gate.test.js.map +1 -0
- package/dist/__tests__/policy-license.test.d.ts +2 -0
- package/dist/__tests__/policy-license.test.d.ts.map +1 -0
- package/dist/__tests__/policy-license.test.js +31 -0
- package/dist/__tests__/policy-license.test.js.map +1 -0
- package/dist/__tests__/policy-types.test.d.ts +2 -0
- package/dist/__tests__/policy-types.test.d.ts.map +1 -0
- package/dist/__tests__/policy-types.test.js +49 -0
- package/dist/__tests__/policy-types.test.js.map +1 -0
- package/dist/__tests__/ralph-gate.test.js +6 -4
- package/dist/__tests__/ralph-gate.test.js.map +1 -1
- package/dist/__tests__/rbac/bootstrap.test.d.ts +2 -0
- package/dist/__tests__/rbac/bootstrap.test.d.ts.map +1 -0
- package/dist/__tests__/rbac/bootstrap.test.js +62 -0
- package/dist/__tests__/rbac/bootstrap.test.js.map +1 -0
- package/dist/__tests__/rbac/matrix.test.d.ts +2 -0
- package/dist/__tests__/rbac/matrix.test.d.ts.map +1 -0
- package/dist/__tests__/rbac/matrix.test.js +62 -0
- package/dist/__tests__/rbac/matrix.test.js.map +1 -0
- package/dist/__tests__/rbac/user-role-store.test.d.ts +2 -0
- package/dist/__tests__/rbac/user-role-store.test.d.ts.map +1 -0
- package/dist/__tests__/rbac/user-role-store.test.js +78 -0
- package/dist/__tests__/rbac/user-role-store.test.js.map +1 -0
- package/dist/__tests__/rbac-defensive.test.d.ts +2 -0
- package/dist/__tests__/rbac-defensive.test.d.ts.map +1 -0
- package/dist/__tests__/rbac-defensive.test.js +29 -0
- package/dist/__tests__/rbac-defensive.test.js.map +1 -0
- package/dist/__tests__/rbac-integration.test.d.ts +2 -0
- package/dist/__tests__/rbac-integration.test.d.ts.map +1 -0
- package/dist/__tests__/rbac-integration.test.js +58 -0
- package/dist/__tests__/rbac-integration.test.js.map +1 -0
- package/dist/__tests__/rbac-license.test.d.ts +2 -0
- package/dist/__tests__/rbac-license.test.d.ts.map +1 -0
- package/dist/__tests__/rbac-license.test.js +27 -0
- package/dist/__tests__/rbac-license.test.js.map +1 -0
- package/dist/__tests__/reproduce-bec113-pagination-warning.test.js +14 -2
- package/dist/__tests__/reproduce-bec113-pagination-warning.test.js.map +1 -1
- package/dist/__tests__/reproduce-bec62.test.js +10 -3
- package/dist/__tests__/reproduce-bec62.test.js.map +1 -1
- package/dist/__tests__/reproduce-bec91-stuck-in-progress.test.js +24 -4
- package/dist/__tests__/reproduce-bec91-stuck-in-progress.test.js.map +1 -1
- package/dist/__tests__/server.test.js +46 -2
- package/dist/__tests__/server.test.js.map +1 -1
- package/dist/__tests__/sso-license.test.d.ts +2 -0
- package/dist/__tests__/sso-license.test.d.ts.map +1 -0
- package/dist/__tests__/sso-license.test.js +49 -0
- package/dist/__tests__/sso-license.test.js.map +1 -0
- package/dist/__tests__/stage-models.test.js.map +1 -1
- package/dist/__tests__/start-todo.test.js +5 -0
- package/dist/__tests__/start-todo.test.js.map +1 -1
- package/dist/__tests__/webhook-handler.test.js +138 -0
- package/dist/__tests__/webhook-handler.test.js.map +1 -1
- package/dist/audit/config-fingerprint.d.ts +10 -0
- package/dist/audit/config-fingerprint.d.ts.map +1 -0
- package/dist/audit/config-fingerprint.js +20 -0
- package/dist/audit/config-fingerprint.js.map +1 -0
- package/dist/audit/csv.d.ts +8 -0
- package/dist/audit/csv.d.ts.map +1 -0
- package/dist/audit/csv.js +56 -0
- package/dist/audit/csv.js.map +1 -0
- package/dist/audit/events.d.ts +107 -0
- package/dist/audit/events.d.ts.map +1 -0
- package/dist/audit/events.js +221 -0
- package/dist/audit/events.js.map +1 -0
- package/dist/audit/index.d.ts +7 -0
- package/dist/audit/index.d.ts.map +1 -0
- package/dist/audit/index.js +7 -0
- package/dist/audit/index.js.map +1 -0
- package/dist/audit/projection.d.ts +38 -0
- package/dist/audit/projection.d.ts.map +1 -0
- package/dist/audit/projection.js +109 -0
- package/dist/audit/projection.js.map +1 -0
- package/dist/audit/reader.d.ts +42 -0
- package/dist/audit/reader.d.ts.map +1 -0
- package/dist/audit/reader.js +243 -0
- package/dist/audit/reader.js.map +1 -0
- package/dist/audit/retention.d.ts +12 -0
- package/dist/audit/retention.d.ts.map +1 -0
- package/dist/audit/retention.js +23 -0
- package/dist/audit/retention.js.map +1 -0
- package/dist/audit/writer.d.ts +26 -0
- package/dist/audit/writer.d.ts.map +1 -0
- package/dist/audit/writer.js +54 -0
- package/dist/audit/writer.js.map +1 -0
- package/dist/auth/index.d.ts +5 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +5 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/session-store.d.ts +17 -0
- package/dist/auth/session-store.d.ts.map +1 -0
- package/dist/auth/session-store.js +59 -0
- package/dist/auth/session-store.js.map +1 -0
- package/dist/auth/sso-config.d.ts +14 -0
- package/dist/auth/sso-config.d.ts.map +1 -0
- package/dist/auth/sso-config.js +50 -0
- package/dist/auth/sso-config.js.map +1 -0
- package/dist/auth/user-store.d.ts +33 -0
- package/dist/auth/user-store.d.ts.map +1 -0
- package/dist/auth/user-store.js +71 -0
- package/dist/auth/user-store.js.map +1 -0
- package/dist/auth/workos-client.d.ts +46 -0
- package/dist/auth/workos-client.d.ts.map +1 -0
- package/dist/auth/workos-client.js +66 -0
- package/dist/auth/workos-client.js.map +1 -0
- package/dist/cost/aggregate.d.ts +49 -0
- package/dist/cost/aggregate.d.ts.map +1 -0
- package/dist/cost/aggregate.js +364 -0
- package/dist/cost/aggregate.js.map +1 -0
- package/dist/cost/csv.d.ts +12 -0
- package/dist/cost/csv.d.ts.map +1 -0
- package/dist/cost/csv.js +79 -0
- package/dist/cost/csv.js.map +1 -0
- package/dist/cost/index.d.ts +7 -0
- package/dist/cost/index.d.ts.map +1 -0
- package/dist/cost/index.js +7 -0
- package/dist/cost/index.js.map +1 -0
- package/dist/cost/per-run.d.ts +31 -0
- package/dist/cost/per-run.d.ts.map +1 -0
- package/dist/cost/per-run.js +35 -0
- package/dist/cost/per-run.js.map +1 -0
- package/dist/cost/rates.d.ts +27 -0
- package/dist/cost/rates.d.ts.map +1 -0
- package/dist/cost/rates.js +26 -0
- package/dist/cost/rates.js.map +1 -0
- package/dist/cost/rollup.d.ts +17 -0
- package/dist/cost/rollup.d.ts.map +1 -0
- package/dist/cost/rollup.js +164 -0
- package/dist/cost/rollup.js.map +1 -0
- package/dist/cost/types.d.ts +54 -0
- package/dist/cost/types.d.ts.map +1 -0
- package/dist/cost/types.js +2 -0
- package/dist/cost/types.js.map +1 -0
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +79 -1
- package/dist/db/client.js.map +1 -1
- package/dist/db/migrations/postgres/006_spend_caps.sql +14 -0
- package/dist/db/migrations/postgres/007_audit_events.sql +19 -0
- package/dist/db/migrations/postgres/008_cost_rollups.sql +19 -0
- package/dist/db/migrations/postgres/008_sso.sql +20 -0
- package/dist/db/migrations/sqlite/005_spend_caps.sql +16 -0
- package/dist/db/migrations/sqlite/006_audit_events.sql +19 -0
- package/dist/db/migrations/sqlite/007_cost_rollups.sql +19 -0
- package/dist/db/migrations/sqlite/007_sso.sql +20 -0
- package/dist/db/schema.d.ts +802 -0
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +80 -1
- package/dist/db/schema.js.map +1 -1
- package/dist/executor/executor.js +2 -2
- package/dist/executor/executor.js.map +1 -1
- package/dist/executor/extract-handoff.d.ts +7 -1
- package/dist/executor/extract-handoff.d.ts.map +1 -1
- package/dist/executor/extract-handoff.js +51 -11
- package/dist/executor/extract-handoff.js.map +1 -1
- package/dist/executor/handoff.d.ts.map +1 -1
- package/dist/executor/handoff.js +6 -0
- package/dist/executor/handoff.js.map +1 -1
- package/dist/executor/index.d.ts +1 -1
- package/dist/executor/index.d.ts.map +1 -1
- package/dist/executor/index.js +1 -1
- package/dist/executor/index.js.map +1 -1
- package/dist/executor/profiles.d.ts +42 -0
- package/dist/executor/profiles.d.ts.map +1 -1
- package/dist/executor/profiles.js +147 -2
- package/dist/executor/profiles.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/license-public-key.d.ts +15 -0
- package/dist/license-public-key.d.ts.map +1 -0
- package/dist/license-public-key.js +15 -0
- package/dist/license-public-key.js.map +1 -0
- package/dist/license.d.ts +30 -5
- package/dist/license.d.ts.map +1 -1
- package/dist/license.js +142 -12
- package/dist/license.js.map +1 -1
- package/dist/pipeline/runner.d.ts +1 -7
- package/dist/pipeline/runner.d.ts.map +1 -1
- package/dist/pipeline/runner.js +168 -21
- package/dist/pipeline/runner.js.map +1 -1
- package/dist/pm/actions/promote.d.ts +3 -0
- package/dist/pm/actions/promote.d.ts.map +1 -1
- package/dist/pm/actions/promote.js +12 -0
- package/dist/pm/actions/promote.js.map +1 -1
- package/dist/pm/actions/resolve-approvals.d.ts.map +1 -1
- package/dist/pm/actions/resolve-approvals.js +16 -0
- package/dist/pm/actions/resolve-approvals.js.map +1 -1
- package/dist/pm/actions/start-todo.d.ts +3 -0
- package/dist/pm/actions/start-todo.d.ts.map +1 -1
- package/dist/pm/actions/start-todo.js +5 -1
- package/dist/pm/actions/start-todo.js.map +1 -1
- package/dist/pm/actions/triage.d.ts +3 -0
- package/dist/pm/actions/triage.d.ts.map +1 -1
- package/dist/pm/actions/triage.js +8 -0
- package/dist/pm/actions/triage.js.map +1 -1
- package/dist/pm/budget-alerts.d.ts +18 -0
- package/dist/pm/budget-alerts.d.ts.map +1 -0
- package/dist/pm/budget-alerts.js +100 -0
- package/dist/pm/budget-alerts.js.map +1 -0
- package/dist/pm/budget.d.ts +28 -5
- package/dist/pm/budget.d.ts.map +1 -1
- package/dist/pm/budget.js +115 -39
- package/dist/pm/budget.js.map +1 -1
- package/dist/pm/scheduler.d.ts +8 -4
- package/dist/pm/scheduler.d.ts.map +1 -1
- package/dist/pm/scheduler.js +128 -5
- package/dist/pm/scheduler.js.map +1 -1
- package/dist/pm/slack.d.ts.map +1 -1
- package/dist/pm/slack.js +11 -0
- package/dist/pm/slack.js.map +1 -1
- package/dist/pm/types.d.ts +36 -0
- package/dist/pm/types.d.ts.map +1 -1
- package/dist/pm/types.js +12 -0
- package/dist/pm/types.js.map +1 -1
- package/dist/policy/cost-gate.d.ts +3 -0
- package/dist/policy/cost-gate.d.ts.map +1 -0
- package/dist/policy/cost-gate.js +11 -0
- package/dist/policy/cost-gate.js.map +1 -0
- package/dist/policy/evaluate.d.ts +32 -0
- package/dist/policy/evaluate.d.ts.map +1 -0
- package/dist/policy/evaluate.js +61 -0
- package/dist/policy/evaluate.js.map +1 -0
- package/dist/policy/index.d.ts +7 -0
- package/dist/policy/index.d.ts.map +1 -0
- package/dist/policy/index.js +7 -0
- package/dist/policy/index.js.map +1 -0
- package/dist/policy/override.d.ts +23 -0
- package/dist/policy/override.d.ts.map +1 -0
- package/dist/policy/override.js +26 -0
- package/dist/policy/override.js.map +1 -0
- package/dist/policy/path-gate.d.ts +3 -0
- package/dist/policy/path-gate.d.ts.map +1 -0
- package/dist/policy/path-gate.js +20 -0
- package/dist/policy/path-gate.js.map +1 -0
- package/dist/policy/reviewer-gate.d.ts +45 -0
- package/dist/policy/reviewer-gate.d.ts.map +1 -0
- package/dist/policy/reviewer-gate.js +77 -0
- package/dist/policy/reviewer-gate.js.map +1 -0
- package/dist/policy/types.d.ts +7 -0
- package/dist/policy/types.d.ts.map +1 -0
- package/dist/policy/types.js +2 -0
- package/dist/policy/types.js.map +1 -0
- package/dist/rbac/errors.d.ts +7 -0
- package/dist/rbac/errors.d.ts.map +1 -0
- package/dist/rbac/errors.js +13 -0
- package/dist/rbac/errors.js.map +1 -0
- package/dist/rbac/index.d.ts +5 -0
- package/dist/rbac/index.d.ts.map +1 -0
- package/dist/rbac/index.js +5 -0
- package/dist/rbac/index.js.map +1 -0
- package/dist/rbac/matrix.d.ts +35 -0
- package/dist/rbac/matrix.d.ts.map +1 -0
- package/dist/rbac/matrix.js +42 -0
- package/dist/rbac/matrix.js.map +1 -0
- package/dist/rbac/types.d.ts +2 -0
- package/dist/rbac/types.d.ts.map +1 -0
- package/dist/rbac/types.js +2 -0
- package/dist/rbac/types.js.map +1 -0
- package/dist/rbac/user-role-store.d.ts +27 -0
- package/dist/rbac/user-role-store.d.ts.map +1 -0
- package/dist/rbac/user-role-store.js +148 -0
- package/dist/rbac/user-role-store.js.map +1 -0
- package/dist/repo/git.d.ts +9 -0
- package/dist/repo/git.d.ts.map +1 -1
- package/dist/repo/git.js +11 -0
- package/dist/repo/git.js.map +1 -1
- package/dist/repo/github.d.ts +4 -0
- package/dist/repo/github.d.ts.map +1 -1
- package/dist/repo/github.js +27 -0
- package/dist/repo/github.js.map +1 -1
- package/dist/repo/gitlab.d.ts +4 -0
- package/dist/repo/gitlab.d.ts.map +1 -1
- package/dist/repo/gitlab.js +7 -0
- package/dist/repo/gitlab.js.map +1 -1
- package/dist/server.d.ts +6 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +16 -10
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts +155 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +83 -0
- package/dist/types.js.map +1 -1
- package/dist/util/glob.d.ts +7 -0
- package/dist/util/glob.d.ts.map +1 -0
- package/dist/util/glob.js +20 -0
- package/dist/util/glob.js.map +1 -0
- package/dist/webhook/handler.d.ts +3 -0
- package/dist/webhook/handler.d.ts.map +1 -1
- package/dist/webhook/handler.js +36 -2
- package/dist/webhook/handler.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { dashboardGrantRoleEvent, dashboardRevokeRoleEvent, dashboardBootstrapAdminEvent, dashboardRetryRunEvent, } from "../../audit/events.js";
|
|
3
|
+
import { AuditEventSchema } from "../../types.js";
|
|
4
|
+
describe("rbac audit event builders", () => {
|
|
5
|
+
it("dashboardGrantRoleEvent", () => {
|
|
6
|
+
const evt = dashboardGrantRoleEvent({
|
|
7
|
+
targetUserId: "u_1",
|
|
8
|
+
targetEmail: "a@b.com",
|
|
9
|
+
oldRole: "viewer",
|
|
10
|
+
newRole: "operator",
|
|
11
|
+
actorUserId: "u_admin",
|
|
12
|
+
actorEmail: "admin@b.com",
|
|
13
|
+
});
|
|
14
|
+
const p = AuditEventSchema.parse(evt);
|
|
15
|
+
expect(p.eventType).toBe("dashboard.manual_action");
|
|
16
|
+
expect(p.actor).toBe("dashboard:admin@b.com");
|
|
17
|
+
expect(p.payload.action).toBe("grant_role");
|
|
18
|
+
expect(p.payload.oldRole).toBe("viewer");
|
|
19
|
+
expect(p.payload.newRole).toBe("operator");
|
|
20
|
+
});
|
|
21
|
+
it("dashboardRevokeRoleEvent", () => {
|
|
22
|
+
const evt = dashboardRevokeRoleEvent({
|
|
23
|
+
targetUserId: "u_1",
|
|
24
|
+
targetEmail: "a@b.com",
|
|
25
|
+
oldRole: "operator",
|
|
26
|
+
newRole: "viewer",
|
|
27
|
+
actorUserId: "u_admin",
|
|
28
|
+
actorEmail: "admin@b.com",
|
|
29
|
+
});
|
|
30
|
+
expect(evt.payload.action).toBe("revoke_role");
|
|
31
|
+
});
|
|
32
|
+
it("dashboardBootstrapAdminEvent", () => {
|
|
33
|
+
const evt = dashboardBootstrapAdminEvent({
|
|
34
|
+
targetUserId: "u_1",
|
|
35
|
+
targetEmail: "alice@acme.com",
|
|
36
|
+
});
|
|
37
|
+
expect(evt.eventType).toBe("dashboard.manual_action");
|
|
38
|
+
expect(evt.actor).toBe("system");
|
|
39
|
+
expect(evt.actorType).toBe("system");
|
|
40
|
+
expect(evt.payload.action).toBe("bootstrap_admin");
|
|
41
|
+
});
|
|
42
|
+
it("dashboardRetryRunEvent", () => {
|
|
43
|
+
const evt = dashboardRetryRunEvent({
|
|
44
|
+
runId: "run_1",
|
|
45
|
+
issueId: "BEC-42",
|
|
46
|
+
previousStatus: "failed",
|
|
47
|
+
actorUserId: "u_op",
|
|
48
|
+
actorEmail: "op@b.com",
|
|
49
|
+
});
|
|
50
|
+
expect(evt.payload.action).toBe("retry_run");
|
|
51
|
+
expect(evt.runId).toBe("run_1");
|
|
52
|
+
expect(evt.issueId).toBe("BEC-42");
|
|
53
|
+
expect(evt.actor).toBe("dashboard:op@b.com");
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
//# sourceMappingURL=rbac-events.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rbac-events.test.js","sourceRoot":"","sources":["../../../src/__tests__/audit/rbac-events.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reader.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/audit/reader.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { createDb } from "../../db/client.js";
|
|
3
|
+
import { pipelineRuns, pmApprovals, budgetAlerts } from "../../db/schema.js";
|
|
4
|
+
import { logAuditEvent } from "../../audit/writer.js";
|
|
5
|
+
import { pmPromotedEvent, budgetRefusedEvent } from "../../audit/events.js";
|
|
6
|
+
import { listAuditEvents, findAuditEventById } from "../../audit/reader.js";
|
|
7
|
+
import { installTestProLicense, restoreLicense } from "../helpers/license.js";
|
|
8
|
+
let db;
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
await installTestProLicense("enterprise");
|
|
11
|
+
db = await createDb({ connectionString: ":memory:" });
|
|
12
|
+
});
|
|
13
|
+
afterEach(async () => {
|
|
14
|
+
await restoreLicense();
|
|
15
|
+
});
|
|
16
|
+
async function seed() {
|
|
17
|
+
// native audit events
|
|
18
|
+
await logAuditEvent(db, pmPromotedEvent({ issueId: "BEC-1", fromState: "Backlog", toState: "Todo" }));
|
|
19
|
+
await logAuditEvent(db, budgetRefusedEvent({
|
|
20
|
+
scope: "team:T1", scopeType: "team", tokensUsed: 100, limit: 100, utilization: 100,
|
|
21
|
+
}));
|
|
22
|
+
// projectable: pipeline run
|
|
23
|
+
await db.insert(pipelineRuns).values({
|
|
24
|
+
id: "run_1", issueId: "BEC-9", issueTitle: "t", pipelineKey: "auto-implement",
|
|
25
|
+
repoUrl: "https://x.y/z", status: "completed",
|
|
26
|
+
startedAt: new Date("2026-04-01T10:00:00Z"),
|
|
27
|
+
completedAt: new Date("2026-04-01T10:05:00Z"),
|
|
28
|
+
totalInputTokens: 100, totalOutputTokens: 50, runType: "standard",
|
|
29
|
+
linearTeamId: "T1",
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
describe("listAuditEvents", () => {
|
|
33
|
+
it("returns native + projected events merged by time", async () => {
|
|
34
|
+
await seed();
|
|
35
|
+
const { events } = await listAuditEvents(db, { limit: 100 });
|
|
36
|
+
const types = events.map(e => e.eventType).sort();
|
|
37
|
+
expect(types).toContain("pm.issue_promoted");
|
|
38
|
+
expect(types).toContain("budget.run_refused");
|
|
39
|
+
expect(types).toContain("run.started");
|
|
40
|
+
expect(types).toContain("run.completed");
|
|
41
|
+
});
|
|
42
|
+
it("filters by event type", async () => {
|
|
43
|
+
await seed();
|
|
44
|
+
const { events } = await listAuditEvents(db, { eventTypes: ["run.completed"], limit: 100 });
|
|
45
|
+
expect(events.map(e => e.eventType)).toEqual(["run.completed"]);
|
|
46
|
+
});
|
|
47
|
+
it("filters by scope prefix-exact", async () => {
|
|
48
|
+
await seed();
|
|
49
|
+
const { events } = await listAuditEvents(db, { scope: "team:T1", limit: 100 });
|
|
50
|
+
for (const e of events)
|
|
51
|
+
expect(e.scope === "team:T1" || e.scope === null).toBeTruthy();
|
|
52
|
+
expect(events.some(e => e.scope === "team:T1")).toBe(true);
|
|
53
|
+
});
|
|
54
|
+
it("filters by date window", async () => {
|
|
55
|
+
await seed();
|
|
56
|
+
const from = new Date("2026-04-01T09:00:00Z");
|
|
57
|
+
const to = new Date("2026-04-01T10:10:00Z");
|
|
58
|
+
const { events } = await listAuditEvents(db, { from, to, limit: 100 });
|
|
59
|
+
for (const e of events) {
|
|
60
|
+
expect(e.timestamp >= from && e.timestamp <= to).toBe(true);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
it("filters by runId", async () => {
|
|
64
|
+
await seed();
|
|
65
|
+
const { events } = await listAuditEvents(db, { runId: "run_1", limit: 100 });
|
|
66
|
+
expect(events.length).toBeGreaterThan(0);
|
|
67
|
+
for (const e of events)
|
|
68
|
+
expect(e.runId).toBe("run_1");
|
|
69
|
+
});
|
|
70
|
+
it("findAuditEventById finds native audit_events rows", async () => {
|
|
71
|
+
await seed();
|
|
72
|
+
const { events } = await listAuditEvents(db, { eventTypes: ["pm.issue_promoted"], limit: 10 });
|
|
73
|
+
expect(events.length).toBeGreaterThan(0);
|
|
74
|
+
const nativeId = events[0].id;
|
|
75
|
+
const found = await findAuditEventById(db, nativeId);
|
|
76
|
+
expect(found).not.toBeNull();
|
|
77
|
+
expect(found.id).toBe(nativeId);
|
|
78
|
+
expect(found.eventType).toBe("pm.issue_promoted");
|
|
79
|
+
});
|
|
80
|
+
it("findAuditEventById resolves projected pipeline_run events", async () => {
|
|
81
|
+
await seed();
|
|
82
|
+
const found = await findAuditEventById(db, "proj_run_started_run_1");
|
|
83
|
+
expect(found).not.toBeNull();
|
|
84
|
+
expect(found.eventType).toBe("run.started");
|
|
85
|
+
expect(found.runId).toBe("run_1");
|
|
86
|
+
const completed = await findAuditEventById(db, "proj_run_completed_run_1");
|
|
87
|
+
expect(completed).not.toBeNull();
|
|
88
|
+
expect(completed.eventType).toBe("run.completed");
|
|
89
|
+
});
|
|
90
|
+
it("findAuditEventById resolves projected pm_approval events", async () => {
|
|
91
|
+
await db.insert(pmApprovals).values({
|
|
92
|
+
id: "appr_1", issueId: "BEC-2", action: "deprioritize", reason: "stale",
|
|
93
|
+
slackMessageTs: "1234.5678", status: "pending",
|
|
94
|
+
createdAt: new Date("2026-04-01T10:00:00Z"),
|
|
95
|
+
resolvedAt: null,
|
|
96
|
+
});
|
|
97
|
+
const found = await findAuditEventById(db, "proj_approval_requested_appr_1");
|
|
98
|
+
expect(found).not.toBeNull();
|
|
99
|
+
expect(found.eventType).toBe("pm.approval_requested");
|
|
100
|
+
});
|
|
101
|
+
it("findAuditEventById resolves projected budget_alert events", async () => {
|
|
102
|
+
await db.insert(budgetAlerts).values({
|
|
103
|
+
id: "alert_1", date: "2026-04-01", scope: "team:T1", threshold: 80,
|
|
104
|
+
firedAt: new Date("2026-04-01T10:00:00Z"),
|
|
105
|
+
});
|
|
106
|
+
const found = await findAuditEventById(db, "proj_budget_alert_alert_1");
|
|
107
|
+
expect(found).not.toBeNull();
|
|
108
|
+
expect(found.eventType).toBe("budget.alert_fired");
|
|
109
|
+
expect(found.scope).toBe("team:T1");
|
|
110
|
+
});
|
|
111
|
+
it("findAuditEventById returns null for missing events", async () => {
|
|
112
|
+
await seed();
|
|
113
|
+
expect(await findAuditEventById(db, "nonexistent")).toBeNull();
|
|
114
|
+
expect(await findAuditEventById(db, "proj_run_started_missing")).toBeNull();
|
|
115
|
+
expect(await findAuditEventById(db, "proj_approval_requested_missing")).toBeNull();
|
|
116
|
+
expect(await findAuditEventById(db, "proj_budget_alert_missing")).toBeNull();
|
|
117
|
+
});
|
|
118
|
+
it("paginates via cursor", async () => {
|
|
119
|
+
// seed 5 promoted events
|
|
120
|
+
for (let i = 0; i < 5; i++) {
|
|
121
|
+
await logAuditEvent(db, pmPromotedEvent({ issueId: `BEC-${i}`, fromState: "Backlog", toState: "Todo" }));
|
|
122
|
+
await new Promise(r => setTimeout(r, 10));
|
|
123
|
+
}
|
|
124
|
+
const page1 = await listAuditEvents(db, { limit: 2 });
|
|
125
|
+
expect(page1.events).toHaveLength(2);
|
|
126
|
+
expect(page1.nextCursor).not.toBeNull();
|
|
127
|
+
const page2 = await listAuditEvents(db, { limit: 2, cursor: page1.nextCursor });
|
|
128
|
+
expect(page2.events).toHaveLength(2);
|
|
129
|
+
const seen = new Set([...page1.events, ...page2.events].map(e => e.id));
|
|
130
|
+
expect(seen.size).toBe(4);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
//# sourceMappingURL=reader.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reader.test.js","sourceRoot":"","sources":["../../../src/__tests__/audit/reader.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/audit/retention.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { createDb } from "../../db/client.js";
|
|
3
|
+
import { auditEvents, pipelineRuns } from "../../db/schema.js";
|
|
4
|
+
import { pruneAuditLog } from "../../audit/retention.js";
|
|
5
|
+
describe("pruneAuditLog", () => {
|
|
6
|
+
it("deletes rows older than retentionDays", async () => {
|
|
7
|
+
const db = await createDb({ connectionString: ":memory:" });
|
|
8
|
+
const now = Date.now();
|
|
9
|
+
await db.insert(auditEvents).values([
|
|
10
|
+
{
|
|
11
|
+
id: "old",
|
|
12
|
+
timestamp: new Date(now - 400 * 86400000),
|
|
13
|
+
eventType: "pm.issue_promoted",
|
|
14
|
+
actor: "pm-agent",
|
|
15
|
+
actorType: "pm-agent",
|
|
16
|
+
payload: "{}",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
id: "new",
|
|
20
|
+
timestamp: new Date(now - 10 * 86400000),
|
|
21
|
+
eventType: "pm.issue_promoted",
|
|
22
|
+
actor: "pm-agent",
|
|
23
|
+
actorType: "pm-agent",
|
|
24
|
+
payload: "{}",
|
|
25
|
+
},
|
|
26
|
+
]);
|
|
27
|
+
const deleted = await pruneAuditLog(db, 365);
|
|
28
|
+
expect(deleted).toBe(1);
|
|
29
|
+
const rows = await db.select().from(auditEvents);
|
|
30
|
+
expect(rows.map((r) => r.id)).toEqual(["new"]);
|
|
31
|
+
});
|
|
32
|
+
it("does not touch pipeline_runs", async () => {
|
|
33
|
+
const db = await createDb({ connectionString: ":memory:" });
|
|
34
|
+
await db.insert(pipelineRuns).values({
|
|
35
|
+
id: "r1",
|
|
36
|
+
issueId: "BEC-1",
|
|
37
|
+
issueTitle: "t",
|
|
38
|
+
pipelineKey: "auto-implement",
|
|
39
|
+
repoUrl: "x",
|
|
40
|
+
status: "completed",
|
|
41
|
+
startedAt: new Date(Date.now() - 400 * 86400000),
|
|
42
|
+
});
|
|
43
|
+
await pruneAuditLog(db, 365);
|
|
44
|
+
const rows = await db.select().from(pipelineRuns);
|
|
45
|
+
expect(rows).toHaveLength(1);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
//# sourceMappingURL=retention.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention.test.js","sourceRoot":"","sources":["../../../src/__tests__/audit/retention.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC,CAAC;QAC5D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAO,EAAU,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC;YAC3C;gBACE,EAAE,EAAE,KAAK;gBACT,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,GAAG,GAAG,GAAG,QAAQ,CAAC;gBACzC,SAAS,EAAE,mBAAmB;gBAC9B,KAAK,EAAE,UAAU;gBACjB,SAAS,EAAE,UAAU;gBACrB,OAAO,EAAE,IAAI;aACd;YACD;gBACE,EAAE,EAAE,KAAK;gBACT,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,GAAG,EAAE,GAAG,QAAQ,CAAC;gBACxC,SAAS,EAAE,mBAAmB;gBAC9B,KAAK,EAAE,UAAU;gBACjB,SAAS,EAAE,UAAU;gBACrB,OAAO,EAAE,IAAI;aACd;SACF,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC7C,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxB,MAAM,IAAI,GAAG,MAAO,EAAU,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC1D,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;QAC5C,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC,CAAC;QAC5D,MAAO,EAAU,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC;YAC5C,EAAE,EAAE,IAAI;YACR,OAAO,EAAE,OAAO;YAChB,UAAU,EAAE,GAAG;YACf,WAAW,EAAE,gBAAgB;YAC7B,OAAO,EAAE,GAAG;YACZ,MAAM,EAAE,WAAW;YACnB,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,QAAQ,CAAC;SACjD,CAAC,CAAC;QACH,MAAM,aAAa,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC7B,MAAM,IAAI,GAAG,MAAO,EAAU,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC3D,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sso-events.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/audit/sso-events.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { dashboardLoginEvent, dashboardLogoutEvent, dashboardLoginDeniedEvent, } from "../../audit/events.js";
|
|
3
|
+
describe("SSO audit event builders", () => {
|
|
4
|
+
describe("dashboardLoginEvent", () => {
|
|
5
|
+
it("builds a dashboard.login event with user details in payload", () => {
|
|
6
|
+
const evt = dashboardLoginEvent({
|
|
7
|
+
userId: "user_123",
|
|
8
|
+
email: "alice@example.com",
|
|
9
|
+
workosUserId: "workos_abc",
|
|
10
|
+
});
|
|
11
|
+
expect(evt.eventType).toBe("dashboard.login");
|
|
12
|
+
expect(evt.actorType).toBe("dashboard-user");
|
|
13
|
+
expect(evt.actor).toBe("dashboard:alice@example.com");
|
|
14
|
+
expect(evt.payload).toEqual({
|
|
15
|
+
userId: "user_123",
|
|
16
|
+
email: "alice@example.com",
|
|
17
|
+
workosUserId: "workos_abc",
|
|
18
|
+
});
|
|
19
|
+
expect(evt.id).toMatch(/^evt_/);
|
|
20
|
+
expect(evt.timestamp).toBeInstanceOf(Date);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
describe("dashboardLogoutEvent", () => {
|
|
24
|
+
it("builds a dashboard.logout event with userId in payload", () => {
|
|
25
|
+
const evt = dashboardLogoutEvent({
|
|
26
|
+
userId: "user_123",
|
|
27
|
+
email: "alice@example.com",
|
|
28
|
+
});
|
|
29
|
+
expect(evt.eventType).toBe("dashboard.logout");
|
|
30
|
+
expect(evt.actorType).toBe("dashboard-user");
|
|
31
|
+
expect(evt.actor).toBe("dashboard:alice@example.com");
|
|
32
|
+
expect(evt.payload).toEqual({ userId: "user_123" });
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
describe("dashboardLoginDeniedEvent", () => {
|
|
36
|
+
it("builds a dashboard.login_denied event without userId", () => {
|
|
37
|
+
const evt = dashboardLoginDeniedEvent({
|
|
38
|
+
email: "intruder@evil.example",
|
|
39
|
+
reason: "domain-mismatch",
|
|
40
|
+
});
|
|
41
|
+
expect(evt.eventType).toBe("dashboard.login_denied");
|
|
42
|
+
expect(evt.actorType).toBe("dashboard-user");
|
|
43
|
+
expect(evt.actor).toBe("dashboard:intruder@evil.example");
|
|
44
|
+
expect(evt.payload).toEqual({ reason: "domain-mismatch" });
|
|
45
|
+
expect(evt.payload).not.toHaveProperty("userId");
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
//# sourceMappingURL=sso-events.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sso-events.test.js","sourceRoot":"","sources":["../../../src/__tests__/audit/sso-events.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC;AAE/B,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;QACnC,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;YACrE,MAAM,GAAG,GAAG,mBAAmB,CAAC;gBAC9B,MAAM,EAAE,UAAU;gBAClB,KAAK,EAAE,mBAAmB;gBAC1B,YAAY,EAAE,YAAY;aAC3B,CAAC,CAAC;YAEH,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAC9C,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAC7C,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;YACtD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;gBAC1B,MAAM,EAAE,UAAU;gBAClB,KAAK,EAAE,mBAAmB;gBAC1B,YAAY,EAAE,YAAY;aAC3B,CAAC,CAAC;YACH,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAChC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACpC,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;YAChE,MAAM,GAAG,GAAG,oBAAoB,CAAC;gBAC/B,MAAM,EAAE,UAAU;gBAClB,KAAK,EAAE,mBAAmB;aAC3B,CAAC,CAAC;YAEH,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;YAC/C,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAC7C,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;YACtD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACzC,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;YAC9D,MAAM,GAAG,GAAG,yBAAyB,CAAC;gBACpC,KAAK,EAAE,uBAAuB;gBAC9B,MAAM,EAAE,iBAAiB;aAC1B,CAAC,CAAC;YAEH,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;YACrD,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAC7C,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;YAC1D,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;YAC3D,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writer.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/audit/writer.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { createDb } from "../../db/client.js";
|
|
3
|
+
import { auditEvents } from "../../db/schema.js";
|
|
4
|
+
import { logAuditEvent } from "../../audit/writer.js";
|
|
5
|
+
import { pmPromotedEvent } from "../../audit/events.js";
|
|
6
|
+
import { installTestProLicense, restoreLicense } from "../helpers/license.js";
|
|
7
|
+
import { _resetLicenseCache } from "../../license.js";
|
|
8
|
+
describe("logAuditEvent", () => {
|
|
9
|
+
describe("with enterprise license", () => {
|
|
10
|
+
beforeEach(async () => {
|
|
11
|
+
await installTestProLicense("enterprise");
|
|
12
|
+
});
|
|
13
|
+
afterEach(async () => {
|
|
14
|
+
await restoreLicense();
|
|
15
|
+
});
|
|
16
|
+
it("persists an event row", async () => {
|
|
17
|
+
const db = await createDb({ connectionString: ":memory:" });
|
|
18
|
+
await logAuditEvent(db, pmPromotedEvent({
|
|
19
|
+
issueId: "BEC-1",
|
|
20
|
+
fromState: "Backlog",
|
|
21
|
+
toState: "Todo",
|
|
22
|
+
}));
|
|
23
|
+
const rows = await db.select().from(auditEvents);
|
|
24
|
+
expect(rows).toHaveLength(1);
|
|
25
|
+
expect(rows[0].eventType).toBe("pm.issue_promoted");
|
|
26
|
+
expect(JSON.parse(rows[0].payload)).toMatchObject({
|
|
27
|
+
fromState: "Backlog",
|
|
28
|
+
toState: "Todo",
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
it("does not throw when the db insert fails", async () => {
|
|
32
|
+
const fakeDb = {
|
|
33
|
+
insert: () => ({
|
|
34
|
+
values: () => {
|
|
35
|
+
throw new Error("db down");
|
|
36
|
+
},
|
|
37
|
+
}),
|
|
38
|
+
};
|
|
39
|
+
await expect(logAuditEvent(fakeDb, pmPromotedEvent({
|
|
40
|
+
issueId: "BEC-1",
|
|
41
|
+
fromState: "Backlog",
|
|
42
|
+
toState: "Todo",
|
|
43
|
+
}))).resolves.toBeUndefined();
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
describe("without a license (OSS mode)", () => {
|
|
47
|
+
beforeEach(() => {
|
|
48
|
+
_resetLicenseCache();
|
|
49
|
+
delete process.env.URATEAM_LICENSE_KEY;
|
|
50
|
+
});
|
|
51
|
+
afterEach(() => {
|
|
52
|
+
_resetLicenseCache();
|
|
53
|
+
delete process.env.URATEAM_LICENSE_KEY;
|
|
54
|
+
});
|
|
55
|
+
it("is a no-op when the audit-log feature is not licensed", async () => {
|
|
56
|
+
const db = await createDb({ connectionString: ":memory:" });
|
|
57
|
+
await logAuditEvent(db, pmPromotedEvent({
|
|
58
|
+
issueId: "BEC-1",
|
|
59
|
+
fromState: "Backlog",
|
|
60
|
+
toState: "Todo",
|
|
61
|
+
}));
|
|
62
|
+
const rows = await db.select().from(auditEvents);
|
|
63
|
+
expect(rows).toHaveLength(0);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
//# sourceMappingURL=writer.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writer.test.js","sourceRoot":"","sources":["../../../src/__tests__/audit/writer.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-immutability.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/audit-immutability.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audit log immutability lint test.
|
|
3
|
+
*
|
|
4
|
+
* The audit_events table is append-only by design. Only the retention sweep
|
|
5
|
+
* (`audit/retention.ts`) may delete rows, and nothing should ever update them.
|
|
6
|
+
*
|
|
7
|
+
* This test greps the source tree for `.delete(auditEvents)` / `.update(auditEvents)`
|
|
8
|
+
* calls and fails if any non-allowlisted file is found.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, it, expect } from "vitest";
|
|
11
|
+
import { execFileSync } from "node:child_process";
|
|
12
|
+
import path from "node:path";
|
|
13
|
+
describe("audit_events immutability", () => {
|
|
14
|
+
it("only audit/retention.ts may delete or update audit_events rows", () => {
|
|
15
|
+
const repoRoot = path.resolve(__dirname, "../../../..");
|
|
16
|
+
const allowed = [
|
|
17
|
+
"packages/core/src/audit/retention.ts",
|
|
18
|
+
"packages/core/src/__tests__/audit/retention.test.ts",
|
|
19
|
+
"packages/core/src/__tests__/audit-immutability.test.ts",
|
|
20
|
+
];
|
|
21
|
+
const patterns = [
|
|
22
|
+
"\\.delete\\s*\\(\\s*auditEvents",
|
|
23
|
+
"\\.update\\s*\\(\\s*auditEvents",
|
|
24
|
+
];
|
|
25
|
+
const matches = [];
|
|
26
|
+
for (const pat of patterns) {
|
|
27
|
+
try {
|
|
28
|
+
const out = execFileSync("git", ["grep", "-nE", pat, "--", "packages/**/*.ts"], { cwd: repoRoot, encoding: "utf8" });
|
|
29
|
+
matches.push(...out.trim().split("\n").filter(Boolean));
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// git grep exits non-zero when no matches; safe to ignore
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const offenders = matches
|
|
36
|
+
.map((line) => line.split(":")[0])
|
|
37
|
+
.filter((file) => !allowed.some((a) => file.endsWith(a) || file === a));
|
|
38
|
+
expect(offenders, `Unauthorized audit_events mutation in:\n${offenders.join("\n")}`).toEqual([]);
|
|
39
|
+
});
|
|
40
|
+
it("logAuditEventUnchecked is only called from license.ts", () => {
|
|
41
|
+
const repoRoot = path.resolve(__dirname, "../../../..");
|
|
42
|
+
const allowed = [
|
|
43
|
+
"packages/core/src/audit/writer.ts",
|
|
44
|
+
"packages/core/src/license.ts",
|
|
45
|
+
"packages/core/src/__tests__/audit-immutability.test.ts",
|
|
46
|
+
];
|
|
47
|
+
let matches = [];
|
|
48
|
+
try {
|
|
49
|
+
const out = execFileSync("git", ["grep", "-nE", "logAuditEventUnchecked", "--", "packages/**/*.ts"], { cwd: repoRoot, encoding: "utf8" });
|
|
50
|
+
matches = out.trim().split("\n").filter(Boolean);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// no matches
|
|
54
|
+
}
|
|
55
|
+
const offenders = matches
|
|
56
|
+
.map((line) => line.split(":")[0])
|
|
57
|
+
.filter((file) => !allowed.some((a) => file.endsWith(a) || file === a));
|
|
58
|
+
expect(offenders, `Unauthorized logAuditEventUnchecked usage in:\n${offenders.join("\n")}`).toEqual([]);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
//# sourceMappingURL=audit-immutability.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-immutability.test.js","sourceRoot":"","sources":["../../src/__tests__/audit-immutability.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-types.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/audit-types.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { AuditEventSchema, AuditEventTypeSchema } from "../types.js";
|
|
3
|
+
describe("audit event zod schemas", () => {
|
|
4
|
+
it("accepts all v1 event types", () => {
|
|
5
|
+
const types = [
|
|
6
|
+
"run.started", "run.completed", "run.failed", "run.auto_merged", "run.auto_merge_skipped",
|
|
7
|
+
"pm.approval_requested", "pm.approval_resolved",
|
|
8
|
+
"pm.issue_promoted", "pm.issue_deprioritized", "pm.issue_cancelled", "pm.triage_classified",
|
|
9
|
+
"budget.alert_fired", "budget.run_refused",
|
|
10
|
+
"license.validation_failed", "config.loaded", "dashboard.manual_action",
|
|
11
|
+
];
|
|
12
|
+
for (const t of types)
|
|
13
|
+
expect(AuditEventTypeSchema.parse(t)).toBe(t);
|
|
14
|
+
});
|
|
15
|
+
it("rejects unknown event type", () => {
|
|
16
|
+
expect(() => AuditEventTypeSchema.parse("nope")).toThrow();
|
|
17
|
+
});
|
|
18
|
+
it("parses a minimal valid audit event", () => {
|
|
19
|
+
const evt = AuditEventSchema.parse({
|
|
20
|
+
id: "evt_1",
|
|
21
|
+
timestamp: new Date(),
|
|
22
|
+
eventType: "pm.issue_promoted",
|
|
23
|
+
actor: "pm-agent",
|
|
24
|
+
actorType: "pm-agent",
|
|
25
|
+
scope: null,
|
|
26
|
+
runId: null,
|
|
27
|
+
issueId: "BEC-1",
|
|
28
|
+
inputTokens: 0,
|
|
29
|
+
outputTokens: 0,
|
|
30
|
+
payload: { issueId: "BEC-1" },
|
|
31
|
+
});
|
|
32
|
+
expect(evt.eventType).toBe("pm.issue_promoted");
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
//# sourceMappingURL=audit-types.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-types.test.js","sourceRoot":"","sources":["../../src/__tests__/audit-types.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAwB,MAAM,aAAa,CAAC;AAE3F,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,KAAK,GAAG;YACZ,aAAa,EAAC,eAAe,EAAC,YAAY,EAAC,iBAAiB,EAAC,wBAAwB;YACrF,uBAAuB,EAAC,sBAAsB;YAC9C,mBAAmB,EAAC,wBAAwB,EAAC,oBAAoB,EAAC,sBAAsB;YACxF,oBAAoB,EAAC,oBAAoB;YACzC,2BAA2B,EAAC,eAAe,EAAC,yBAAyB;SACtE,CAAC;QACF,KAAK,MAAM,CAAC,IAAI,KAAK;YAAE,MAAM,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,GAAG,EAAE,CAAC,oBAAoB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,GAAG,GAAG,gBAAgB,CAAC,KAAK,CAAC;YACjC,EAAE,EAAE,OAAO;YACX,SAAS,EAAE,IAAI,IAAI,EAAE;YACrB,SAAS,EAAE,mBAAmB;YAC9B,KAAK,EAAE,UAAU;YACjB,SAAS,EAAE,UAAU;YACrB,KAAK,EAAE,IAAI;YACX,KAAK,EAAE,IAAI;YACX,OAAO,EAAE,OAAO;YAChB,WAAW,EAAE,CAAC;YACd,YAAY,EAAE,CAAC;YACf,OAAO,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE;SAC9B,CAAC,CAAC;QACH,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-store.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/auth/session-store.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from "vitest";
|
|
2
|
+
import { createDb } from "../../db/client.js";
|
|
3
|
+
import { upsertUser } from "../../auth/user-store.js";
|
|
4
|
+
import { createSession, getSession, deleteSession, pruneExpiredSessions, touchSessionLastSeen, } from "../../auth/session-store.js";
|
|
5
|
+
let db;
|
|
6
|
+
let userId;
|
|
7
|
+
beforeEach(async () => {
|
|
8
|
+
db = await createDb({ connectionString: ":memory:" });
|
|
9
|
+
userId = await upsertUser(db, {
|
|
10
|
+
email: "a@b.com",
|
|
11
|
+
name: "A",
|
|
12
|
+
workosUserId: null,
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
describe("session-store", () => {
|
|
16
|
+
it("creates a session and reads it back", async () => {
|
|
17
|
+
const sid = await createSession(db, { userId, durationHours: 24 });
|
|
18
|
+
expect(sid).toBeTruthy();
|
|
19
|
+
expect(sid.length).toBeGreaterThan(20);
|
|
20
|
+
const s = await getSession(db, sid);
|
|
21
|
+
expect(s?.userId).toBe(userId);
|
|
22
|
+
expect(s?.expiresAt.getTime()).toBeGreaterThan(Date.now());
|
|
23
|
+
});
|
|
24
|
+
it("returns null for unknown session id", async () => {
|
|
25
|
+
expect(await getSession(db, "nope")).toBeNull();
|
|
26
|
+
});
|
|
27
|
+
it("returns null for expired sessions", async () => {
|
|
28
|
+
const sid = await createSession(db, { userId, durationHours: 24 });
|
|
29
|
+
await deleteSession(db, sid);
|
|
30
|
+
const { dashboardSessions } = await import("../../db/schema.js");
|
|
31
|
+
await db.insert(dashboardSessions).values({
|
|
32
|
+
id: sid,
|
|
33
|
+
userId,
|
|
34
|
+
expiresAt: new Date(Date.now() - 1000),
|
|
35
|
+
});
|
|
36
|
+
expect(await getSession(db, sid)).toBeNull();
|
|
37
|
+
});
|
|
38
|
+
it("deleteSession removes the row", async () => {
|
|
39
|
+
const sid = await createSession(db, { userId, durationHours: 24 });
|
|
40
|
+
await deleteSession(db, sid);
|
|
41
|
+
expect(await getSession(db, sid)).toBeNull();
|
|
42
|
+
});
|
|
43
|
+
it("pruneExpiredSessions removes only expired rows", async () => {
|
|
44
|
+
const live = await createSession(db, { userId, durationHours: 24 });
|
|
45
|
+
const dead = "sess_dead";
|
|
46
|
+
const { dashboardSessions } = await import("../../db/schema.js");
|
|
47
|
+
await db.insert(dashboardSessions).values({
|
|
48
|
+
id: dead,
|
|
49
|
+
userId,
|
|
50
|
+
expiresAt: new Date(Date.now() - 1000),
|
|
51
|
+
});
|
|
52
|
+
const deleted = await pruneExpiredSessions(db);
|
|
53
|
+
expect(deleted).toBe(1);
|
|
54
|
+
expect(await getSession(db, live)).not.toBeNull();
|
|
55
|
+
});
|
|
56
|
+
it("touchSessionLastSeen updates lastSeenAt", async () => {
|
|
57
|
+
const sid = await createSession(db, { userId, durationHours: 24 });
|
|
58
|
+
const before = (await getSession(db, sid)).lastSeenAt;
|
|
59
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
60
|
+
await touchSessionLastSeen(db, sid);
|
|
61
|
+
const after = (await getSession(db, sid)).lastSeenAt;
|
|
62
|
+
expect(after.getTime()).toBeGreaterThanOrEqual(before.getTime());
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=session-store.test.js.map
|