@fivepixels-js/lite-api 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +93 -0
- package/README.md +537 -0
- package/dist/app.d.ts +10 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +70 -0
- package/dist/app.js.map +1 -0
- package/dist/auth/identity.repository.d.ts +62 -0
- package/dist/auth/identity.repository.d.ts.map +1 -0
- package/dist/auth/identity.repository.js +202 -0
- package/dist/auth/identity.repository.js.map +1 -0
- package/dist/auth/identity.routes.d.ts +5 -0
- package/dist/auth/identity.routes.d.ts.map +1 -0
- package/dist/auth/identity.routes.js +56 -0
- package/dist/auth/identity.routes.js.map +1 -0
- package/dist/auth/identity.schemas.d.ts +2711 -0
- package/dist/auth/identity.schemas.d.ts.map +1 -0
- package/dist/auth/identity.schemas.js +117 -0
- package/dist/auth/identity.schemas.js.map +1 -0
- package/dist/auth/identity.service.d.ts +37 -0
- package/dist/auth/identity.service.d.ts.map +1 -0
- package/dist/auth/identity.service.js +131 -0
- package/dist/auth/identity.service.js.map +1 -0
- package/dist/auth/password.service.d.ts +15 -0
- package/dist/auth/password.service.d.ts.map +1 -0
- package/dist/auth/password.service.js +116 -0
- package/dist/auth/password.service.js.map +1 -0
- package/dist/auth/token.service.d.ts +38 -0
- package/dist/auth/token.service.d.ts.map +1 -0
- package/dist/auth/token.service.js +54 -0
- package/dist/auth/token.service.js.map +1 -0
- package/dist/cli/cli.d.ts +3 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/cli/cli.js +132 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/cli/commands/backup.d.ts +4 -0
- package/dist/cli/commands/backup.d.ts.map +1 -0
- package/dist/cli/commands/backup.js +24 -0
- package/dist/cli/commands/backup.js.map +1 -0
- package/dist/cli/commands/init.d.ts +4 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +23 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/migrate.d.ts +4 -0
- package/dist/cli/commands/migrate.d.ts.map +1 -0
- package/dist/cli/commands/migrate.js +20 -0
- package/dist/cli/commands/migrate.js.map +1 -0
- package/dist/cli/commands/start.d.ts +4 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +13 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/status.d.ts +4 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +48 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +4 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/io.d.ts +6 -0
- package/dist/cli/io.d.ts.map +1 -0
- package/dist/cli/io.js +9 -0
- package/dist/cli/io.js.map +1 -0
- package/dist/community/contracts.d.ts +29 -0
- package/dist/community/contracts.d.ts.map +1 -0
- package/dist/community/contracts.js +41 -0
- package/dist/community/contracts.js.map +1 -0
- package/dist/community/error-handler.d.ts +3 -0
- package/dist/community/error-handler.d.ts.map +1 -0
- package/dist/community/error-handler.js +66 -0
- package/dist/community/error-handler.js.map +1 -0
- package/dist/community/errors.d.ts +10 -0
- package/dist/community/errors.d.ts.map +1 -0
- package/dist/community/errors.js +39 -0
- package/dist/community/errors.js.map +1 -0
- package/dist/community/etag.d.ts +5 -0
- package/dist/community/etag.d.ts.map +1 -0
- package/dist/community/etag.js +31 -0
- package/dist/community/etag.js.map +1 -0
- package/dist/community/input.d.ts +10 -0
- package/dist/community/input.d.ts.map +1 -0
- package/dist/community/input.js +48 -0
- package/dist/community/input.js.map +1 -0
- package/dist/community/mutation-route.d.ts +7 -0
- package/dist/community/mutation-route.d.ts.map +1 -0
- package/dist/community/mutation-route.js +47 -0
- package/dist/community/mutation-route.js.map +1 -0
- package/dist/community/schemas.d.ts +807 -0
- package/dist/community/schemas.d.ts.map +1 -0
- package/dist/community/schemas.js +100 -0
- package/dist/community/schemas.js.map +1 -0
- package/dist/community/system.schemas.d.ts +40 -0
- package/dist/community/system.schemas.d.ts.map +1 -0
- package/dist/community/system.schemas.js +30 -0
- package/dist/community/system.schemas.js.map +1 -0
- package/dist/config/config.d.ts +43 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +208 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/data-path.d.ts +2 -0
- package/dist/config/data-path.d.ts.map +1 -0
- package/dist/config/data-path.js +16 -0
- package/dist/config/data-path.js.map +1 -0
- package/dist/config/jwt-secret.d.ts +3 -0
- package/dist/config/jwt-secret.d.ts.map +1 -0
- package/dist/config/jwt-secret.js +67 -0
- package/dist/config/jwt-secret.js.map +1 -0
- package/dist/db/backup.d.ts +10 -0
- package/dist/db/backup.d.ts.map +1 -0
- package/dist/db/backup.js +51 -0
- package/dist/db/backup.js.map +1 -0
- package/dist/db/connection.d.ts +15 -0
- package/dist/db/connection.d.ts.map +1 -0
- package/dist/db/connection.js +82 -0
- package/dist/db/connection.js.map +1 -0
- package/dist/db/guid-order.d.ts +2 -0
- package/dist/db/guid-order.d.ts.map +1 -0
- package/dist/db/guid-order.js +9 -0
- package/dist/db/guid-order.js.map +1 -0
- package/dist/db/migrate.d.ts +37 -0
- package/dist/db/migrate.d.ts.map +1 -0
- package/dist/db/migrate.js +145 -0
- package/dist/db/migrate.js.map +1 -0
- package/dist/db/migrations/001_schema_migrations.sql +6 -0
- package/dist/db/migrations/002_identity.sql +95 -0
- package/dist/db/migrations/003_projects.sql +62 -0
- package/dist/db/migrations/004_feedback_core.sql +236 -0
- package/dist/db/migrations/005_project_member_management.sql +55 -0
- package/dist/db/migrations/006_align_credentials.sql +33 -0
- package/dist/db/migrations/007_align_storage_values.sql +78 -0
- package/dist/db/storage-migration.d.ts +9 -0
- package/dist/db/storage-migration.d.ts.map +1 -0
- package/dist/db/storage-migration.js +79 -0
- package/dist/db/storage-migration.js.map +1 -0
- package/dist/db/transaction.d.ts +9 -0
- package/dist/db/transaction.d.ts.map +1 -0
- package/dist/db/transaction.js +14 -0
- package/dist/db/transaction.js.map +1 -0
- package/dist/errors/error-handler.d.ts +3 -0
- package/dist/errors/error-handler.d.ts.map +1 -0
- package/dist/errors/error-handler.js +50 -0
- package/dist/errors/error-handler.js.map +1 -0
- package/dist/feedbacks/feedback-workflow.service.d.ts +59 -0
- package/dist/feedbacks/feedback-workflow.service.d.ts.map +1 -0
- package/dist/feedbacks/feedback-workflow.service.js +89 -0
- package/dist/feedbacks/feedback-workflow.service.js.map +1 -0
- package/dist/feedbacks/feedback.input.d.ts +4 -0
- package/dist/feedbacks/feedback.input.d.ts.map +1 -0
- package/dist/feedbacks/feedback.input.js +25 -0
- package/dist/feedbacks/feedback.input.js.map +1 -0
- package/dist/feedbacks/feedback.repository.d.ts +48 -0
- package/dist/feedbacks/feedback.repository.d.ts.map +1 -0
- package/dist/feedbacks/feedback.repository.js +238 -0
- package/dist/feedbacks/feedback.repository.js.map +1 -0
- package/dist/feedbacks/feedback.routes.d.ts +4 -0
- package/dist/feedbacks/feedback.routes.d.ts.map +1 -0
- package/dist/feedbacks/feedback.routes.js +78 -0
- package/dist/feedbacks/feedback.routes.js.map +1 -0
- package/dist/feedbacks/feedback.schemas.d.ts +642 -0
- package/dist/feedbacks/feedback.schemas.d.ts.map +1 -0
- package/dist/feedbacks/feedback.schemas.js +131 -0
- package/dist/feedbacks/feedback.schemas.js.map +1 -0
- package/dist/feedbacks/feedback.service.d.ts +23 -0
- package/dist/feedbacks/feedback.service.d.ts.map +1 -0
- package/dist/feedbacks/feedback.service.js +74 -0
- package/dist/feedbacks/feedback.service.js.map +1 -0
- package/dist/feedbacks/feedback.types.d.ts +64 -0
- package/dist/feedbacks/feedback.types.d.ts.map +1 -0
- package/dist/feedbacks/feedback.types.js +2 -0
- package/dist/feedbacks/feedback.types.js.map +1 -0
- package/dist/page-elements/page-element.input.d.ts +7 -0
- package/dist/page-elements/page-element.input.d.ts.map +1 -0
- package/dist/page-elements/page-element.input.js +59 -0
- package/dist/page-elements/page-element.input.js.map +1 -0
- package/dist/page-elements/page-element.repository.d.ts +21 -0
- package/dist/page-elements/page-element.repository.d.ts.map +1 -0
- package/dist/page-elements/page-element.repository.js +123 -0
- package/dist/page-elements/page-element.repository.js.map +1 -0
- package/dist/page-elements/page-element.schemas.d.ts +97 -0
- package/dist/page-elements/page-element.schemas.d.ts.map +1 -0
- package/dist/page-elements/page-element.schemas.js +40 -0
- package/dist/page-elements/page-element.schemas.js.map +1 -0
- package/dist/page-elements/page-element.types.d.ts +24 -0
- package/dist/page-elements/page-element.types.d.ts.map +1 -0
- package/dist/page-elements/page-element.types.js +2 -0
- package/dist/page-elements/page-element.types.js.map +1 -0
- package/dist/plugins/auth.plugin.d.ts +3 -0
- package/dist/plugins/auth.plugin.d.ts.map +1 -0
- package/dist/plugins/auth.plugin.js +28 -0
- package/dist/plugins/auth.plugin.js.map +1 -0
- package/dist/plugins/community-api.plugin.d.ts +5 -0
- package/dist/plugins/community-api.plugin.d.ts.map +1 -0
- package/dist/plugins/community-api.plugin.js +25 -0
- package/dist/plugins/community-api.plugin.js.map +1 -0
- package/dist/plugins/cors.plugin.d.ts +3 -0
- package/dist/plugins/cors.plugin.d.ts.map +1 -0
- package/dist/plugins/cors.plugin.js +19 -0
- package/dist/plugins/cors.plugin.js.map +1 -0
- package/dist/plugins/swagger.plugin.d.ts +3 -0
- package/dist/plugins/swagger.plugin.d.ts.map +1 -0
- package/dist/plugins/swagger.plugin.js +59 -0
- package/dist/plugins/swagger.plugin.js.map +1 -0
- package/dist/plugins/user-auth.plugin.d.ts +33 -0
- package/dist/plugins/user-auth.plugin.d.ts.map +1 -0
- package/dist/plugins/user-auth.plugin.js +62 -0
- package/dist/plugins/user-auth.plugin.js.map +1 -0
- package/dist/projects/members/project-member.repository.d.ts +49 -0
- package/dist/projects/members/project-member.repository.d.ts.map +1 -0
- package/dist/projects/members/project-member.repository.js +215 -0
- package/dist/projects/members/project-member.repository.js.map +1 -0
- package/dist/projects/members/project-member.routes.d.ts +4 -0
- package/dist/projects/members/project-member.routes.d.ts.map +1 -0
- package/dist/projects/members/project-member.routes.js +82 -0
- package/dist/projects/members/project-member.routes.js.map +1 -0
- package/dist/projects/members/project-member.schemas.d.ts +2735 -0
- package/dist/projects/members/project-member.schemas.d.ts.map +1 -0
- package/dist/projects/members/project-member.schemas.js +138 -0
- package/dist/projects/members/project-member.schemas.js.map +1 -0
- package/dist/projects/members/project-member.service.d.ts +29 -0
- package/dist/projects/members/project-member.service.d.ts.map +1 -0
- package/dist/projects/members/project-member.service.js +92 -0
- package/dist/projects/members/project-member.service.js.map +1 -0
- package/dist/projects/project-access.policy.d.ts +11 -0
- package/dist/projects/project-access.policy.d.ts.map +1 -0
- package/dist/projects/project-access.policy.js +30 -0
- package/dist/projects/project-access.policy.js.map +1 -0
- package/dist/projects/project-access.repository.d.ts +12 -0
- package/dist/projects/project-access.repository.d.ts.map +1 -0
- package/dist/projects/project-access.repository.js +45 -0
- package/dist/projects/project-access.repository.js.map +1 -0
- package/dist/projects/project-access.types.d.ts +9 -0
- package/dist/projects/project-access.types.d.ts.map +1 -0
- package/dist/projects/project-access.types.js +2 -0
- package/dist/projects/project-access.types.js.map +1 -0
- package/dist/projects/project-mutation.service.d.ts +15 -0
- package/dist/projects/project-mutation.service.d.ts.map +1 -0
- package/dist/projects/project-mutation.service.js +39 -0
- package/dist/projects/project-mutation.service.js.map +1 -0
- package/dist/projects/project.repository.d.ts +49 -0
- package/dist/projects/project.repository.d.ts.map +1 -0
- package/dist/projects/project.repository.js +155 -0
- package/dist/projects/project.repository.js.map +1 -0
- package/dist/projects/project.routes.d.ts +4 -0
- package/dist/projects/project.routes.d.ts.map +1 -0
- package/dist/projects/project.routes.js +45 -0
- package/dist/projects/project.routes.js.map +1 -0
- package/dist/projects/project.schemas.d.ts +2044 -0
- package/dist/projects/project.schemas.d.ts.map +1 -0
- package/dist/projects/project.schemas.js +90 -0
- package/dist/projects/project.schemas.js.map +1 -0
- package/dist/projects/project.service.d.ts +40 -0
- package/dist/projects/project.service.d.ts.map +1 -0
- package/dist/projects/project.service.js +128 -0
- package/dist/projects/project.service.js.map +1 -0
- package/dist/replies/reply-mutation.service.d.ts +19 -0
- package/dist/replies/reply-mutation.service.d.ts.map +1 -0
- package/dist/replies/reply-mutation.service.js +51 -0
- package/dist/replies/reply-mutation.service.js.map +1 -0
- package/dist/replies/reply.input.d.ts +4 -0
- package/dist/replies/reply.input.d.ts.map +1 -0
- package/dist/replies/reply.input.js +33 -0
- package/dist/replies/reply.input.js.map +1 -0
- package/dist/replies/reply.repository.d.ts +40 -0
- package/dist/replies/reply.repository.d.ts.map +1 -0
- package/dist/replies/reply.repository.js +173 -0
- package/dist/replies/reply.repository.js.map +1 -0
- package/dist/replies/reply.routes.d.ts +4 -0
- package/dist/replies/reply.routes.d.ts.map +1 -0
- package/dist/replies/reply.routes.js +64 -0
- package/dist/replies/reply.routes.js.map +1 -0
- package/dist/replies/reply.schemas.d.ts +251 -0
- package/dist/replies/reply.schemas.d.ts.map +1 -0
- package/dist/replies/reply.schemas.js +51 -0
- package/dist/replies/reply.schemas.js.map +1 -0
- package/dist/replies/reply.service.d.ts +19 -0
- package/dist/replies/reply.service.d.ts.map +1 -0
- package/dist/replies/reply.service.js +50 -0
- package/dist/replies/reply.service.js.map +1 -0
- package/dist/replies/reply.types.d.ts +31 -0
- package/dist/replies/reply.types.d.ts.map +1 -0
- package/dist/replies/reply.types.js +2 -0
- package/dist/replies/reply.types.js.map +1 -0
- package/dist/report-cases/report-case-workflow.service.d.ts +39 -0
- package/dist/report-cases/report-case-workflow.service.d.ts.map +1 -0
- package/dist/report-cases/report-case-workflow.service.js +103 -0
- package/dist/report-cases/report-case-workflow.service.js.map +1 -0
- package/dist/report-cases/report-case.input.d.ts +4 -0
- package/dist/report-cases/report-case.input.d.ts.map +1 -0
- package/dist/report-cases/report-case.input.js +29 -0
- package/dist/report-cases/report-case.input.js.map +1 -0
- package/dist/report-cases/report-case.repository.d.ts +45 -0
- package/dist/report-cases/report-case.repository.d.ts.map +1 -0
- package/dist/report-cases/report-case.repository.js +185 -0
- package/dist/report-cases/report-case.repository.js.map +1 -0
- package/dist/report-cases/report-case.routes.d.ts +4 -0
- package/dist/report-cases/report-case.routes.d.ts.map +1 -0
- package/dist/report-cases/report-case.routes.js +94 -0
- package/dist/report-cases/report-case.routes.js.map +1 -0
- package/dist/report-cases/report-case.schemas.d.ts +294 -0
- package/dist/report-cases/report-case.schemas.d.ts.map +1 -0
- package/dist/report-cases/report-case.schemas.js +77 -0
- package/dist/report-cases/report-case.schemas.js.map +1 -0
- package/dist/report-cases/report-case.service.d.ts +21 -0
- package/dist/report-cases/report-case.service.d.ts.map +1 -0
- package/dist/report-cases/report-case.service.js +60 -0
- package/dist/report-cases/report-case.service.js.map +1 -0
- package/dist/report-cases/report-case.types.d.ts +39 -0
- package/dist/report-cases/report-case.types.d.ts.map +1 -0
- package/dist/report-cases/report-case.types.js +2 -0
- package/dist/report-cases/report-case.types.js.map +1 -0
- package/dist/routes/health.route.d.ts +4 -0
- package/dist/routes/health.route.d.ts.map +1 -0
- package/dist/routes/health.route.js +39 -0
- package/dist/routes/health.route.js.map +1 -0
- package/dist/routes/version.route.d.ts +3 -0
- package/dist/routes/version.route.d.ts.map +1 -0
- package/dist/routes/version.route.js +22 -0
- package/dist/routes/version.route.js.map +1 -0
- package/dist/runtime/index.d.ts +8 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +11 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/server.d.ts +11 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +66 -0
- package/dist/server.js.map +1 -0
- package/dist/storage/values.d.ts +3 -0
- package/dist/storage/values.d.ts.map +1 -0
- package/dist/storage/values.js +30 -0
- package/dist/storage/values.js.map +1 -0
- package/dist/users/current-user.routes.d.ts +3 -0
- package/dist/users/current-user.routes.d.ts.map +1 -0
- package/dist/users/current-user.routes.js +9 -0
- package/dist/users/current-user.routes.js.map +1 -0
- package/dist/users/current-user.schemas.d.ts +641 -0
- package/dist/users/current-user.schemas.d.ts.map +1 -0
- package/dist/users/current-user.schemas.js +21 -0
- package/dist/users/current-user.schemas.js.map +1 -0
- package/dist/users/user-search.repository.d.ts +19 -0
- package/dist/users/user-search.repository.d.ts.map +1 -0
- package/dist/users/user-search.repository.js +55 -0
- package/dist/users/user-search.repository.js.map +1 -0
- package/dist/users/user-search.routes.d.ts +4 -0
- package/dist/users/user-search.routes.d.ts.map +1 -0
- package/dist/users/user-search.routes.js +19 -0
- package/dist/users/user-search.routes.js.map +1 -0
- package/dist/users/user-search.schemas.d.ts +693 -0
- package/dist/users/user-search.schemas.d.ts.map +1 -0
- package/dist/users/user-search.schemas.js +41 -0
- package/dist/users/user-search.schemas.js.map +1 -0
- package/dist/users/user-search.service.d.ts +20 -0
- package/dist/users/user-search.service.d.ts.map +1 -0
- package/dist/users/user-search.service.js +41 -0
- package/dist/users/user-search.service.js.map +1 -0
- package/dist/users/user.schemas.d.ts +47 -0
- package/dist/users/user.schemas.d.ts.map +1 -0
- package/dist/users/user.schemas.js +13 -0
- package/dist/users/user.schemas.js.map +1 -0
- package/dist/users/user.types.d.ts +6 -0
- package/dist/users/user.types.d.ts.map +1 -0
- package/dist/users/user.types.js +2 -0
- package/dist/users/user.types.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/docs/guides/community-api-quickstart.md +171 -0
- package/docs/guides/feature-structure.md +138 -0
- package/docs/guides/independent-cli.md +73 -0
- package/docs/guides/non-attachment-api-contract.md +138 -0
- package/docs/plans/selfdev-schema-alignment.md +61 -0
- package/package.json +76 -0
- package/sql/fivepixels-lite-init.sql +518 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
CREATE TABLE feedbacks (
|
|
2
|
+
feedback_id TEXT PRIMARY KEY,
|
|
3
|
+
project_id TEXT NOT NULL,
|
|
4
|
+
environment TEXT NOT NULL
|
|
5
|
+
CHECK (length(environment) BETWEEN 1 AND 50 AND environment = lower(trim(environment))),
|
|
6
|
+
pathname TEXT NOT NULL
|
|
7
|
+
CHECK (length(pathname) BETWEEN 1 AND 2000 AND substr(pathname, 1, 1) = '/'),
|
|
8
|
+
pathname_hash TEXT NOT NULL
|
|
9
|
+
CHECK (length(pathname_hash) = 64 AND pathname_hash NOT GLOB '*[^0-9a-f]*'),
|
|
10
|
+
report_id TEXT NOT NULL
|
|
11
|
+
CHECK (length(report_id) BETWEEN 1 AND 255 AND report_id = trim(report_id)),
|
|
12
|
+
report_type TEXT NOT NULL
|
|
13
|
+
CHECK (length(report_type) BETWEEN 1 AND 50 AND report_type = trim(report_type)),
|
|
14
|
+
target_selector TEXT
|
|
15
|
+
CHECK (target_selector IS NULL OR (length(target_selector) BETWEEN 1 AND 2000 AND target_selector = trim(target_selector))),
|
|
16
|
+
status_code INTEGER NOT NULL DEFAULT 1
|
|
17
|
+
CHECK (status_code IN (1, 2)),
|
|
18
|
+
field_values TEXT NOT NULL
|
|
19
|
+
CHECK (json_valid(field_values) AND json_type(field_values) = 'object'),
|
|
20
|
+
position TEXT NOT NULL
|
|
21
|
+
CHECK (json_valid(position) AND json_type(position) = 'object'),
|
|
22
|
+
app_version TEXT NOT NULL
|
|
23
|
+
CHECK (length(app_version) BETWEEN 1 AND 100 AND app_version = trim(app_version)),
|
|
24
|
+
author_id TEXT NOT NULL,
|
|
25
|
+
assignee_id TEXT,
|
|
26
|
+
integrations TEXT NOT NULL
|
|
27
|
+
CHECK (json_valid(integrations) AND json_type(integrations) = 'array'),
|
|
28
|
+
lock_version INTEGER NOT NULL DEFAULT 0
|
|
29
|
+
CHECK (lock_version >= 0),
|
|
30
|
+
created_at TEXT NOT NULL,
|
|
31
|
+
updated_at TEXT NOT NULL,
|
|
32
|
+
CONSTRAINT fk_feedbacks_project
|
|
33
|
+
FOREIGN KEY (project_id) REFERENCES projects(project_id)
|
|
34
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
35
|
+
CONSTRAINT fk_feedbacks_author
|
|
36
|
+
FOREIGN KEY (author_id) REFERENCES users(user_id)
|
|
37
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
38
|
+
CONSTRAINT fk_feedbacks_assignee_membership
|
|
39
|
+
FOREIGN KEY (project_id, assignee_id) REFERENCES project_members(project_id, user_id)
|
|
40
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
41
|
+
CHECK (
|
|
42
|
+
length(feedback_id) = 36
|
|
43
|
+
AND feedback_id = lower(feedback_id)
|
|
44
|
+
AND substr(feedback_id, 9, 1) = '-'
|
|
45
|
+
AND substr(feedback_id, 14, 1) = '-'
|
|
46
|
+
AND substr(feedback_id, 19, 1) = '-'
|
|
47
|
+
AND substr(feedback_id, 24, 1) = '-'
|
|
48
|
+
AND replace(feedback_id, '-', '') NOT GLOB '*[^0-9a-f]*'
|
|
49
|
+
)
|
|
50
|
+
) STRICT;
|
|
51
|
+
|
|
52
|
+
CREATE INDEX ix_feedbacks_markers
|
|
53
|
+
ON feedbacks (
|
|
54
|
+
project_id,
|
|
55
|
+
environment,
|
|
56
|
+
pathname_hash,
|
|
57
|
+
status_code,
|
|
58
|
+
created_at DESC,
|
|
59
|
+
feedback_id DESC
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
CREATE INDEX ix_feedbacks_author_created_at
|
|
63
|
+
ON feedbacks (author_id, created_at DESC, feedback_id DESC);
|
|
64
|
+
|
|
65
|
+
CREATE UNIQUE INDEX uq_feedbacks_project_environment_report_id
|
|
66
|
+
ON feedbacks (project_id, environment, report_id);
|
|
67
|
+
|
|
68
|
+
CREATE INDEX ix_feedbacks_assignee_status
|
|
69
|
+
ON feedbacks (assignee_id, status_code, updated_at DESC, feedback_id DESC);
|
|
70
|
+
|
|
71
|
+
CREATE TABLE report_cases (
|
|
72
|
+
report_case_id TEXT PRIMARY KEY,
|
|
73
|
+
feedback_id TEXT NOT NULL,
|
|
74
|
+
type_code INTEGER NOT NULL
|
|
75
|
+
CHECK (type_code BETWEEN 1 AND 4),
|
|
76
|
+
status_code INTEGER NOT NULL DEFAULT 1
|
|
77
|
+
CHECK (status_code IN (1, 2)),
|
|
78
|
+
content TEXT NOT NULL
|
|
79
|
+
CHECK (length(content) >= 1 AND content = trim(content)),
|
|
80
|
+
creator_id TEXT NOT NULL,
|
|
81
|
+
assignee_id TEXT,
|
|
82
|
+
lock_version INTEGER NOT NULL DEFAULT 0
|
|
83
|
+
CHECK (lock_version >= 0),
|
|
84
|
+
resolved_at TEXT,
|
|
85
|
+
created_at TEXT NOT NULL,
|
|
86
|
+
updated_at TEXT NOT NULL,
|
|
87
|
+
CONSTRAINT fk_report_cases_feedback
|
|
88
|
+
FOREIGN KEY (feedback_id) REFERENCES feedbacks(feedback_id)
|
|
89
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
90
|
+
CONSTRAINT fk_report_cases_creator
|
|
91
|
+
FOREIGN KEY (creator_id) REFERENCES users(user_id)
|
|
92
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
93
|
+
CONSTRAINT fk_report_cases_assignee
|
|
94
|
+
FOREIGN KEY (assignee_id) REFERENCES users(user_id)
|
|
95
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
96
|
+
CHECK (
|
|
97
|
+
(status_code = 1 AND resolved_at IS NULL)
|
|
98
|
+
OR (status_code = 2 AND resolved_at IS NOT NULL)
|
|
99
|
+
),
|
|
100
|
+
CHECK (
|
|
101
|
+
length(report_case_id) = 36
|
|
102
|
+
AND report_case_id = lower(report_case_id)
|
|
103
|
+
AND substr(report_case_id, 9, 1) = '-'
|
|
104
|
+
AND substr(report_case_id, 14, 1) = '-'
|
|
105
|
+
AND substr(report_case_id, 19, 1) = '-'
|
|
106
|
+
AND substr(report_case_id, 24, 1) = '-'
|
|
107
|
+
AND replace(report_case_id, '-', '') NOT GLOB '*[^0-9a-f]*'
|
|
108
|
+
)
|
|
109
|
+
) STRICT;
|
|
110
|
+
|
|
111
|
+
CREATE INDEX ix_report_cases_feedback_status_created_at
|
|
112
|
+
ON report_cases (feedback_id, status_code, created_at DESC, report_case_id DESC);
|
|
113
|
+
|
|
114
|
+
CREATE INDEX ix_report_cases_assignee_status
|
|
115
|
+
ON report_cases (assignee_id, status_code, updated_at DESC, report_case_id DESC);
|
|
116
|
+
|
|
117
|
+
CREATE TABLE replies (
|
|
118
|
+
reply_id TEXT PRIMARY KEY,
|
|
119
|
+
type_code INTEGER NOT NULL
|
|
120
|
+
CHECK (type_code BETWEEN 1 AND 9),
|
|
121
|
+
status_code INTEGER NOT NULL DEFAULT 1
|
|
122
|
+
CHECK (status_code IN (1, 2)),
|
|
123
|
+
report_case_id TEXT NOT NULL,
|
|
124
|
+
parent_reply_id TEXT,
|
|
125
|
+
content TEXT NOT NULL
|
|
126
|
+
CHECK (length(content) BETWEEN 1 AND 10000 AND content = trim(content)),
|
|
127
|
+
author_id TEXT NOT NULL,
|
|
128
|
+
assignee_id TEXT,
|
|
129
|
+
previous_assignee_id TEXT,
|
|
130
|
+
lock_version INTEGER NOT NULL DEFAULT 0
|
|
131
|
+
CHECK (lock_version >= 0),
|
|
132
|
+
deleted_at TEXT,
|
|
133
|
+
created_at TEXT NOT NULL,
|
|
134
|
+
updated_at TEXT NOT NULL,
|
|
135
|
+
CONSTRAINT uq_replies_report_case_reply UNIQUE (report_case_id, reply_id),
|
|
136
|
+
CONSTRAINT fk_replies_report_case
|
|
137
|
+
FOREIGN KEY (report_case_id) REFERENCES report_cases(report_case_id)
|
|
138
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
139
|
+
CONSTRAINT fk_replies_parent
|
|
140
|
+
FOREIGN KEY (report_case_id, parent_reply_id)
|
|
141
|
+
REFERENCES replies(report_case_id, reply_id)
|
|
142
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
143
|
+
CONSTRAINT fk_replies_author
|
|
144
|
+
FOREIGN KEY (author_id) REFERENCES users(user_id)
|
|
145
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
146
|
+
CONSTRAINT fk_replies_assignee
|
|
147
|
+
FOREIGN KEY (assignee_id) REFERENCES users(user_id)
|
|
148
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
149
|
+
CONSTRAINT fk_replies_previous_assignee
|
|
150
|
+
FOREIGN KEY (previous_assignee_id) REFERENCES users(user_id)
|
|
151
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
152
|
+
CHECK (parent_reply_id IS NULL OR parent_reply_id <> reply_id),
|
|
153
|
+
CHECK (
|
|
154
|
+
(status_code = 1 AND deleted_at IS NULL)
|
|
155
|
+
OR (status_code = 2 AND deleted_at IS NOT NULL)
|
|
156
|
+
),
|
|
157
|
+
CHECK (
|
|
158
|
+
length(reply_id) = 36
|
|
159
|
+
AND reply_id = lower(reply_id)
|
|
160
|
+
AND substr(reply_id, 9, 1) = '-'
|
|
161
|
+
AND substr(reply_id, 14, 1) = '-'
|
|
162
|
+
AND substr(reply_id, 19, 1) = '-'
|
|
163
|
+
AND substr(reply_id, 24, 1) = '-'
|
|
164
|
+
AND replace(reply_id, '-', '') NOT GLOB '*[^0-9a-f]*'
|
|
165
|
+
)
|
|
166
|
+
) STRICT;
|
|
167
|
+
|
|
168
|
+
CREATE INDEX ix_replies_report_case_created_at
|
|
169
|
+
ON replies (report_case_id, created_at, reply_id);
|
|
170
|
+
|
|
171
|
+
CREATE INDEX ix_replies_parent
|
|
172
|
+
ON replies (parent_reply_id, created_at, reply_id);
|
|
173
|
+
|
|
174
|
+
CREATE TABLE page_elements (
|
|
175
|
+
page_element_id TEXT PRIMARY KEY,
|
|
176
|
+
mention_id TEXT NOT NULL UNIQUE,
|
|
177
|
+
label TEXT NOT NULL
|
|
178
|
+
CHECK (length(label) BETWEEN 1 AND 200 AND label = trim(label) AND instr(label, char(0)) = 0),
|
|
179
|
+
data_report_id TEXT
|
|
180
|
+
CHECK (data_report_id IS NULL OR (length(data_report_id) BETWEEN 1 AND 255 AND data_report_id = trim(data_report_id) AND instr(data_report_id, char(0)) = 0)),
|
|
181
|
+
selector TEXT NOT NULL
|
|
182
|
+
CHECK (length(selector) BETWEEN 1 AND 2000 AND selector = trim(selector) AND instr(selector, char(0)) = 0),
|
|
183
|
+
created_by TEXT NOT NULL,
|
|
184
|
+
created_at TEXT NOT NULL,
|
|
185
|
+
CONSTRAINT fk_page_elements_creator
|
|
186
|
+
FOREIGN KEY (created_by) REFERENCES users(user_id)
|
|
187
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
188
|
+
CHECK (
|
|
189
|
+
length(page_element_id) = 36
|
|
190
|
+
AND page_element_id = lower(page_element_id)
|
|
191
|
+
AND substr(page_element_id, 9, 1) = '-'
|
|
192
|
+
AND substr(page_element_id, 14, 1) = '-'
|
|
193
|
+
AND substr(page_element_id, 19, 1) = '-'
|
|
194
|
+
AND substr(page_element_id, 24, 1) = '-'
|
|
195
|
+
AND replace(page_element_id, '-', '') NOT GLOB '*[^0-9a-f]*'
|
|
196
|
+
),
|
|
197
|
+
CHECK (
|
|
198
|
+
length(mention_id) = 36
|
|
199
|
+
AND mention_id = lower(mention_id)
|
|
200
|
+
AND substr(mention_id, 9, 1) = '-'
|
|
201
|
+
AND substr(mention_id, 14, 1) = '-'
|
|
202
|
+
AND substr(mention_id, 19, 1) = '-'
|
|
203
|
+
AND substr(mention_id, 24, 1) = '-'
|
|
204
|
+
AND replace(mention_id, '-', '') NOT GLOB '*[^0-9a-f]*'
|
|
205
|
+
)
|
|
206
|
+
) STRICT;
|
|
207
|
+
|
|
208
|
+
CREATE TABLE report_case_page_elements (
|
|
209
|
+
report_case_id TEXT NOT NULL,
|
|
210
|
+
page_element_id TEXT NOT NULL,
|
|
211
|
+
CONSTRAINT pk_report_case_page_elements PRIMARY KEY (report_case_id, page_element_id),
|
|
212
|
+
CONSTRAINT fk_report_case_page_elements_case
|
|
213
|
+
FOREIGN KEY (report_case_id) REFERENCES report_cases(report_case_id)
|
|
214
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
215
|
+
CONSTRAINT fk_report_case_page_elements_element
|
|
216
|
+
FOREIGN KEY (page_element_id) REFERENCES page_elements(page_element_id)
|
|
217
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT
|
|
218
|
+
) STRICT;
|
|
219
|
+
|
|
220
|
+
CREATE INDEX ix_report_case_page_elements_element
|
|
221
|
+
ON report_case_page_elements (page_element_id, report_case_id);
|
|
222
|
+
|
|
223
|
+
CREATE TABLE reply_page_elements (
|
|
224
|
+
reply_id TEXT NOT NULL,
|
|
225
|
+
page_element_id TEXT NOT NULL,
|
|
226
|
+
CONSTRAINT pk_reply_page_elements PRIMARY KEY (reply_id, page_element_id),
|
|
227
|
+
CONSTRAINT fk_reply_page_elements_reply
|
|
228
|
+
FOREIGN KEY (reply_id) REFERENCES replies(reply_id)
|
|
229
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT,
|
|
230
|
+
CONSTRAINT fk_reply_page_elements_element
|
|
231
|
+
FOREIGN KEY (page_element_id) REFERENCES page_elements(page_element_id)
|
|
232
|
+
ON UPDATE RESTRICT ON DELETE RESTRICT
|
|
233
|
+
) STRICT;
|
|
234
|
+
|
|
235
|
+
CREATE INDEX ix_reply_page_elements_element
|
|
236
|
+
ON reply_page_elements (page_element_id, reply_id);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
CREATE INDEX ix_project_members_project_joined_at
|
|
2
|
+
ON project_members (project_id, joined_at, user_id);
|
|
3
|
+
|
|
4
|
+
CREATE INDEX ix_users_status_user_name
|
|
5
|
+
ON users (status_code, user_name, user_id);
|
|
6
|
+
|
|
7
|
+
CREATE TRIGGER tr_project_members_keep_owner_on_update
|
|
8
|
+
BEFORE UPDATE OF project_id, role_code ON project_members
|
|
9
|
+
FOR EACH ROW
|
|
10
|
+
WHEN OLD.role_code = 1
|
|
11
|
+
AND (NEW.project_id <> OLD.project_id OR NEW.role_code <> 1)
|
|
12
|
+
AND (
|
|
13
|
+
SELECT COUNT(*)
|
|
14
|
+
FROM project_members
|
|
15
|
+
WHERE project_id = OLD.project_id
|
|
16
|
+
AND role_code = 1
|
|
17
|
+
) <= 1
|
|
18
|
+
BEGIN
|
|
19
|
+
SELECT RAISE(ABORT, 'project-owner-required');
|
|
20
|
+
END;
|
|
21
|
+
|
|
22
|
+
CREATE TRIGGER tr_project_members_keep_owner_on_replace
|
|
23
|
+
BEFORE INSERT ON project_members
|
|
24
|
+
FOR EACH ROW
|
|
25
|
+
WHEN NEW.role_code <> 1
|
|
26
|
+
AND EXISTS (
|
|
27
|
+
SELECT 1
|
|
28
|
+
FROM project_members
|
|
29
|
+
WHERE project_id = NEW.project_id
|
|
30
|
+
AND user_id = NEW.user_id
|
|
31
|
+
AND role_code = 1
|
|
32
|
+
)
|
|
33
|
+
AND (
|
|
34
|
+
SELECT COUNT(*)
|
|
35
|
+
FROM project_members
|
|
36
|
+
WHERE project_id = NEW.project_id
|
|
37
|
+
AND role_code = 1
|
|
38
|
+
) <= 1
|
|
39
|
+
BEGIN
|
|
40
|
+
SELECT RAISE(ABORT, 'project-owner-required');
|
|
41
|
+
END;
|
|
42
|
+
|
|
43
|
+
CREATE TRIGGER tr_project_members_keep_owner_on_delete
|
|
44
|
+
BEFORE DELETE ON project_members
|
|
45
|
+
FOR EACH ROW
|
|
46
|
+
WHEN OLD.role_code = 1
|
|
47
|
+
AND (
|
|
48
|
+
SELECT COUNT(*)
|
|
49
|
+
FROM project_members
|
|
50
|
+
WHERE project_id = OLD.project_id
|
|
51
|
+
AND role_code = 1
|
|
52
|
+
) <= 1
|
|
53
|
+
BEGIN
|
|
54
|
+
SELECT RAISE(ABORT, 'project-owner-required');
|
|
55
|
+
END;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
-- Preflight in migrate.ts rejects schema drift and inconsistent credential keys.
|
|
2
|
+
-- Only this unreferenced child table is rebuilt. foreign_keys stays ON.
|
|
3
|
+
CREATE TABLE local_credentials_v6 (
|
|
4
|
+
user_id TEXT PRIMARY KEY
|
|
5
|
+
, login_id TEXT COLLATE NOCASE NOT NULL
|
|
6
|
+
, email TEXT NOT NULL
|
|
7
|
+
, password_hash TEXT NOT NULL
|
|
8
|
+
, failed_login_count INTEGER NOT NULL DEFAULT 0
|
|
9
|
+
, locked_until TEXT
|
|
10
|
+
, email_verified_at TEXT
|
|
11
|
+
, password_changed_at TEXT NOT NULL
|
|
12
|
+
, last_login_at TEXT
|
|
13
|
+
, lock_version INTEGER NOT NULL DEFAULT 0
|
|
14
|
+
, created_at TEXT NOT NULL
|
|
15
|
+
, updated_at TEXT NOT NULL
|
|
16
|
+
, CONSTRAINT fk_local_credentials_user FOREIGN KEY (user_id)
|
|
17
|
+
REFERENCES users (user_id) ON DELETE RESTRICT
|
|
18
|
+
, CHECK (login_id = trim(login_id) AND length(login_id) BETWEEN 4 AND 50)
|
|
19
|
+
, CHECK (substr(login_id, 1, 1) GLOB '[A-Za-z0-9]')
|
|
20
|
+
, CHECK (login_id NOT GLOB '*[^A-Za-z0-9._-]*')
|
|
21
|
+
, CHECK (email = trim(email) AND length(email) BETWEEN 3 AND 320)
|
|
22
|
+
, CHECK (password_hash = trim(password_hash) AND length(password_hash) BETWEEN 20 AND 512)
|
|
23
|
+
, CHECK (failed_login_count >= 0)
|
|
24
|
+
, CHECK (lock_version >= 0)
|
|
25
|
+
) STRICT;
|
|
26
|
+
|
|
27
|
+
INSERT INTO local_credentials_v6 (user_id, login_id, email, password_hash, failed_login_count, locked_until, email_verified_at, password_changed_at, last_login_at, lock_version, created_at, updated_at)
|
|
28
|
+
SELECT user_id, login_id, email, password_hash, failed_login_count, locked_until, email_verified_at, password_changed_at, last_login_at, lock_version, created_at, updated_at FROM local_credentials;
|
|
29
|
+
|
|
30
|
+
DROP TABLE local_credentials;
|
|
31
|
+
ALTER TABLE local_credentials_v6 RENAME TO local_credentials;
|
|
32
|
+
CREATE UNIQUE INDEX uq_local_credentials_login_id ON local_credentials (login_id);
|
|
33
|
+
CREATE UNIQUE INDEX uq_local_credentials_email ON local_credentials (email);
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
-- Frozen v1 conversion functions are registered by migrate.ts.
|
|
2
|
+
-- Preflight counts and validates the affected rows; no identifiers/versions/passwords change.
|
|
3
|
+
|
|
4
|
+
UPDATE users
|
|
5
|
+
SET created_at = fp_storage_timestamp_v1(created_at),
|
|
6
|
+
updated_at = fp_storage_timestamp_v1(updated_at)
|
|
7
|
+
WHERE created_at IS NOT NULL OR updated_at IS NOT NULL;
|
|
8
|
+
|
|
9
|
+
UPDATE local_credentials
|
|
10
|
+
SET locked_until = fp_storage_timestamp_v1(locked_until),
|
|
11
|
+
email_verified_at = fp_storage_timestamp_v1(email_verified_at),
|
|
12
|
+
password_changed_at = fp_storage_timestamp_v1(password_changed_at),
|
|
13
|
+
last_login_at = fp_storage_timestamp_v1(last_login_at),
|
|
14
|
+
created_at = fp_storage_timestamp_v1(created_at),
|
|
15
|
+
updated_at = fp_storage_timestamp_v1(updated_at)
|
|
16
|
+
WHERE locked_until IS NOT NULL OR email_verified_at IS NOT NULL OR password_changed_at IS NOT NULL OR last_login_at IS NOT NULL OR created_at IS NOT NULL OR updated_at IS NOT NULL;
|
|
17
|
+
|
|
18
|
+
UPDATE auth_refresh_tokens
|
|
19
|
+
SET expires_at = fp_storage_timestamp_v1(expires_at),
|
|
20
|
+
last_used_at = fp_storage_timestamp_v1(last_used_at),
|
|
21
|
+
revoked_at = fp_storage_timestamp_v1(revoked_at),
|
|
22
|
+
created_at = fp_storage_timestamp_v1(created_at)
|
|
23
|
+
WHERE expires_at IS NOT NULL OR last_used_at IS NOT NULL OR revoked_at IS NOT NULL OR created_at IS NOT NULL;
|
|
24
|
+
|
|
25
|
+
UPDATE projects
|
|
26
|
+
SET created_at = fp_storage_timestamp_v1(created_at),
|
|
27
|
+
updated_at = fp_storage_timestamp_v1(updated_at)
|
|
28
|
+
WHERE created_at IS NOT NULL OR updated_at IS NOT NULL;
|
|
29
|
+
|
|
30
|
+
UPDATE project_members
|
|
31
|
+
SET joined_at = fp_storage_timestamp_v1(joined_at),
|
|
32
|
+
updated_at = fp_storage_timestamp_v1(updated_at)
|
|
33
|
+
WHERE joined_at IS NOT NULL OR updated_at IS NOT NULL;
|
|
34
|
+
|
|
35
|
+
UPDATE feedbacks
|
|
36
|
+
SET created_at = fp_storage_timestamp_v1(created_at),
|
|
37
|
+
updated_at = fp_storage_timestamp_v1(updated_at)
|
|
38
|
+
WHERE created_at IS NOT NULL OR updated_at IS NOT NULL;
|
|
39
|
+
|
|
40
|
+
UPDATE replies
|
|
41
|
+
SET deleted_at = fp_storage_timestamp_v1(deleted_at),
|
|
42
|
+
created_at = fp_storage_timestamp_v1(created_at),
|
|
43
|
+
updated_at = fp_storage_timestamp_v1(updated_at)
|
|
44
|
+
WHERE deleted_at IS NOT NULL OR created_at IS NOT NULL OR updated_at IS NOT NULL;
|
|
45
|
+
|
|
46
|
+
UPDATE report_cases
|
|
47
|
+
SET resolved_at = fp_storage_timestamp_v1(resolved_at),
|
|
48
|
+
created_at = fp_storage_timestamp_v1(created_at),
|
|
49
|
+
updated_at = fp_storage_timestamp_v1(updated_at)
|
|
50
|
+
WHERE resolved_at IS NOT NULL OR created_at IS NOT NULL OR updated_at IS NOT NULL;
|
|
51
|
+
|
|
52
|
+
UPDATE page_elements
|
|
53
|
+
SET created_at = fp_storage_timestamp_v1(created_at)
|
|
54
|
+
WHERE created_at IS NOT NULL;
|
|
55
|
+
|
|
56
|
+
UPDATE feedbacks
|
|
57
|
+
SET pathname_hash = fp_pathname_hash_v1(pathname)
|
|
58
|
+
WHERE pathname_hash <> fp_pathname_hash_v1(pathname);
|
|
59
|
+
|
|
60
|
+
-- Preserve paging performance for SQL Server-compatible GUID tie breakers.
|
|
61
|
+
DROP INDEX ix_projects_status_created_at;
|
|
62
|
+
CREATE INDEX ix_projects_status_created_at ON projects (status_code, created_at DESC, (substr(project_id, 25, 12) || substr(project_id, 20, 4) || substr(project_id, 17, 2) || substr(project_id, 15, 2) || substr(project_id, 12, 2) || substr(project_id, 10, 2) || substr(project_id, 7, 2) || substr(project_id, 5, 2) || substr(project_id, 3, 2) || substr(project_id, 1, 2)) DESC);
|
|
63
|
+
DROP INDEX ix_projects_creator_created_at;
|
|
64
|
+
CREATE INDEX ix_projects_creator_created_at ON projects (creator_id, created_at DESC, (substr(project_id, 25, 12) || substr(project_id, 20, 4) || substr(project_id, 17, 2) || substr(project_id, 15, 2) || substr(project_id, 12, 2) || substr(project_id, 10, 2) || substr(project_id, 7, 2) || substr(project_id, 5, 2) || substr(project_id, 3, 2) || substr(project_id, 1, 2)) DESC);
|
|
65
|
+
DROP INDEX ix_project_members_project_joined_at;
|
|
66
|
+
CREATE INDEX ix_project_members_project_joined_at ON project_members (project_id, joined_at, (substr(user_id, 25, 12) || substr(user_id, 20, 4) || substr(user_id, 17, 2) || substr(user_id, 15, 2) || substr(user_id, 12, 2) || substr(user_id, 10, 2) || substr(user_id, 7, 2) || substr(user_id, 5, 2) || substr(user_id, 3, 2) || substr(user_id, 1, 2)));
|
|
67
|
+
DROP INDEX ix_feedbacks_markers;
|
|
68
|
+
CREATE INDEX ix_feedbacks_markers ON feedbacks (project_id, environment, pathname_hash, status_code, created_at DESC, (substr(feedback_id, 25, 12) || substr(feedback_id, 20, 4) || substr(feedback_id, 17, 2) || substr(feedback_id, 15, 2) || substr(feedback_id, 12, 2) || substr(feedback_id, 10, 2) || substr(feedback_id, 7, 2) || substr(feedback_id, 5, 2) || substr(feedback_id, 3, 2) || substr(feedback_id, 1, 2)) DESC);
|
|
69
|
+
DROP INDEX ix_feedbacks_author_created_at;
|
|
70
|
+
CREATE INDEX ix_feedbacks_author_created_at ON feedbacks (author_id, created_at DESC, (substr(feedback_id, 25, 12) || substr(feedback_id, 20, 4) || substr(feedback_id, 17, 2) || substr(feedback_id, 15, 2) || substr(feedback_id, 12, 2) || substr(feedback_id, 10, 2) || substr(feedback_id, 7, 2) || substr(feedback_id, 5, 2) || substr(feedback_id, 3, 2) || substr(feedback_id, 1, 2)) DESC);
|
|
71
|
+
DROP INDEX ix_report_cases_feedback_status_created_at;
|
|
72
|
+
CREATE INDEX ix_report_cases_feedback_status_created_at ON report_cases (feedback_id, status_code, created_at DESC, (substr(report_case_id, 25, 12) || substr(report_case_id, 20, 4) || substr(report_case_id, 17, 2) || substr(report_case_id, 15, 2) || substr(report_case_id, 12, 2) || substr(report_case_id, 10, 2) || substr(report_case_id, 7, 2) || substr(report_case_id, 5, 2) || substr(report_case_id, 3, 2) || substr(report_case_id, 1, 2)) DESC);
|
|
73
|
+
DROP INDEX ix_replies_report_case_created_at;
|
|
74
|
+
CREATE INDEX ix_replies_report_case_created_at ON replies (report_case_id, created_at, (substr(reply_id, 25, 12) || substr(reply_id, 20, 4) || substr(reply_id, 17, 2) || substr(reply_id, 15, 2) || substr(reply_id, 12, 2) || substr(reply_id, 10, 2) || substr(reply_id, 7, 2) || substr(reply_id, 5, 2) || substr(reply_id, 3, 2) || substr(reply_id, 1, 2)));
|
|
75
|
+
DROP INDEX ix_users_status_user_name;
|
|
76
|
+
CREATE INDEX ix_users_status_user_name ON users (status_code, user_name, (substr(user_id, 25, 12) || substr(user_id, 20, 4) || substr(user_id, 17, 2) || substr(user_id, 15, 2) || substr(user_id, 12, 2) || substr(user_id, 10, 2) || substr(user_id, 7, 2) || substr(user_id, 5, 2) || substr(user_id, 3, 2) || substr(user_id, 1, 2)));
|
|
77
|
+
CREATE INDEX ix_feedbacks_path_created_at ON feedbacks (project_id, environment, pathname_hash, created_at DESC, (substr(feedback_id, 25, 12) || substr(feedback_id, 20, 4) || substr(feedback_id, 17, 2) || substr(feedback_id, 15, 2) || substr(feedback_id, 12, 2) || substr(feedback_id, 10, 2) || substr(feedback_id, 7, 2) || substr(feedback_id, 5, 2) || substr(feedback_id, 3, 2) || substr(feedback_id, 1, 2)) DESC);
|
|
78
|
+
CREATE INDEX ix_report_cases_feedback_created_at ON report_cases (feedback_id, created_at DESC, (substr(report_case_id, 25, 12) || substr(report_case_id, 20, 4) || substr(report_case_id, 17, 2) || substr(report_case_id, 15, 2) || substr(report_case_id, 12, 2) || substr(report_case_id, 10, 2) || substr(report_case_id, 7, 2) || substr(report_case_id, 5, 2) || substr(report_case_id, 3, 2) || substr(report_case_id, 1, 2)) DESC);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SqliteDatabase } from './connection.js';
|
|
2
|
+
interface PriorMigration {
|
|
3
|
+
sql: string;
|
|
4
|
+
version: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function assertDatabaseIntegrity(database: SqliteDatabase): void;
|
|
7
|
+
export declare function prepareStorageMigration(database: SqliteDatabase, prior: PriorMigration[], version: number): () => void;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=storage-migration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-migration.d.ts","sourceRoot":"","sources":["../../src/db/storage-migration.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGtD,UAAU,cAAc;IAAG,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AAQzD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAKtE;AAID,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,cAAc,EAAE,EACvB,OAAO,EAAE,MAAM,GACd,MAAM,IAAI,CA0DZ"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import BetterSqlite3 from 'better-sqlite3';
|
|
2
|
+
import { pathnameHash, storageTimestamp } from '../storage/values.js';
|
|
3
|
+
function schema(database) {
|
|
4
|
+
return database.prepare("SELECT name, type, sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%' ORDER BY name, type").all();
|
|
5
|
+
}
|
|
6
|
+
export function assertDatabaseIntegrity(database) {
|
|
7
|
+
if (database.pragma('foreign_keys', { simple: true }) !== 1)
|
|
8
|
+
throw new Error('foreign-keys-required');
|
|
9
|
+
if (database.pragma('foreign_key_check').length !== 0)
|
|
10
|
+
throw new Error('foreign-key-check-failed');
|
|
11
|
+
const integrity = database.pragma('integrity_check');
|
|
12
|
+
if (integrity.length !== 1 || integrity[0]?.integrity_check !== 'ok')
|
|
13
|
+
throw new Error('integrity-check-failed');
|
|
14
|
+
}
|
|
15
|
+
// Reject unknown schema rather than dropping custom columns, indices, triggers or dependencies.
|
|
16
|
+
// This guard runs under the same IMMEDIATE transaction as the migration itself.
|
|
17
|
+
export function prepareStorageMigration(database, prior, version) {
|
|
18
|
+
assertDatabaseIntegrity(database);
|
|
19
|
+
const expected = new BetterSqlite3(':memory:');
|
|
20
|
+
try {
|
|
21
|
+
for (const migration of prior) {
|
|
22
|
+
if (migration.version < version)
|
|
23
|
+
expected.exec(migration.sql);
|
|
24
|
+
}
|
|
25
|
+
if (JSON.stringify(schema(expected)) !== JSON.stringify(schema(database))) {
|
|
26
|
+
throw new Error('unsupported-custom-schema');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
expected.close();
|
|
31
|
+
}
|
|
32
|
+
if (version === 6) {
|
|
33
|
+
const credentials = database.prepare('SELECT login_id, normalized_login_id, email, normalized_email FROM local_credentials').iterate();
|
|
34
|
+
for (const row of credentials) {
|
|
35
|
+
if (row.normalized_login_id !== row.login_id.toLowerCase()
|
|
36
|
+
|| row.normalized_email !== row.email || row.email !== row.email.trim().toLowerCase()) {
|
|
37
|
+
throw new Error('inconsistent-credential-keys');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const tables = schema(database).filter((row) => row.type === 'table' && row.name !== 'schema_migrations');
|
|
42
|
+
// Table/column names below have just been compared against bundled, trusted migrations.
|
|
43
|
+
const before = tables.map(({ name }) => ({
|
|
44
|
+
name,
|
|
45
|
+
count: database.prepare(`SELECT COUNT(*) AS count FROM "${name}"`).get().count,
|
|
46
|
+
}));
|
|
47
|
+
if (version === 7) {
|
|
48
|
+
for (const table of tables) {
|
|
49
|
+
const columns = database.prepare('SELECT name FROM pragma_table_xinfo(?)').all(table.name);
|
|
50
|
+
for (const { name } of columns.filter((column) => column.name.endsWith('_at') || column.name === 'locked_until')) {
|
|
51
|
+
for (const row of database.prepare(`SELECT "${name}" AS value FROM "${table.name}" WHERE "${name}" IS NOT NULL`).iterate()) {
|
|
52
|
+
const value = row.value;
|
|
53
|
+
storageTimestamp(value);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
database.function('fp_storage_timestamp_v1', { deterministic: true }, (value) => {
|
|
58
|
+
if (value === null)
|
|
59
|
+
return null;
|
|
60
|
+
if (typeof value !== 'string')
|
|
61
|
+
throw new Error('invalid-storage-timestamp');
|
|
62
|
+
return storageTimestamp(value);
|
|
63
|
+
});
|
|
64
|
+
database.function('fp_pathname_hash_v1', { deterministic: true }, (value) => {
|
|
65
|
+
if (typeof value !== 'string')
|
|
66
|
+
throw new Error('invalid-storage-pathname');
|
|
67
|
+
return pathnameHash(value);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return () => {
|
|
71
|
+
for (const { name, count } of before) {
|
|
72
|
+
if (database.prepare(`SELECT COUNT(*) AS count FROM "${name}"`).get().count !== count) {
|
|
73
|
+
throw new Error('migration-row-count-mismatch');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
assertDatabaseIntegrity(database);
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=storage-migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-migration.js","sourceRoot":"","sources":["../../src/db/storage-migration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SqliteDatabase } from './connection.js';
|
|
2
|
+
/** Shared synchronous transaction boundary; every participant uses this connection. */
|
|
3
|
+
export declare class TransactionRunner {
|
|
4
|
+
private readonly database;
|
|
5
|
+
constructor(database: SqliteDatabase);
|
|
6
|
+
write<T>(operation: () => T): T;
|
|
7
|
+
read<T>(operation: () => T): T;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=transaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../../src/db/transaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,uFAAuF;AACvF,qBAAa,iBAAiB;IACT,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,cAAc;IAErD,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC;IAI/B,IAAI,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC;CAGtC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Shared synchronous transaction boundary; every participant uses this connection. */
|
|
2
|
+
export class TransactionRunner {
|
|
3
|
+
database;
|
|
4
|
+
constructor(database) {
|
|
5
|
+
this.database = database;
|
|
6
|
+
}
|
|
7
|
+
write(operation) {
|
|
8
|
+
return this.database.transaction(operation).immediate();
|
|
9
|
+
}
|
|
10
|
+
read(operation) {
|
|
11
|
+
return this.database.transaction(operation)();
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=transaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../src/db/transaction.ts"],"names":[],"mappings":"AAEA,uFAAuF;AACvF,MAAM,OAAO,iBAAiB;IACQ;IAApC,YAAoC,QAAwB;QAAxB,aAAQ,GAAR,QAAQ,CAAgB;IAAG,CAAC;IAEzD,KAAK,CAAI,SAAkB;QAChC,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE,CAAC;IAC1D,CAAC;IAEM,IAAI,CAAI,SAAkB;QAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;IAChD,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../src/errors/error-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAwC7E,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI,CAoChE"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
function sendError(reply, request, statusCode, code, message, details) {
|
|
2
|
+
void reply.code(statusCode).send({
|
|
3
|
+
error: {
|
|
4
|
+
code,
|
|
5
|
+
message,
|
|
6
|
+
requestId: request.id,
|
|
7
|
+
...(details === undefined ? {} : { details }),
|
|
8
|
+
},
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
function errorDetails(error) {
|
|
12
|
+
return typeof error === 'object' && error !== null ? error : {};
|
|
13
|
+
}
|
|
14
|
+
function isSqliteBusy(error) {
|
|
15
|
+
const code = errorDetails(error).code;
|
|
16
|
+
return code === 'SQLITE_BUSY' || code === 'SQLITE_LOCKED';
|
|
17
|
+
}
|
|
18
|
+
export function registerErrorHandlers(app) {
|
|
19
|
+
app.setNotFoundHandler((request, reply) => {
|
|
20
|
+
sendError(reply, request, 404, 'NOT_FOUND', 'Resource not found.');
|
|
21
|
+
});
|
|
22
|
+
app.setErrorHandler((error, request, reply) => {
|
|
23
|
+
const knownError = errorDetails(error);
|
|
24
|
+
if (knownError.validation !== undefined) {
|
|
25
|
+
const details = knownError.validation.map((issue) => ({
|
|
26
|
+
path: issue.instancePath || '/',
|
|
27
|
+
message: issue.message ?? 'Invalid value.',
|
|
28
|
+
}));
|
|
29
|
+
sendError(reply, request, 400, 'VALIDATION_ERROR', 'Invalid request.', details);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (isSqliteBusy(error)) {
|
|
33
|
+
request.log.warn({ err: error }, 'SQLite is busy');
|
|
34
|
+
void reply.header('Retry-After', '1');
|
|
35
|
+
sendError(reply, request, 503, 'SERVICE_BUSY', 'Service is temporarily busy.');
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (knownError.code === 'FST_ERR_CTP_BODY_TOO_LARGE') {
|
|
39
|
+
sendError(reply, request, 413, 'VALIDATION_ERROR', 'Request body is too large.');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (knownError.statusCode === 400) {
|
|
43
|
+
sendError(reply, request, 400, 'VALIDATION_ERROR', 'Invalid request.');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
request.log.error({ err: error }, 'Unhandled request error');
|
|
47
|
+
sendError(reply, request, 500, 'INTERNAL_ERROR', 'Internal server error.');
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=error-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/errors/error-handler.ts"],"names":[],"mappings":"AAOA,SAAS,SAAS,CAChB,KAAmB,EACnB,OAAuB,EACvB,UAAkB,EAClB,IAAY,EACZ,OAAe,EACf,OAAuB;IAEvB,KAAK,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;QAC/B,KAAK,EAAE;YACL,IAAI;YACJ,OAAO;YACP,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;SAC9C;KACF,CAAC,CAAC;AACL,CAAC;AAQD,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAClE,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC;IACtC,OAAO,IAAI,KAAK,aAAa,IAAI,IAAI,KAAK,eAAe,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAAoB;IACxD,GAAG,CAAC,kBAAkB,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;QACxC,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,qBAAqB,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,eAAe,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC5C,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,UAAU,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACxC,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACpD,IAAI,EAAE,KAAK,CAAC,YAAY,IAAI,GAAG;gBAC/B,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,gBAAgB;aAC3C,CAAC,CAAC,CAAC;YACJ,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,OAAO,CAAC,CAAC;YAChF,OAAO;QACT,CAAC;QAED,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,gBAAgB,CAAC,CAAC;YACnD,KAAK,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;YACtC,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,8BAA8B,CAAC,CAAC;YAC/E,OAAO;QACT,CAAC;QAED,IAAI,UAAU,CAAC,IAAI,KAAK,4BAA4B,EAAE,CAAC;YACrD,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,kBAAkB,EAAE,4BAA4B,CAAC,CAAC;YACjF,OAAO;QACT,CAAC;QAED,IAAI,UAAU,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;YAClC,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,kBAAkB,EAAE,kBAAkB,CAAC,CAAC;YACvE,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,yBAAyB,CAAC,CAAC;QAC7D,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,gBAAgB,EAAE,wBAAwB,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;AACL,CAAC"}
|