wood-fired-tasks 1.12.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/AGENTS.md +112 -0
- package/CHANGELOG.md +271 -0
- package/CLAUDE.md +21 -0
- package/LICENSE +21 -0
- package/README.md +687 -0
- package/SECURITY.md +299 -0
- package/dist/api/hooks/error-handler.d.ts +6 -0
- package/dist/api/hooks/error-handler.js +128 -0
- package/dist/api/hooks/error-handler.js.map +1 -0
- package/dist/api/plugins/auth/index.d.ts +78 -0
- package/dist/api/plugins/auth/index.js +300 -0
- package/dist/api/plugins/auth/index.js.map +1 -0
- package/dist/api/plugins/auth/keys.d.ts +23 -0
- package/dist/api/plugins/auth/keys.js +100 -0
- package/dist/api/plugins/auth/keys.js.map +1 -0
- package/dist/api/plugins/auth/strategies/legacy.d.ts +46 -0
- package/dist/api/plugins/auth/strategies/legacy.js +87 -0
- package/dist/api/plugins/auth/strategies/legacy.js.map +1 -0
- package/dist/api/plugins/auth/strategies/pat.d.ts +37 -0
- package/dist/api/plugins/auth/strategies/pat.js +99 -0
- package/dist/api/plugins/auth/strategies/pat.js.map +1 -0
- package/dist/api/plugins/auth/strategies/session.d.ts +37 -0
- package/dist/api/plugins/auth/strategies/session.js +30 -0
- package/dist/api/plugins/auth/strategies/session.js.map +1 -0
- package/dist/api/plugins/auth/strategies/types.d.ts +12 -0
- package/dist/api/plugins/auth/strategies/types.js +2 -0
- package/dist/api/plugins/auth/strategies/types.js.map +1 -0
- package/dist/api/plugins/auth.d.ts +29 -0
- package/dist/api/plugins/auth.js +30 -0
- package/dist/api/plugins/auth.js.map +1 -0
- package/dist/api/plugins/swagger.d.ts +31 -0
- package/dist/api/plugins/swagger.js +83 -0
- package/dist/api/plugins/swagger.js.map +1 -0
- package/dist/api/routes/auth/auth-error.d.ts +23 -0
- package/dist/api/routes/auth/auth-error.js +68 -0
- package/dist/api/routes/auth/auth-error.js.map +1 -0
- package/dist/api/routes/auth/callback.d.ts +44 -0
- package/dist/api/routes/auth/callback.js +175 -0
- package/dist/api/routes/auth/callback.js.map +1 -0
- package/dist/api/routes/auth/csrf.d.ts +24 -0
- package/dist/api/routes/auth/csrf.js +75 -0
- package/dist/api/routes/auth/csrf.js.map +1 -0
- package/dist/api/routes/auth/device-code.d.ts +41 -0
- package/dist/api/routes/auth/device-code.js +51 -0
- package/dist/api/routes/auth/device-code.js.map +1 -0
- package/dist/api/routes/auth/device-disabled-stub.d.ts +33 -0
- package/dist/api/routes/auth/device-disabled-stub.js +16 -0
- package/dist/api/routes/auth/device-disabled-stub.js.map +1 -0
- package/dist/api/routes/auth/device-html.d.ts +41 -0
- package/dist/api/routes/auth/device-html.js +243 -0
- package/dist/api/routes/auth/device-html.js.map +1 -0
- package/dist/api/routes/auth/device-token.d.ts +38 -0
- package/dist/api/routes/auth/device-token.js +153 -0
- package/dist/api/routes/auth/device-token.js.map +1 -0
- package/dist/api/routes/auth/disabled-stub.d.ts +31 -0
- package/dist/api/routes/auth/disabled-stub.js +21 -0
- package/dist/api/routes/auth/disabled-stub.js.map +1 -0
- package/dist/api/routes/auth/index.d.ts +65 -0
- package/dist/api/routes/auth/index.js +47 -0
- package/dist/api/routes/auth/index.js.map +1 -0
- package/dist/api/routes/auth/login.d.ts +27 -0
- package/dist/api/routes/auth/login.js +91 -0
- package/dist/api/routes/auth/login.js.map +1 -0
- package/dist/api/routes/auth/logout.d.ts +29 -0
- package/dist/api/routes/auth/logout.js +43 -0
- package/dist/api/routes/auth/logout.js.map +1 -0
- package/dist/api/routes/comments/index.d.ts +3 -0
- package/dist/api/routes/comments/index.js +74 -0
- package/dist/api/routes/comments/index.js.map +1 -0
- package/dist/api/routes/comments/schemas.d.ts +37 -0
- package/dist/api/routes/comments/schemas.js +24 -0
- package/dist/api/routes/comments/schemas.js.map +1 -0
- package/dist/api/routes/dependencies/index.d.ts +3 -0
- package/dist/api/routes/dependencies/index.js +60 -0
- package/dist/api/routes/dependencies/index.js.map +1 -0
- package/dist/api/routes/dependencies/schemas.d.ts +24 -0
- package/dist/api/routes/dependencies/schemas.js +15 -0
- package/dist/api/routes/dependencies/schemas.js.map +1 -0
- package/dist/api/routes/events.d.ts +3 -0
- package/dist/api/routes/events.js +157 -0
- package/dist/api/routes/events.js.map +1 -0
- package/dist/api/routes/health.d.ts +27 -0
- package/dist/api/routes/health.js +231 -0
- package/dist/api/routes/health.js.map +1 -0
- package/dist/api/routes/me/index.d.ts +3 -0
- package/dist/api/routes/me/index.js +8 -0
- package/dist/api/routes/me/index.js.map +1 -0
- package/dist/api/routes/me/profile.d.ts +3 -0
- package/dist/api/routes/me/profile.js +58 -0
- package/dist/api/routes/me/profile.js.map +1 -0
- package/dist/api/routes/me/tokens.d.ts +3 -0
- package/dist/api/routes/me/tokens.js +410 -0
- package/dist/api/routes/me/tokens.js.map +1 -0
- package/dist/api/routes/projects/dependency-graph.d.ts +26 -0
- package/dist/api/routes/projects/dependency-graph.js +56 -0
- package/dist/api/routes/projects/dependency-graph.js.map +1 -0
- package/dist/api/routes/projects/index.d.ts +3 -0
- package/dist/api/routes/projects/index.js +96 -0
- package/dist/api/routes/projects/index.js.map +1 -0
- package/dist/api/routes/projects/schemas.d.ts +37 -0
- package/dist/api/routes/projects/schemas.js +27 -0
- package/dist/api/routes/projects/schemas.js.map +1 -0
- package/dist/api/routes/projects/topology.d.ts +27 -0
- package/dist/api/routes/projects/topology.js +51 -0
- package/dist/api/routes/projects/topology.js.map +1 -0
- package/dist/api/routes/tasks/index.d.ts +3 -0
- package/dist/api/routes/tasks/index.js +330 -0
- package/dist/api/routes/tasks/index.js.map +1 -0
- package/dist/api/routes/tasks/schemas.d.ts +316 -0
- package/dist/api/routes/tasks/schemas.js +129 -0
- package/dist/api/routes/tasks/schemas.js.map +1 -0
- package/dist/api/routes/web/index.d.ts +23 -0
- package/dist/api/routes/web/index.js +30 -0
- package/dist/api/routes/web/index.js.map +1 -0
- package/dist/api/routes/web/login.d.ts +20 -0
- package/dist/api/routes/web/login.js +20 -0
- package/dist/api/routes/web/login.js.map +1 -0
- package/dist/api/routes/web/me.d.ts +23 -0
- package/dist/api/routes/web/me.js +31 -0
- package/dist/api/routes/web/me.js.map +1 -0
- package/dist/api/routes/web/tokens.d.ts +29 -0
- package/dist/api/routes/web/tokens.js +65 -0
- package/dist/api/routes/web/tokens.js.map +1 -0
- package/dist/api/server.d.ts +44 -0
- package/dist/api/server.js +521 -0
- package/dist/api/server.js.map +1 -0
- package/dist/api/start.d.ts +1 -0
- package/dist/api/start.js +79 -0
- package/dist/api/start.js.map +1 -0
- package/dist/cli/api/client.d.ts +126 -0
- package/dist/cli/api/client.js +408 -0
- package/dist/cli/api/client.js.map +1 -0
- package/dist/cli/api/errors.d.ts +16 -0
- package/dist/cli/api/errors.js +20 -0
- package/dist/cli/api/errors.js.map +1 -0
- package/dist/cli/api/types.d.ts +205 -0
- package/dist/cli/api/types.js +15 -0
- package/dist/cli/api/types.js.map +1 -0
- package/dist/cli/auth/browser-open.d.ts +1 -0
- package/dist/cli/auth/browser-open.js +116 -0
- package/dist/cli/auth/browser-open.js.map +1 -0
- package/dist/cli/auth/credentials.d.ts +27 -0
- package/dist/cli/auth/credentials.js +179 -0
- package/dist/cli/auth/credentials.js.map +1 -0
- package/dist/cli/auth/device-flow.d.ts +75 -0
- package/dist/cli/auth/device-flow.js +149 -0
- package/dist/cli/auth/device-flow.js.map +1 -0
- package/dist/cli/bin/tasks-client.d.ts +2 -0
- package/dist/cli/bin/tasks-client.js +86 -0
- package/dist/cli/bin/tasks-client.js.map +1 -0
- package/dist/cli/bin/tasks.d.ts +3 -0
- package/dist/cli/bin/tasks.js +127 -0
- package/dist/cli/bin/tasks.js.map +1 -0
- package/dist/cli/commands/backup.d.ts +3 -0
- package/dist/cli/commands/backup.js +65 -0
- package/dist/cli/commands/backup.js.map +1 -0
- package/dist/cli/commands/claim.d.ts +2 -0
- package/dist/cli/commands/claim.js +37 -0
- package/dist/cli/commands/claim.js.map +1 -0
- package/dist/cli/commands/comment-add.d.ts +2 -0
- package/dist/cli/commands/comment-add.js +45 -0
- package/dist/cli/commands/comment-add.js.map +1 -0
- package/dist/cli/commands/comment-delete.d.ts +2 -0
- package/dist/cli/commands/comment-delete.js +56 -0
- package/dist/cli/commands/comment-delete.js.map +1 -0
- package/dist/cli/commands/comment-list.d.ts +2 -0
- package/dist/cli/commands/comment-list.js +56 -0
- package/dist/cli/commands/comment-list.js.map +1 -0
- package/dist/cli/commands/completed.d.ts +10 -0
- package/dist/cli/commands/completed.js +168 -0
- package/dist/cli/commands/completed.js.map +1 -0
- package/dist/cli/commands/completions.d.ts +10 -0
- package/dist/cli/commands/completions.js +179 -0
- package/dist/cli/commands/completions.js.map +1 -0
- package/dist/cli/commands/create.d.ts +2 -0
- package/dist/cli/commands/create.js +99 -0
- package/dist/cli/commands/create.js.map +1 -0
- package/dist/cli/commands/db-check.d.ts +3 -0
- package/dist/cli/commands/db-check.js +63 -0
- package/dist/cli/commands/db-check.js.map +1 -0
- package/dist/cli/commands/db-migrate-identities.d.ts +37 -0
- package/dist/cli/commands/db-migrate-identities.js +352 -0
- package/dist/cli/commands/db-migrate-identities.js.map +1 -0
- package/dist/cli/commands/db-mint-token.d.ts +33 -0
- package/dist/cli/commands/db-mint-token.js +150 -0
- package/dist/cli/commands/db-mint-token.js.map +1 -0
- package/dist/cli/commands/db.d.ts +10 -0
- package/dist/cli/commands/db.js +16 -0
- package/dist/cli/commands/db.js.map +1 -0
- package/dist/cli/commands/delete.d.ts +2 -0
- package/dist/cli/commands/delete.js +54 -0
- package/dist/cli/commands/delete.js.map +1 -0
- package/dist/cli/commands/dep-add.d.ts +2 -0
- package/dist/cli/commands/dep-add.js +43 -0
- package/dist/cli/commands/dep-add.js.map +1 -0
- package/dist/cli/commands/dep-list.d.ts +2 -0
- package/dist/cli/commands/dep-list.js +36 -0
- package/dist/cli/commands/dep-list.js.map +1 -0
- package/dist/cli/commands/dep-remove.d.ts +2 -0
- package/dist/cli/commands/dep-remove.js +55 -0
- package/dist/cli/commands/dep-remove.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +3 -0
- package/dist/cli/commands/doctor.js +139 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/health.d.ts +2 -0
- package/dist/cli/commands/health.js +28 -0
- package/dist/cli/commands/health.js.map +1 -0
- package/dist/cli/commands/list.d.ts +2 -0
- package/dist/cli/commands/list.js +103 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/login.d.ts +2 -0
- package/dist/cli/commands/login.js +210 -0
- package/dist/cli/commands/login.js.map +1 -0
- package/dist/cli/commands/logout.d.ts +31 -0
- package/dist/cli/commands/logout.js +184 -0
- package/dist/cli/commands/logout.js.map +1 -0
- package/dist/cli/commands/project-create.d.ts +2 -0
- package/dist/cli/commands/project-create.js +44 -0
- package/dist/cli/commands/project-create.js.map +1 -0
- package/dist/cli/commands/project-delete.d.ts +2 -0
- package/dist/cli/commands/project-delete.js +54 -0
- package/dist/cli/commands/project-delete.js.map +1 -0
- package/dist/cli/commands/project-list.d.ts +2 -0
- package/dist/cli/commands/project-list.js +55 -0
- package/dist/cli/commands/project-list.js.map +1 -0
- package/dist/cli/commands/project-show.d.ts +2 -0
- package/dist/cli/commands/project-show.js +38 -0
- package/dist/cli/commands/project-show.js.map +1 -0
- package/dist/cli/commands/project-update.d.ts +2 -0
- package/dist/cli/commands/project-update.js +56 -0
- package/dist/cli/commands/project-update.js.map +1 -0
- package/dist/cli/commands/show.d.ts +2 -0
- package/dist/cli/commands/show.js +38 -0
- package/dist/cli/commands/show.js.map +1 -0
- package/dist/cli/commands/stats.d.ts +3 -0
- package/dist/cli/commands/stats.js +81 -0
- package/dist/cli/commands/stats.js.map +1 -0
- package/dist/cli/commands/subtask-create.d.ts +2 -0
- package/dist/cli/commands/subtask-create.js +85 -0
- package/dist/cli/commands/subtask-create.js.map +1 -0
- package/dist/cli/commands/subtask-list.d.ts +2 -0
- package/dist/cli/commands/subtask-list.js +61 -0
- package/dist/cli/commands/subtask-list.js.map +1 -0
- package/dist/cli/commands/topology.d.ts +16 -0
- package/dist/cli/commands/topology.js +52 -0
- package/dist/cli/commands/topology.js.map +1 -0
- package/dist/cli/commands/update.d.ts +2 -0
- package/dist/cli/commands/update.js +90 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/commands/whoami.d.ts +30 -0
- package/dist/cli/commands/whoami.js +201 -0
- package/dist/cli/commands/whoami.js.map +1 -0
- package/dist/cli/config/env.d.ts +4 -0
- package/dist/cli/config/env.js +25 -0
- package/dist/cli/config/env.js.map +1 -0
- package/dist/cli/output/error-handler.d.ts +5 -0
- package/dist/cli/output/error-handler.js +41 -0
- package/dist/cli/output/error-handler.js.map +1 -0
- package/dist/cli/output/formatters.d.ts +86 -0
- package/dist/cli/output/formatters.js +352 -0
- package/dist/cli/output/formatters.js.map +1 -0
- package/dist/cli/output/json-output.d.ts +39 -0
- package/dist/cli/output/json-output.js +50 -0
- package/dist/cli/output/json-output.js.map +1 -0
- package/dist/cli/output/spinner.d.ts +14 -0
- package/dist/cli/output/spinner.js +48 -0
- package/dist/cli/output/spinner.js.map +1 -0
- package/dist/cli/prompts/interactive.d.ts +25 -0
- package/dist/cli/prompts/interactive.js +80 -0
- package/dist/cli/prompts/interactive.js.map +1 -0
- package/dist/config/env.d.ts +182 -0
- package/dist/config/env.js +311 -0
- package/dist/config/env.js.map +1 -0
- package/dist/db/database.d.ts +11 -0
- package/dist/db/database.js +25 -0
- package/dist/db/database.js.map +1 -0
- package/dist/db/migrate.d.ts +10 -0
- package/dist/db/migrate.js +137 -0
- package/dist/db/migrate.js.map +1 -0
- package/dist/db/migrations/001-initial-schema.d.ts +3 -0
- package/dist/db/migrations/001-initial-schema.js +100 -0
- package/dist/db/migrations/001-initial-schema.js.map +1 -0
- package/dist/db/migrations/002-task-hierarchy-and-dependencies.d.ts +3 -0
- package/dist/db/migrations/002-task-hierarchy-and-dependencies.js +42 -0
- package/dist/db/migrations/002-task-hierarchy-and-dependencies.js.map +1 -0
- package/dist/db/migrations/003-comments-and-estimates.d.ts +3 -0
- package/dist/db/migrations/003-comments-and-estimates.js +36 -0
- package/dist/db/migrations/003-comments-and-estimates.js.map +1 -0
- package/dist/db/migrations/004-claim-protocol.d.ts +3 -0
- package/dist/db/migrations/004-claim-protocol.js +41 -0
- package/dist/db/migrations/004-claim-protocol.js.map +1 -0
- package/dist/db/migrations/005-backlogged-status.d.ts +3 -0
- package/dist/db/migrations/005-backlogged-status.js +156 -0
- package/dist/db/migrations/005-backlogged-status.js.map +1 -0
- package/dist/db/migrations/006-slack-channel-subscriptions.d.ts +3 -0
- package/dist/db/migrations/006-slack-channel-subscriptions.js +23 -0
- package/dist/db/migrations/006-slack-channel-subscriptions.js.map +1 -0
- package/dist/db/migrations/007-completed-at.d.ts +19 -0
- package/dist/db/migrations/007-completed-at.js +36 -0
- package/dist/db/migrations/007-completed-at.js.map +1 -0
- package/dist/db/migrations/008-identity-tables.d.ts +21 -0
- package/dist/db/migrations/008-identity-tables.js +84 -0
- package/dist/db/migrations/008-identity-tables.js.map +1 -0
- package/dist/db/migrations/009-parallel-fk-columns.d.ts +33 -0
- package/dist/db/migrations/009-parallel-fk-columns.js +62 -0
- package/dist/db/migrations/009-parallel-fk-columns.js.map +1 -0
- package/dist/db/migrations/010-identity-uniqueness-indexes.d.ts +47 -0
- package/dist/db/migrations/010-identity-uniqueness-indexes.js +65 -0
- package/dist/db/migrations/010-identity-uniqueness-indexes.js.map +1 -0
- package/dist/db/migrations/011-acceptance-criteria.d.ts +30 -0
- package/dist/db/migrations/011-acceptance-criteria.js +41 -0
- package/dist/db/migrations/011-acceptance-criteria.js.map +1 -0
- package/dist/db/migrations/012-verification-evidence.d.ts +41 -0
- package/dist/db/migrations/012-verification-evidence.js +49 -0
- package/dist/db/migrations/012-verification-evidence.js.map +1 -0
- package/dist/events/event-bus.d.ts +101 -0
- package/dist/events/event-bus.js +184 -0
- package/dist/events/event-bus.js.map +1 -0
- package/dist/events/sse-manager.d.ts +79 -0
- package/dist/events/sse-manager.js +220 -0
- package/dist/events/sse-manager.js.map +1 -0
- package/dist/events/types.d.ts +43 -0
- package/dist/events/types.js +22 -0
- package/dist/events/types.js.map +1 -0
- package/dist/index.d.ts +110 -0
- package/dist/index.js +209 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/audit/schema.d.ts +201 -0
- package/dist/lib/audit/schema.js +141 -0
- package/dist/lib/audit/schema.js.map +1 -0
- package/dist/lib/decompose/schema.d.ts +157 -0
- package/dist/lib/decompose/schema.js +138 -0
- package/dist/lib/decompose/schema.js.map +1 -0
- package/dist/lib/loop-run/integration-audit-schema.d.ts +78 -0
- package/dist/lib/loop-run/integration-audit-schema.js +68 -0
- package/dist/lib/loop-run/integration-audit-schema.js.map +1 -0
- package/dist/lib/loop-run/schema.d.ts +49 -0
- package/dist/lib/loop-run/schema.js +67 -0
- package/dist/lib/loop-run/schema.js.map +1 -0
- package/dist/mcp/errors.d.ts +11 -0
- package/dist/mcp/errors.js +29 -0
- package/dist/mcp/errors.js.map +1 -0
- package/dist/mcp/identity-resolution.d.ts +76 -0
- package/dist/mcp/identity-resolution.js +189 -0
- package/dist/mcp/identity-resolution.js.map +1 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.js +126 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/remote/index.d.ts +21 -0
- package/dist/mcp/remote/index.js +95 -0
- package/dist/mcp/remote/index.js.map +1 -0
- package/dist/mcp/remote/register-tools.d.ts +26 -0
- package/dist/mcp/remote/register-tools.js +751 -0
- package/dist/mcp/remote/register-tools.js.map +1 -0
- package/dist/mcp/remote/rest-client.d.ts +66 -0
- package/dist/mcp/remote/rest-client.js +300 -0
- package/dist/mcp/remote/rest-client.js.map +1 -0
- package/dist/mcp/resources/events.d.ts +28 -0
- package/dist/mcp/resources/events.js +98 -0
- package/dist/mcp/resources/events.js.map +1 -0
- package/dist/mcp/server.d.ts +59 -0
- package/dist/mcp/server.js +72 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/comment-tools.d.ts +12 -0
- package/dist/mcp/tools/comment-tools.js +115 -0
- package/dist/mcp/tools/comment-tools.js.map +1 -0
- package/dist/mcp/tools/dependency-tools.d.ts +3 -0
- package/dist/mcp/tools/dependency-tools.js +91 -0
- package/dist/mcp/tools/dependency-tools.js.map +1 -0
- package/dist/mcp/tools/health-tools.d.ts +9 -0
- package/dist/mcp/tools/health-tools.js +82 -0
- package/dist/mcp/tools/health-tools.js.map +1 -0
- package/dist/mcp/tools/project-tools.d.ts +13 -0
- package/dist/mcp/tools/project-tools.js +167 -0
- package/dist/mcp/tools/project-tools.js.map +1 -0
- package/dist/mcp/tools/task-tools.d.ts +41 -0
- package/dist/mcp/tools/task-tools.js +434 -0
- package/dist/mcp/tools/task-tools.js.map +1 -0
- package/dist/mcp/tools/topology-tools.d.ts +14 -0
- package/dist/mcp/tools/topology-tools.js +46 -0
- package/dist/mcp/tools/topology-tools.js.map +1 -0
- package/dist/repositories/api-token.repository.d.ts +40 -0
- package/dist/repositories/api-token.repository.js +63 -0
- package/dist/repositories/api-token.repository.js.map +1 -0
- package/dist/repositories/comment.repository.d.ts +17 -0
- package/dist/repositories/comment.repository.js +73 -0
- package/dist/repositories/comment.repository.js.map +1 -0
- package/dist/repositories/dependency.repository.d.ts +19 -0
- package/dist/repositories/dependency.repository.js +55 -0
- package/dist/repositories/dependency.repository.js.map +1 -0
- package/dist/repositories/errors.d.ts +29 -0
- package/dist/repositories/errors.js +48 -0
- package/dist/repositories/errors.js.map +1 -0
- package/dist/repositories/interfaces.d.ts +200 -0
- package/dist/repositories/interfaces.js +2 -0
- package/dist/repositories/interfaces.js.map +1 -0
- package/dist/repositories/project.repository.d.ts +21 -0
- package/dist/repositories/project.repository.js +97 -0
- package/dist/repositories/project.repository.js.map +1 -0
- package/dist/repositories/row-mapper.d.ts +40 -0
- package/dist/repositories/row-mapper.js +38 -0
- package/dist/repositories/row-mapper.js.map +1 -0
- package/dist/repositories/task.repository.d.ts +45 -0
- package/dist/repositories/task.repository.js +612 -0
- package/dist/repositories/task.repository.js.map +1 -0
- package/dist/repositories/types.d.ts +20 -0
- package/dist/repositories/types.js +11 -0
- package/dist/repositories/types.js.map +1 -0
- package/dist/repositories/user.repository.d.ts +121 -0
- package/dist/repositories/user.repository.js +209 -0
- package/dist/repositories/user.repository.js.map +1 -0
- package/dist/schemas/comment.schema.d.ts +24 -0
- package/dist/schemas/comment.schema.js +27 -0
- package/dist/schemas/comment.schema.js.map +1 -0
- package/dist/schemas/dependency-graph.schema.d.ts +181 -0
- package/dist/schemas/dependency-graph.schema.js +98 -0
- package/dist/schemas/dependency-graph.schema.js.map +1 -0
- package/dist/schemas/dependency.schema.d.ts +9 -0
- package/dist/schemas/dependency.schema.js +16 -0
- package/dist/schemas/dependency.schema.js.map +1 -0
- package/dist/schemas/idempotency.schema.d.ts +18 -0
- package/dist/schemas/idempotency.schema.js +22 -0
- package/dist/schemas/idempotency.schema.js.map +1 -0
- package/dist/schemas/task.schema.d.ts +369 -0
- package/dist/schemas/task.schema.js +276 -0
- package/dist/schemas/task.schema.js.map +1 -0
- package/dist/schemas/topology.schema.d.ts +56 -0
- package/dist/schemas/topology.schema.js +48 -0
- package/dist/schemas/topology.schema.js.map +1 -0
- package/dist/services/auth-audit.d.ts +46 -0
- package/dist/services/auth-audit.js +28 -0
- package/dist/services/auth-audit.js.map +1 -0
- package/dist/services/claim-release.service.d.ts +42 -0
- package/dist/services/claim-release.service.js +90 -0
- package/dist/services/claim-release.service.js.map +1 -0
- package/dist/services/comment.service.d.ts +44 -0
- package/dist/services/comment.service.js +96 -0
- package/dist/services/comment.service.js.map +1 -0
- package/dist/services/dependency-graph.service.d.ts +33 -0
- package/dist/services/dependency-graph.service.js +453 -0
- package/dist/services/dependency-graph.service.js.map +1 -0
- package/dist/services/dependency.service.d.ts +32 -0
- package/dist/services/dependency.service.js +79 -0
- package/dist/services/dependency.service.js.map +1 -0
- package/dist/services/device-flow-store.d.ts +155 -0
- package/dist/services/device-flow-store.js +323 -0
- package/dist/services/device-flow-store.js.map +1 -0
- package/dist/services/errors.d.ts +28 -0
- package/dist/services/errors.js +44 -0
- package/dist/services/errors.js.map +1 -0
- package/dist/services/idempotency.service.d.ts +37 -0
- package/dist/services/idempotency.service.js +54 -0
- package/dist/services/idempotency.service.js.map +1 -0
- package/dist/services/identity-seeder.d.ts +56 -0
- package/dist/services/identity-seeder.js +131 -0
- package/dist/services/identity-seeder.js.map +1 -0
- package/dist/services/oidc-boot.d.ts +73 -0
- package/dist/services/oidc-boot.js +66 -0
- package/dist/services/oidc-boot.js.map +1 -0
- package/dist/services/oidc-client.d.ts +99 -0
- package/dist/services/oidc-client.js +108 -0
- package/dist/services/oidc-client.js.map +1 -0
- package/dist/services/pat-hash.d.ts +23 -0
- package/dist/services/pat-hash.js +73 -0
- package/dist/services/pat-hash.js.map +1 -0
- package/dist/services/pat-touch-debounce.d.ts +65 -0
- package/dist/services/pat-touch-debounce.js +82 -0
- package/dist/services/pat-touch-debounce.js.map +1 -0
- package/dist/services/project.service.d.ts +41 -0
- package/dist/services/project.service.js +133 -0
- package/dist/services/project.service.js.map +1 -0
- package/dist/services/slack.service.d.ts +31 -0
- package/dist/services/slack.service.js +52 -0
- package/dist/services/slack.service.js.map +1 -0
- package/dist/services/task.service.d.ts +151 -0
- package/dist/services/task.service.js +425 -0
- package/dist/services/task.service.js.map +1 -0
- package/dist/services/topology.service.d.ts +65 -0
- package/dist/services/topology.service.js +170 -0
- package/dist/services/topology.service.js.map +1 -0
- package/dist/services/user-upsert.d.ts +43 -0
- package/dist/services/user-upsert.js +53 -0
- package/dist/services/user-upsert.js.map +1 -0
- package/dist/services/workflow-engine.d.ts +93 -0
- package/dist/services/workflow-engine.js +250 -0
- package/dist/services/workflow-engine.js.map +1 -0
- package/dist/slack/commands/tasks-command.d.ts +88 -0
- package/dist/slack/commands/tasks-command.js +920 -0
- package/dist/slack/commands/tasks-command.js.map +1 -0
- package/dist/slack/formatters/project-formatter.d.ts +19 -0
- package/dist/slack/formatters/project-formatter.js +94 -0
- package/dist/slack/formatters/project-formatter.js.map +1 -0
- package/dist/slack/notifier.d.ts +41 -0
- package/dist/slack/notifier.js +111 -0
- package/dist/slack/notifier.js.map +1 -0
- package/dist/slack/repositories/channel-subscription.repository.d.ts +25 -0
- package/dist/slack/repositories/channel-subscription.repository.js +51 -0
- package/dist/slack/repositories/channel-subscription.repository.js.map +1 -0
- package/dist/slack/task-formatter.d.ts +31 -0
- package/dist/slack/task-formatter.js +151 -0
- package/dist/slack/task-formatter.js.map +1 -0
- package/dist/slack/user-identity.d.ts +37 -0
- package/dist/slack/user-identity.js +70 -0
- package/dist/slack/user-identity.js.map +1 -0
- package/dist/types/identity.d.ts +84 -0
- package/dist/types/identity.js +6 -0
- package/dist/types/identity.js.map +1 -0
- package/dist/types/task.d.ts +202 -0
- package/dist/types/task.js +17 -0
- package/dist/types/task.js.map +1 -0
- package/dist/utils/cycle-detector.d.ts +25 -0
- package/dist/utils/cycle-detector.js +86 -0
- package/dist/utils/cycle-detector.js.map +1 -0
- package/dist/utils/exit-codes.d.ts +64 -0
- package/dist/utils/exit-codes.js +57 -0
- package/dist/utils/exit-codes.js.map +1 -0
- package/dist/utils/is-main.d.ts +12 -0
- package/dist/utils/is-main.js +24 -0
- package/dist/utils/is-main.js.map +1 -0
- package/dist/utils/version.d.ts +1 -0
- package/dist/utils/version.js +22 -0
- package/dist/utils/version.js.map +1 -0
- package/dist/web/html.d.ts +73 -0
- package/dist/web/html.js +154 -0
- package/dist/web/html.js.map +1 -0
- package/dist/web/pages/device.d.ts +19 -0
- package/dist/web/pages/device.js +76 -0
- package/dist/web/pages/device.js.map +1 -0
- package/dist/web/pages/error.d.ts +6 -0
- package/dist/web/pages/error.js +23 -0
- package/dist/web/pages/error.js.map +1 -0
- package/dist/web/pages/login.d.ts +5 -0
- package/dist/web/pages/login.js +22 -0
- package/dist/web/pages/login.js.map +1 -0
- package/dist/web/pages/me.d.ts +9 -0
- package/dist/web/pages/me.js +37 -0
- package/dist/web/pages/me.js.map +1 -0
- package/dist/web/pages/tokens.d.ts +20 -0
- package/dist/web/pages/tokens.js +89 -0
- package/dist/web/pages/tokens.js.map +1 -0
- package/dist/web/session-constants.d.ts +21 -0
- package/dist/web/session-constants.js +22 -0
- package/dist/web/session-constants.js.map +1 -0
- package/dist/web/session-flash.d.ts +15 -0
- package/dist/web/session-flash.js +11 -0
- package/dist/web/session-flash.js.map +1 -0
- package/dist/web/session-user.d.ts +59 -0
- package/dist/web/session-user.js +44 -0
- package/dist/web/session-user.js.map +1 -0
- package/docs/AGENT_CONTEXT.md +280 -0
- package/docs/README.md +49 -0
- package/llms.txt +33 -0
- package/package.json +129 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { TASK_STATUSES, TASK_PRIORITIES } from '../types/task.js';
|
|
3
|
+
/**
|
|
4
|
+
* Wave 1.4 (task #312): verdict enum for the verification_evidence envelope.
|
|
5
|
+
*
|
|
6
|
+
* - PASS — verifier confirmed the task's acceptance criteria.
|
|
7
|
+
* - FAIL — verifier ran the checks and at least one failed.
|
|
8
|
+
* - PARTIAL — some checks passed, some failed/skipped.
|
|
9
|
+
* - NOT_VERIFIED — task closed without verification (auto-materialized by the
|
|
10
|
+
* service layer when status -> done/closed and no evidence
|
|
11
|
+
* was supplied). Explicitly distinct from "evidence absent
|
|
12
|
+
* because the column is NULL" — see service updateTask.
|
|
13
|
+
*/
|
|
14
|
+
export const VERIFICATION_VERDICTS = [
|
|
15
|
+
'PASS',
|
|
16
|
+
'FAIL',
|
|
17
|
+
'PARTIAL',
|
|
18
|
+
'NOT_VERIFIED',
|
|
19
|
+
];
|
|
20
|
+
/**
|
|
21
|
+
* Per-check status — tighter than the top-level verdict because a single
|
|
22
|
+
* check is a leaf (it either ran, or was skipped). Kept narrow on purpose so
|
|
23
|
+
* the boundary rejects free-form strings ("ok", "good", etc.) and forces
|
|
24
|
+
* verifier subagents to pick one of the three values.
|
|
25
|
+
*/
|
|
26
|
+
export const VERIFICATION_CHECK_STATUSES = ['PASS', 'FAIL', 'SKIP'];
|
|
27
|
+
/**
|
|
28
|
+
* Structured verification evidence stored in `tasks.verification_evidence`
|
|
29
|
+
* as a JSON string (write: JSON.stringify; read: JSON.parse — both happen
|
|
30
|
+
* inside the repository).
|
|
31
|
+
*
|
|
32
|
+
* Only `verdict` is required. Every other field is optional so the
|
|
33
|
+
* auto-NOT_VERIFIED materialization on close (service-layer behavior — see
|
|
34
|
+
* task.service.ts updateTask) can emit `{verdict: "NOT_VERIFIED"}` without
|
|
35
|
+
* lying about a verified_at timestamp or fabricating a session id.
|
|
36
|
+
*
|
|
37
|
+
* Bounds:
|
|
38
|
+
* - `checks` capped at 50 entries (a single task does not realistically
|
|
39
|
+
* accumulate more verification gates than that; the cap bounds row size).
|
|
40
|
+
* - `evidence_url_or_text` capped at 2000 chars per entry.
|
|
41
|
+
* - identifier strings capped at 200 chars.
|
|
42
|
+
*/
|
|
43
|
+
export const VerificationEvidenceSchema = z.object({
|
|
44
|
+
verdict: z.enum(VERIFICATION_VERDICTS),
|
|
45
|
+
checks: z
|
|
46
|
+
.array(z.object({
|
|
47
|
+
name: z.string().min(1).max(200),
|
|
48
|
+
status: z.enum(VERIFICATION_CHECK_STATUSES),
|
|
49
|
+
evidence_url_or_text: z.string().max(2000),
|
|
50
|
+
}))
|
|
51
|
+
.max(50)
|
|
52
|
+
.optional(),
|
|
53
|
+
verifier_session_id: z.string().min(1).max(200).optional(),
|
|
54
|
+
verifier_request_id: z.string().min(1).max(200).optional(),
|
|
55
|
+
verified_at: z.string().datetime().optional(),
|
|
56
|
+
}).strict();
|
|
57
|
+
/**
|
|
58
|
+
* CreateTaskSchema - validation for creating new tasks
|
|
59
|
+
* Note: status is NOT included - new tasks always start as 'open'
|
|
60
|
+
*/
|
|
61
|
+
export const CreateTaskSchema = z.object({
|
|
62
|
+
title: z.string().min(1, 'Title is required').max(255, 'Title must be 255 characters or less'),
|
|
63
|
+
description: z.string().max(5000).optional().nullable(),
|
|
64
|
+
priority: z.enum(TASK_PRIORITIES).default('medium'),
|
|
65
|
+
project_id: z.number().int().positive('Project ID must be a positive integer'),
|
|
66
|
+
parent_task_id: z.number().int().positive().optional().nullable(),
|
|
67
|
+
estimated_minutes: z.number().int().min(0).max(10080).optional().nullable(),
|
|
68
|
+
assignee: z.string().max(100).optional().nullable(),
|
|
69
|
+
created_by: z.string().min(1, 'Created by is required').max(100),
|
|
70
|
+
due_date: z.string().datetime({ message: 'Due date must be ISO8601 format' }).optional().nullable(),
|
|
71
|
+
tags: z.array(z.string().min(1).max(50)).max(20).optional().default([]),
|
|
72
|
+
// Wave 1.3 (task #311): free-form plain-text acceptance criteria. Clients
|
|
73
|
+
// supply this on create to make "what would prove this is done?" structured
|
|
74
|
+
// rather than buried in the description field. Multi-line markdown is fine.
|
|
75
|
+
// No DB constraint — the 5000-char cap is a schema-layer business rule.
|
|
76
|
+
acceptance_criteria: z.string().max(5000).optional().nullable(),
|
|
77
|
+
// Phase 31 (Plan 31-01): optional FK fields. NOTE — these are server-derived
|
|
78
|
+
// at route boundaries (T-31-02 of 31-01-PLAN threat register): downstream
|
|
79
|
+
// plans STRIP body-supplied values and set them from request.user / Slack
|
|
80
|
+
// lookup / MCP boot. They are accepted here only so service/repository
|
|
81
|
+
// call sites can pass them through.
|
|
82
|
+
created_by_user_id: z.number().int().positive().optional().nullable(),
|
|
83
|
+
assignee_user_id: z.number().int().positive().optional().nullable(),
|
|
84
|
+
});
|
|
85
|
+
/**
|
|
86
|
+
* Client-facing variant of CreateTaskSchema for MCP tool registration
|
|
87
|
+
* (Phase 31 review WR-04). Omits the server-derived FK fields
|
|
88
|
+
* (`created_by_user_id`, `assignee_user_id`) so a client supplying them
|
|
89
|
+
* gets a clear validation error instead of having the values silently
|
|
90
|
+
* stripped by the route handler.
|
|
91
|
+
*
|
|
92
|
+
* The service-layer `CreateTaskSchema` still accepts them because
|
|
93
|
+
* internal callers (routes, MCP handlers) populate them from
|
|
94
|
+
* request.user / boot-time context. This separation makes the public
|
|
95
|
+
* API surface honest about what fields clients control.
|
|
96
|
+
*/
|
|
97
|
+
export const CreateTaskClientSchema = CreateTaskSchema.omit({
|
|
98
|
+
created_by_user_id: true,
|
|
99
|
+
assignee_user_id: true,
|
|
100
|
+
}).strict();
|
|
101
|
+
/**
|
|
102
|
+
* UpdateTaskSchema - validation for updating tasks
|
|
103
|
+
* All fields are optional (partial updates)
|
|
104
|
+
*/
|
|
105
|
+
export const UpdateTaskSchema = z.object({
|
|
106
|
+
title: z.string().min(1).max(255),
|
|
107
|
+
description: z.string().max(5000).nullable(),
|
|
108
|
+
status: z.enum(TASK_STATUSES),
|
|
109
|
+
priority: z.enum(TASK_PRIORITIES),
|
|
110
|
+
parent_task_id: z.number().int().positive().nullable(),
|
|
111
|
+
estimated_minutes: z.number().int().min(0).max(10080).nullable(),
|
|
112
|
+
assignee: z.string().max(100).nullable(),
|
|
113
|
+
due_date: z.string().datetime().nullable(),
|
|
114
|
+
tags: z.array(z.string().min(1).max(50)).max(20),
|
|
115
|
+
// Phase 31 (Plan 31-01): optional FK field. Server-derived at the route
|
|
116
|
+
// boundary (T-31-02) — downstream plans STRIP body-supplied values.
|
|
117
|
+
assignee_user_id: z.number().int().positive().nullable(),
|
|
118
|
+
// Wave 1.3 (task #311): patch acceptance_criteria on existing tasks.
|
|
119
|
+
// Pass null to clear, a string to set. Same 5000-char cap as create.
|
|
120
|
+
acceptance_criteria: z.string().max(5000).nullable(),
|
|
121
|
+
// Wave 1.4 (task #312): structured verification evidence. The Zod enum on
|
|
122
|
+
// `verdict` rejects unknown values at the boundary (the "unknown verdict =
|
|
123
|
+
// 400" contract). Pass null to clear, an object to set. Stored as a JSON
|
|
124
|
+
// string by the repository.
|
|
125
|
+
verification_evidence: VerificationEvidenceSchema.nullable(),
|
|
126
|
+
}).partial();
|
|
127
|
+
/**
|
|
128
|
+
* Client-facing variant of UpdateTaskSchema for MCP tool registration
|
|
129
|
+
* (Phase 31 review WR-04). Omits the server-derived `assignee_user_id`
|
|
130
|
+
* FK; clients update the FK indirectly by supplying `assignee` (an email
|
|
131
|
+
* or display name), which the MCP handler resolves server-side via
|
|
132
|
+
* `resolveAssigneeUserId`.
|
|
133
|
+
*/
|
|
134
|
+
export const UpdateTaskClientSchema = z.object({
|
|
135
|
+
title: z.string().min(1).max(255),
|
|
136
|
+
description: z.string().max(5000).nullable(),
|
|
137
|
+
status: z.enum(TASK_STATUSES),
|
|
138
|
+
priority: z.enum(TASK_PRIORITIES),
|
|
139
|
+
parent_task_id: z.number().int().positive().nullable(),
|
|
140
|
+
estimated_minutes: z.number().int().min(0).max(10080).nullable(),
|
|
141
|
+
assignee: z.string().max(100).nullable(),
|
|
142
|
+
due_date: z.string().datetime().nullable(),
|
|
143
|
+
tags: z.array(z.string().min(1).max(50)).max(20),
|
|
144
|
+
// Wave 1.3 (task #311): clients can patch acceptance_criteria — it is
|
|
145
|
+
// NOT server-derived, so it stays on the client-facing schema.
|
|
146
|
+
acceptance_criteria: z.string().max(5000).nullable(),
|
|
147
|
+
// Wave 1.4 (task #312): verifier subagents call update_task with this
|
|
148
|
+
// envelope. It is NOT server-derived, so it stays on the client-facing
|
|
149
|
+
// schema. Unknown verdicts get rejected at the Zod boundary.
|
|
150
|
+
verification_evidence: VerificationEvidenceSchema.nullable(),
|
|
151
|
+
}).partial().strict();
|
|
152
|
+
/**
|
|
153
|
+
* CreateProjectSchema - validation for creating new projects
|
|
154
|
+
*/
|
|
155
|
+
export const CreateProjectSchema = z.object({
|
|
156
|
+
name: z.string().min(1, 'Name is required').max(100, 'Name must be 100 characters or less'),
|
|
157
|
+
description: z.string().max(1000).optional().nullable(),
|
|
158
|
+
});
|
|
159
|
+
/**
|
|
160
|
+
* Pagination bounds applied to all list endpoints.
|
|
161
|
+
*
|
|
162
|
+
* `limit` — page size; capped at 500 to bound query cost (GROUP_CONCAT
|
|
163
|
+
* over task_tags scales with row count).
|
|
164
|
+
* `offset` — starting row, zero-based.
|
|
165
|
+
*
|
|
166
|
+
* Both fields default to safe values so existing callers that omit them
|
|
167
|
+
* receive the first page (50 rows) rather than the full table.
|
|
168
|
+
*/
|
|
169
|
+
export const PaginationSchema = z.object({
|
|
170
|
+
limit: z.coerce.number().int().positive().max(500).default(50),
|
|
171
|
+
offset: z.coerce.number().int().nonnegative().default(0),
|
|
172
|
+
});
|
|
173
|
+
/**
|
|
174
|
+
* Optional pagination — same bounds, but each field can be omitted entirely.
|
|
175
|
+
* Used inside service-level filter parsing where defaults are applied later.
|
|
176
|
+
*/
|
|
177
|
+
export const PaginationOptionalSchema = z.object({
|
|
178
|
+
limit: z.coerce.number().int().positive().max(500).optional(),
|
|
179
|
+
offset: z.coerce.number().int().nonnegative().optional(),
|
|
180
|
+
});
|
|
181
|
+
/**
|
|
182
|
+
* Wrap a row schema in the standard paginated envelope:
|
|
183
|
+
* { data: [...], total, limit, offset }
|
|
184
|
+
*
|
|
185
|
+
* `total` is the unbounded count for the same filter set, so clients can
|
|
186
|
+
* implement page navigation without re-issuing without filters.
|
|
187
|
+
*/
|
|
188
|
+
export function paginatedSchema(itemSchema) {
|
|
189
|
+
return z.object({
|
|
190
|
+
data: z.array(itemSchema),
|
|
191
|
+
total: z.number().int().nonnegative(),
|
|
192
|
+
limit: z.number().int().positive(),
|
|
193
|
+
offset: z.number().int().nonnegative(),
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* TaskFiltersSchema - validation for task filtering
|
|
198
|
+
* All fields are optional. Includes pagination knobs (limit/offset).
|
|
199
|
+
*/
|
|
200
|
+
export const TaskFiltersSchema = z.object({
|
|
201
|
+
project_id: z.number().int().positive(),
|
|
202
|
+
status: z.enum(TASK_STATUSES),
|
|
203
|
+
assignee: z.string(),
|
|
204
|
+
tags: z.array(z.string()),
|
|
205
|
+
due_before: z.string().datetime(),
|
|
206
|
+
due_after: z.string().datetime(),
|
|
207
|
+
updated_before: z.string().datetime(),
|
|
208
|
+
updated_after: z.string().datetime(),
|
|
209
|
+
search: z
|
|
210
|
+
.string()
|
|
211
|
+
.min(1)
|
|
212
|
+
.max(200)
|
|
213
|
+
.refine((s) => s.trim().split(/\s+/).filter(Boolean).length <= 32, { message: 'Search query must contain at most 32 terms.' }),
|
|
214
|
+
// Wave 1.4 (#312): verified-state filter. See TaskFilters.verified in
|
|
215
|
+
// src/types/task.ts for semantics. The repository builds the
|
|
216
|
+
// json_extract(verification_evidence, '$.verdict') predicate.
|
|
217
|
+
verified: z.boolean(),
|
|
218
|
+
limit: z.coerce.number().int().positive().max(500),
|
|
219
|
+
offset: z.coerce.number().int().nonnegative(),
|
|
220
|
+
}).partial();
|
|
221
|
+
/**
|
|
222
|
+
* ListTasksMcpSchema - filters plus MCP-only knobs.
|
|
223
|
+
*
|
|
224
|
+
* `verbose` opts back into full task bodies (description + audit fields).
|
|
225
|
+
* Default response is a compact projection to keep MCP tool result payloads
|
|
226
|
+
* within reasonable token budgets — full data is still available via get_task.
|
|
227
|
+
*/
|
|
228
|
+
export const ListTasksMcpSchema = TaskFiltersSchema.extend({
|
|
229
|
+
verbose: z.boolean().optional(),
|
|
230
|
+
});
|
|
231
|
+
/**
|
|
232
|
+
* Strip heavy/audit fields from a task for use in list responses. Keeps the
|
|
233
|
+
* fields a caller needs to decide whether to drill into a task with get_task.
|
|
234
|
+
*
|
|
235
|
+
* `parent_task_id` is optional because the remote REST TaskResponse does not
|
|
236
|
+
* surface it; in-process Task does. The compact projection includes it when
|
|
237
|
+
* present so callers can still see hierarchy.
|
|
238
|
+
*/
|
|
239
|
+
export function toCompactTask(task) {
|
|
240
|
+
return {
|
|
241
|
+
id: task.id,
|
|
242
|
+
title: task.title,
|
|
243
|
+
status: task.status,
|
|
244
|
+
priority: task.priority,
|
|
245
|
+
project_id: task.project_id,
|
|
246
|
+
parent_task_id: task.parent_task_id ?? null,
|
|
247
|
+
assignee: task.assignee,
|
|
248
|
+
due_date: task.due_date,
|
|
249
|
+
tags: task.tags,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* ClaimTaskSchema - validation for claiming a task
|
|
254
|
+
*/
|
|
255
|
+
export const ClaimTaskSchema = z.object({
|
|
256
|
+
assignee: z.string().min(1, 'Assignee is required').max(100),
|
|
257
|
+
});
|
|
258
|
+
/**
|
|
259
|
+
* CompletionReportSchema - validation for `getCompletionReport`.
|
|
260
|
+
*
|
|
261
|
+
* Caller supplies EITHER `days` (trailing N days from now, max 365) OR an
|
|
262
|
+
* explicit `start`/`end` pair (both ISO8601, end >= start). Optional
|
|
263
|
+
* `project_id` and `assignee` filters narrow the result set.
|
|
264
|
+
*/
|
|
265
|
+
export const CompletionReportSchema = z
|
|
266
|
+
.object({
|
|
267
|
+
days: z.number().int().min(1).max(365).optional(),
|
|
268
|
+
start: z.string().datetime().optional(),
|
|
269
|
+
end: z.string().datetime().optional(),
|
|
270
|
+
project_id: z.number().int().positive().optional(),
|
|
271
|
+
assignee: z.string().min(1).max(100).optional(),
|
|
272
|
+
})
|
|
273
|
+
.refine((v) => v.days !== undefined || (v.start !== undefined && v.end !== undefined), { message: 'Provide either `days` or both `start` and `end`' })
|
|
274
|
+
.refine((v) => v.days !== undefined ||
|
|
275
|
+
(v.start !== undefined && v.end !== undefined && v.end >= v.start), { message: '`end` must be greater than or equal to `start`' });
|
|
276
|
+
//# sourceMappingURL=task.schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task.schema.js","sourceRoot":"","sources":["../../src/schemas/task.schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Wave 4.1 (task #318) — Task-topology classifier output contract.
|
|
4
|
+
*
|
|
5
|
+
* `TopologyReportSchema` is the wire-shape returned by:
|
|
6
|
+
* - `TopologyService.classify(projectId)`
|
|
7
|
+
* - the `tasks topology --project <id>` CLI command (stdout JSON)
|
|
8
|
+
* - the `topology_check` MCP tool (structuredContent)
|
|
9
|
+
*
|
|
10
|
+
* The classifier decides whether a project is `/tasks:loop`-safe (parallelizable
|
|
11
|
+
* leaves) or requires `/tasks:loop-dag` (wave-by-wave parallel dispatch
|
|
12
|
+
* respecting dependency edges; Wave 4.3 / task #341) based on whether the
|
|
13
|
+
* project's `task_dependencies` rows form a flat set, an acyclic DAG, or a
|
|
14
|
+
* cycle-bearing graph.
|
|
15
|
+
*
|
|
16
|
+
* Field semantics:
|
|
17
|
+
* - `topology`:
|
|
18
|
+
* FLAT — zero `task_dependencies` edges in the project.
|
|
19
|
+
* DAG — ≥1 edge, no cycles (a total order exists).
|
|
20
|
+
* DAG_CYCLIC — ≥1 edge, contains a cycle (`/tasks:loop` is unsafe).
|
|
21
|
+
* - `edges`: `{from, to}` rows where `from` blocks `to` (i.e. `from` must
|
|
22
|
+
* complete before `to` can start). Derived from `task_dependencies`
|
|
23
|
+
* (`task_id → blocks_task_id`). Sorted by (from asc, to asc) for
|
|
24
|
+
* deterministic comparison across runs.
|
|
25
|
+
* - `roots`: task IDs with zero in-degree (no task blocks them). Sorted asc.
|
|
26
|
+
* - `leaves`: task IDs with zero out-degree (they block nothing). Sorted asc.
|
|
27
|
+
* - `advisory`:
|
|
28
|
+
* `/tasks:loop` — recommended for FLAT projects.
|
|
29
|
+
* `/tasks:loop-dag` — recommended for DAG projects (Wave 4.3 / #341).
|
|
30
|
+
* `BLOCKED` — refuse to loop; manual intervention needed for
|
|
31
|
+
* DAG_CYCLIC projects.
|
|
32
|
+
*
|
|
33
|
+
* NOTE: `parent_task_id` (the taxonomy column) is INCLUDED in node enumeration
|
|
34
|
+
* (we know about parent/child rows) but NOT counted as graph edges — per AC
|
|
35
|
+
* "excluding parent/child taxonomy edges". The only edge source is the
|
|
36
|
+
* `task_dependencies` table.
|
|
37
|
+
*/
|
|
38
|
+
export declare const TopologyReportSchema: z.ZodObject<{
|
|
39
|
+
topology: z.ZodEnum<{
|
|
40
|
+
FLAT: "FLAT";
|
|
41
|
+
DAG: "DAG";
|
|
42
|
+
DAG_CYCLIC: "DAG_CYCLIC";
|
|
43
|
+
}>;
|
|
44
|
+
edges: z.ZodArray<z.ZodObject<{
|
|
45
|
+
from: z.ZodNumber;
|
|
46
|
+
to: z.ZodNumber;
|
|
47
|
+
}, z.core.$strip>>;
|
|
48
|
+
roots: z.ZodArray<z.ZodNumber>;
|
|
49
|
+
leaves: z.ZodArray<z.ZodNumber>;
|
|
50
|
+
advisory: z.ZodEnum<{
|
|
51
|
+
"/tasks:loop": "/tasks:loop";
|
|
52
|
+
"/tasks:loop-dag": "/tasks:loop-dag";
|
|
53
|
+
BLOCKED: "BLOCKED";
|
|
54
|
+
}>;
|
|
55
|
+
}, z.core.$strip>;
|
|
56
|
+
export type TopologyReport = z.infer<typeof TopologyReportSchema>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Wave 4.1 (task #318) — Task-topology classifier output contract.
|
|
4
|
+
*
|
|
5
|
+
* `TopologyReportSchema` is the wire-shape returned by:
|
|
6
|
+
* - `TopologyService.classify(projectId)`
|
|
7
|
+
* - the `tasks topology --project <id>` CLI command (stdout JSON)
|
|
8
|
+
* - the `topology_check` MCP tool (structuredContent)
|
|
9
|
+
*
|
|
10
|
+
* The classifier decides whether a project is `/tasks:loop`-safe (parallelizable
|
|
11
|
+
* leaves) or requires `/tasks:loop-dag` (wave-by-wave parallel dispatch
|
|
12
|
+
* respecting dependency edges; Wave 4.3 / task #341) based on whether the
|
|
13
|
+
* project's `task_dependencies` rows form a flat set, an acyclic DAG, or a
|
|
14
|
+
* cycle-bearing graph.
|
|
15
|
+
*
|
|
16
|
+
* Field semantics:
|
|
17
|
+
* - `topology`:
|
|
18
|
+
* FLAT — zero `task_dependencies` edges in the project.
|
|
19
|
+
* DAG — ≥1 edge, no cycles (a total order exists).
|
|
20
|
+
* DAG_CYCLIC — ≥1 edge, contains a cycle (`/tasks:loop` is unsafe).
|
|
21
|
+
* - `edges`: `{from, to}` rows where `from` blocks `to` (i.e. `from` must
|
|
22
|
+
* complete before `to` can start). Derived from `task_dependencies`
|
|
23
|
+
* (`task_id → blocks_task_id`). Sorted by (from asc, to asc) for
|
|
24
|
+
* deterministic comparison across runs.
|
|
25
|
+
* - `roots`: task IDs with zero in-degree (no task blocks them). Sorted asc.
|
|
26
|
+
* - `leaves`: task IDs with zero out-degree (they block nothing). Sorted asc.
|
|
27
|
+
* - `advisory`:
|
|
28
|
+
* `/tasks:loop` — recommended for FLAT projects.
|
|
29
|
+
* `/tasks:loop-dag` — recommended for DAG projects (Wave 4.3 / #341).
|
|
30
|
+
* `BLOCKED` — refuse to loop; manual intervention needed for
|
|
31
|
+
* DAG_CYCLIC projects.
|
|
32
|
+
*
|
|
33
|
+
* NOTE: `parent_task_id` (the taxonomy column) is INCLUDED in node enumeration
|
|
34
|
+
* (we know about parent/child rows) but NOT counted as graph edges — per AC
|
|
35
|
+
* "excluding parent/child taxonomy edges". The only edge source is the
|
|
36
|
+
* `task_dependencies` table.
|
|
37
|
+
*/
|
|
38
|
+
export const TopologyReportSchema = z.object({
|
|
39
|
+
topology: z.enum(['FLAT', 'DAG', 'DAG_CYCLIC']),
|
|
40
|
+
edges: z.array(z.object({
|
|
41
|
+
from: z.number().int().positive(),
|
|
42
|
+
to: z.number().int().positive(),
|
|
43
|
+
})),
|
|
44
|
+
roots: z.array(z.number().int().positive()),
|
|
45
|
+
leaves: z.array(z.number().int().positive()),
|
|
46
|
+
advisory: z.enum(['/tasks:loop', '/tasks:loop-dag', 'BLOCKED']),
|
|
47
|
+
});
|
|
48
|
+
//# sourceMappingURL=topology.schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"topology.schema.js","sourceRoot":"","sources":["../../src/schemas/topology.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;IAC/C,KAAK,EAAE,CAAC,CAAC,KAAK,CACZ,CAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;QACjC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;KAChC,CAAC,CACH;IACD,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;IAC3C,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;IAC5C,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,iBAAiB,EAAE,SAAS,CAAC,CAAC;CAChE,CAAC,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Failed-auth audit-log helper.
|
|
3
|
+
*
|
|
4
|
+
* Locks the AUDIT-03 contract: the helper signature physically cannot accept
|
|
5
|
+
* a raw credential. Callers MUST reduce the failure to a categorical
|
|
6
|
+
* `reasonCode` before invoking, which makes credential-leakage a compile-time
|
|
7
|
+
* error rather than a runtime convention.
|
|
8
|
+
*
|
|
9
|
+
* Used by Phase 28's auth chain (PAT / session / legacy strategies). Defined
|
|
10
|
+
* here in Phase 27 so the contract is fixed before any caller exists.
|
|
11
|
+
*/
|
|
12
|
+
/** Authentication strategy that produced the failure. */
|
|
13
|
+
export type AuthStrategy = 'pat' | 'session' | 'legacy';
|
|
14
|
+
/**
|
|
15
|
+
* Categorical reason a credential-bearing request was rejected. The set is
|
|
16
|
+
* intentionally narrow — anything that does not fit one of these buckets
|
|
17
|
+
* should be widened here (and in the test fixture) rather than smuggled in
|
|
18
|
+
* via a free-form string.
|
|
19
|
+
*/
|
|
20
|
+
export type AuthFailureReason = 'missing_credential' | 'malformed' | 'unknown_token' | 'revoked' | 'expired' | 'user_disabled' | 'wrong_prefix';
|
|
21
|
+
/**
|
|
22
|
+
* Required context for every auth-failure log line. There is NO field for
|
|
23
|
+
* the supplied credential — this is the discipline the helper enforces.
|
|
24
|
+
*/
|
|
25
|
+
export interface AuthFailureContext {
|
|
26
|
+
readonly strategy: AuthStrategy;
|
|
27
|
+
readonly reasonCode: AuthFailureReason;
|
|
28
|
+
readonly requestId: string;
|
|
29
|
+
readonly peerIp: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Structural logger contract — compatible with both Fastify's
|
|
33
|
+
* `FastifyBaseLogger` and a vitest mock. Kept minimal to avoid pulling
|
|
34
|
+
* Fastify types into the helper's surface.
|
|
35
|
+
*/
|
|
36
|
+
export interface MinimalWarnLogger {
|
|
37
|
+
warn(obj: object, msg?: string): void;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Emit exactly one `warn`-level structured log line tagged `auth.failure`.
|
|
41
|
+
*
|
|
42
|
+
* The payload is deliberately minimal: `tag`, `strategy`, `reasonCode`,
|
|
43
|
+
* `requestId`, `peerIp` — nothing else. Aggregators filter on `tag` and
|
|
44
|
+
* group by `strategy` + `reasonCode`.
|
|
45
|
+
*/
|
|
46
|
+
export declare function logAuthFailure(logger: MinimalWarnLogger, ctx: AuthFailureContext): void;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Failed-auth audit-log helper.
|
|
3
|
+
*
|
|
4
|
+
* Locks the AUDIT-03 contract: the helper signature physically cannot accept
|
|
5
|
+
* a raw credential. Callers MUST reduce the failure to a categorical
|
|
6
|
+
* `reasonCode` before invoking, which makes credential-leakage a compile-time
|
|
7
|
+
* error rather than a runtime convention.
|
|
8
|
+
*
|
|
9
|
+
* Used by Phase 28's auth chain (PAT / session / legacy strategies). Defined
|
|
10
|
+
* here in Phase 27 so the contract is fixed before any caller exists.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Emit exactly one `warn`-level structured log line tagged `auth.failure`.
|
|
14
|
+
*
|
|
15
|
+
* The payload is deliberately minimal: `tag`, `strategy`, `reasonCode`,
|
|
16
|
+
* `requestId`, `peerIp` — nothing else. Aggregators filter on `tag` and
|
|
17
|
+
* group by `strategy` + `reasonCode`.
|
|
18
|
+
*/
|
|
19
|
+
export function logAuthFailure(logger, ctx) {
|
|
20
|
+
logger.warn({
|
|
21
|
+
tag: 'auth.failure',
|
|
22
|
+
strategy: ctx.strategy,
|
|
23
|
+
reasonCode: ctx.reasonCode,
|
|
24
|
+
requestId: ctx.requestId,
|
|
25
|
+
peerIp: ctx.peerIp,
|
|
26
|
+
}, 'Authentication failed');
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=auth-audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-audit.js","sourceRoot":"","sources":["../../src/services/auth-audit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAwCH;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAyB,EACzB,GAAuB;IAEvB,MAAM,CAAC,IAAI,CACT;QACE,GAAG,EAAE,cAAc;QACnB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,MAAM,EAAE,GAAG,CAAC,MAAM;KACnB,EACD,uBAAuB,CACxB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
/**
|
|
3
|
+
* ClaimReleaseService - auto-releases stale task claims after a configurable timeout.
|
|
4
|
+
*
|
|
5
|
+
* Tasks that have been claimed but show no activity (no updated_at changes)
|
|
6
|
+
* for longer than the timeout are considered stale and are automatically
|
|
7
|
+
* released back to 'open' status with no assignee.
|
|
8
|
+
*/
|
|
9
|
+
export declare class ClaimReleaseService {
|
|
10
|
+
private db;
|
|
11
|
+
private timeoutMinutes;
|
|
12
|
+
private intervalHandle;
|
|
13
|
+
constructor(db: Database.Database, timeoutMinutes?: number);
|
|
14
|
+
/**
|
|
15
|
+
* Find all claimed tasks with no activity past the timeout.
|
|
16
|
+
* "No activity" = claimed_at is older than timeoutMinutes AND updated_at is also older.
|
|
17
|
+
* This way, any update/comment activity resets the clock via updated_at.
|
|
18
|
+
*/
|
|
19
|
+
findStaleClaims(): Array<{
|
|
20
|
+
id: number;
|
|
21
|
+
assignee: string;
|
|
22
|
+
claimed_at: string;
|
|
23
|
+
}>;
|
|
24
|
+
/**
|
|
25
|
+
* Release a stale claim: set assignee to NULL, status to 'open',
|
|
26
|
+
* clear claimed_at, increment version.
|
|
27
|
+
*/
|
|
28
|
+
releaseClaim(taskId: number): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Sweep: find and release all stale claims.
|
|
31
|
+
* Returns count of released claims.
|
|
32
|
+
*/
|
|
33
|
+
sweep(): number;
|
|
34
|
+
/**
|
|
35
|
+
* Start periodic sweep (default: every 5 minutes).
|
|
36
|
+
*/
|
|
37
|
+
start(intervalMs?: number): void;
|
|
38
|
+
/**
|
|
39
|
+
* Stop periodic sweep.
|
|
40
|
+
*/
|
|
41
|
+
stop(): void;
|
|
42
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { eventBus } from '../events/event-bus.js';
|
|
2
|
+
/**
|
|
3
|
+
* ClaimReleaseService - auto-releases stale task claims after a configurable timeout.
|
|
4
|
+
*
|
|
5
|
+
* Tasks that have been claimed but show no activity (no updated_at changes)
|
|
6
|
+
* for longer than the timeout are considered stale and are automatically
|
|
7
|
+
* released back to 'open' status with no assignee.
|
|
8
|
+
*/
|
|
9
|
+
export class ClaimReleaseService {
|
|
10
|
+
db;
|
|
11
|
+
timeoutMinutes;
|
|
12
|
+
intervalHandle = null;
|
|
13
|
+
constructor(db, timeoutMinutes = 30) {
|
|
14
|
+
this.db = db;
|
|
15
|
+
this.timeoutMinutes = timeoutMinutes;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Find all claimed tasks with no activity past the timeout.
|
|
19
|
+
* "No activity" = claimed_at is older than timeoutMinutes AND updated_at is also older.
|
|
20
|
+
* This way, any update/comment activity resets the clock via updated_at.
|
|
21
|
+
*/
|
|
22
|
+
findStaleClaims() {
|
|
23
|
+
const cutoff = `-${this.timeoutMinutes} minutes`;
|
|
24
|
+
return this.db.prepare(`SELECT id, assignee, claimed_at FROM tasks
|
|
25
|
+
WHERE assignee IS NOT NULL
|
|
26
|
+
AND claimed_at IS NOT NULL
|
|
27
|
+
AND status = 'in_progress'
|
|
28
|
+
AND claimed_at <= datetime('now', ?)
|
|
29
|
+
AND updated_at <= datetime('now', ?)`).all(cutoff, cutoff);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Release a stale claim: set assignee to NULL, status to 'open',
|
|
33
|
+
* clear claimed_at, increment version.
|
|
34
|
+
*/
|
|
35
|
+
releaseClaim(taskId) {
|
|
36
|
+
const info = this.db.prepare(`UPDATE tasks
|
|
37
|
+
SET assignee = NULL, status = 'open', claimed_at = NULL,
|
|
38
|
+
version = version + 1, updated_at = datetime('now')
|
|
39
|
+
WHERE id = ? AND assignee IS NOT NULL AND status = 'in_progress'`).run(taskId);
|
|
40
|
+
return info.changes > 0;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Sweep: find and release all stale claims.
|
|
44
|
+
* Returns count of released claims.
|
|
45
|
+
*/
|
|
46
|
+
sweep() {
|
|
47
|
+
const stale = this.findStaleClaims();
|
|
48
|
+
let released = 0;
|
|
49
|
+
for (const claim of stale) {
|
|
50
|
+
if (this.releaseClaim(claim.id)) {
|
|
51
|
+
// Reload task for event payload
|
|
52
|
+
const task = this.db.prepare(`SELECT t.*, GROUP_CONCAT(tt.tag, ',') as tags_csv
|
|
53
|
+
FROM tasks t
|
|
54
|
+
LEFT JOIN task_tags tt ON tt.task_id = t.id
|
|
55
|
+
WHERE t.id = ?
|
|
56
|
+
GROUP BY t.id`).get(claim.id);
|
|
57
|
+
if (task) {
|
|
58
|
+
const { tags_csv, ...taskData } = task;
|
|
59
|
+
const tags = tags_csv ? tags_csv.split(',').sort() : [];
|
|
60
|
+
eventBus.emit('task.updated', {
|
|
61
|
+
eventType: 'task.updated',
|
|
62
|
+
timestamp: new Date().toISOString(),
|
|
63
|
+
data: { ...taskData, tags },
|
|
64
|
+
metadata: { source: 'workflow' }
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
released++;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return released;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Start periodic sweep (default: every 5 minutes).
|
|
74
|
+
*/
|
|
75
|
+
start(intervalMs = 5 * 60 * 1000) {
|
|
76
|
+
if (this.intervalHandle)
|
|
77
|
+
return;
|
|
78
|
+
this.intervalHandle = setInterval(() => this.sweep(), intervalMs);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Stop periodic sweep.
|
|
82
|
+
*/
|
|
83
|
+
stop() {
|
|
84
|
+
if (this.intervalHandle) {
|
|
85
|
+
clearInterval(this.intervalHandle);
|
|
86
|
+
this.intervalHandle = null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=claim-release.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claim-release.service.js","sourceRoot":"","sources":["../../src/services/claim-release.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGlD;;;;;;GAMG;AACH,MAAM,OAAO,mBAAmB;IAIpB;IACA;IAJF,cAAc,GAA0C,IAAI,CAAC;IAErE,YACU,EAAqB,EACrB,iBAAyB,EAAE;QAD3B,OAAE,GAAF,EAAE,CAAmB;QACrB,mBAAc,GAAd,cAAc,CAAa;IAClC,CAAC;IAEJ;;;;OAIG;IACH,eAAe;QACb,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,cAAc,UAAU,CAAC;QACjD,OAAO,IAAI,CAAC,EAAE,CAAC,OAAO,CACpB;;;;;8CAKwC,CACzC,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAgE,CAAC;IACvF,CAAC;IAED;;;OAGG;IACH,YAAY,CAAC,MAAc;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B;;;wEAGkE,CACnE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACd,OAAO,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED;;;OAGG;IACH,KAAK;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QACrC,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;YAC1B,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;gBAChC,gCAAgC;gBAChC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B;;;;yBAIe,CAChB,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAqD,CAAC;gBACpE,IAAI,IAAI,EAAE,CAAC;oBACT,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,GAAG,IAAI,CAAC;oBACvC,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACxD,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE;wBAC5B,SAAS,EAAE,cAAc;wBACzB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;wBACnC,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE;wBAC3B,QAAQ,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;qBACjC,CAAC,CAAC;gBACL,CAAC;gBACD,QAAQ,EAAE,CAAC;YACb,CAAC;QACH,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAqB,CAAC,GAAG,EAAE,GAAG,IAAI;QACtC,IAAI,IAAI,CAAC,cAAc;YAAE,OAAO;QAChC,IAAI,CAAC,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,UAAU,CAAC,CAAC;IACpE,CAAC;IAED;;OAEG;IACH,IAAI;QACF,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACnC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC7B,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ICommentRepository } from '../repositories/interfaces.js';
|
|
2
|
+
import type { ITaskRepository } from '../repositories/interfaces.js';
|
|
3
|
+
import type { Comment, PaginatedResponse } from '../types/task.js';
|
|
4
|
+
export declare class CommentService {
|
|
5
|
+
private commentRepo;
|
|
6
|
+
private taskRepo;
|
|
7
|
+
constructor(commentRepo: ICommentRepository, taskRepo: ITaskRepository);
|
|
8
|
+
/**
|
|
9
|
+
* Add a comment to a task
|
|
10
|
+
* @throws ValidationError if input is invalid
|
|
11
|
+
* @throws NotFoundError if task does not exist
|
|
12
|
+
*/
|
|
13
|
+
addComment(input: unknown): Comment;
|
|
14
|
+
/**
|
|
15
|
+
* Get comments for a task in chronological order — current page only.
|
|
16
|
+
* Internal callers use this; REST/MCP use {@link getCommentsPaginated}.
|
|
17
|
+
* @throws NotFoundError if task does not exist
|
|
18
|
+
*/
|
|
19
|
+
getComments(taskId: number, pagination?: {
|
|
20
|
+
limit?: number;
|
|
21
|
+
offset?: number;
|
|
22
|
+
}): Comment[];
|
|
23
|
+
/**
|
|
24
|
+
* Paginated get-comments: `{ data, total, limit, offset }`.
|
|
25
|
+
*/
|
|
26
|
+
getCommentsPaginated(taskId: number, pagination?: {
|
|
27
|
+
limit?: number;
|
|
28
|
+
offset?: number;
|
|
29
|
+
}): PaginatedResponse<Comment>;
|
|
30
|
+
/**
|
|
31
|
+
* Delete a comment
|
|
32
|
+
*
|
|
33
|
+
* @param id - Comment id to delete.
|
|
34
|
+
* @param task_id - Optional parent task id. When provided, the comment is
|
|
35
|
+
* only deleted if it belongs to this task. This protects the
|
|
36
|
+
* `DELETE /tasks/:id/comments/:commentId` route from IDOR — a caller cannot
|
|
37
|
+
* delete a comment by guessing its id under an unrelated task. Mismatches
|
|
38
|
+
* are reported as NotFoundError to avoid leaking comment existence across
|
|
39
|
+
* tasks.
|
|
40
|
+
* @throws NotFoundError if the comment does not exist, or if `task_id` is
|
|
41
|
+
* provided and the comment does not belong to that task.
|
|
42
|
+
*/
|
|
43
|
+
deleteComment(id: number, task_id?: number): void;
|
|
44
|
+
}
|