create-safest-tools 0.2.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.
Files changed (240) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +71 -0
  3. package/bin/create-safest-tools.mjs +12 -0
  4. package/package.json +34 -0
  5. package/src/cli.mjs +128 -0
  6. package/src/config.mjs +151 -0
  7. package/src/scaffold.mjs +30 -0
  8. package/template/LICENSE +201 -0
  9. package/template/README.md +35 -0
  10. package/template/console/README.md +28 -0
  11. package/template/console/analytics/AnalyticsWorkspace.tsx +55 -0
  12. package/template/console/analytics/controller.ts +133 -0
  13. package/template/console/analytics/events.ts +33 -0
  14. package/template/console/analytics/store.ts +33 -0
  15. package/template/console/analytics/types.ts +38 -0
  16. package/template/console/appeals/AppealWorkspace.tsx +73 -0
  17. package/template/console/appeals/controller.ts +125 -0
  18. package/template/console/appeals/events.ts +33 -0
  19. package/template/console/appeals/store.ts +35 -0
  20. package/template/console/appeals/types.ts +37 -0
  21. package/template/console/assistant/AssistantWorkspace.tsx +133 -0
  22. package/template/console/assistant/types.ts +34 -0
  23. package/template/console/auth/AccountJourney.tsx +69 -0
  24. package/template/console/auth/InvitationAcceptance.tsx +145 -0
  25. package/template/console/auth/OAuthButtons.tsx +78 -0
  26. package/template/console/auth/OperatorLogin.tsx +110 -0
  27. package/template/console/auth/PasswordRecovery.tsx +132 -0
  28. package/template/console/auth/account-route.ts +15 -0
  29. package/template/console/auth/browser-navigation.ts +7 -0
  30. package/template/console/auth/events.ts +15 -0
  31. package/template/console/command/CommandCentre.tsx +119 -0
  32. package/template/console/command/controller.ts +267 -0
  33. package/template/console/command/events.ts +19 -0
  34. package/template/console/command/store.ts +36 -0
  35. package/template/console/command/types.ts +61 -0
  36. package/template/console/components/AnalystIdentity.tsx +25 -0
  37. package/template/console/components/PageHeader.tsx +27 -0
  38. package/template/console/configuration/ConfigurationDialog.tsx +200 -0
  39. package/template/console/configuration/ConfigurationWorkspace.tsx +66 -0
  40. package/template/console/configuration/FormBuilder.tsx +143 -0
  41. package/template/console/configuration/api.ts +40 -0
  42. package/template/console/configuration/events.ts +14 -0
  43. package/template/console/configuration/types.ts +79 -0
  44. package/template/console/lib/format.ts +49 -0
  45. package/template/console/lib/http.ts +96 -0
  46. package/template/console/main.tsx +225 -0
  47. package/template/console/operations/OperationsWorkspace.tsx +126 -0
  48. package/template/console/operations/controller.ts +237 -0
  49. package/template/console/operations/events.ts +37 -0
  50. package/template/console/operations/store.ts +32 -0
  51. package/template/console/operations/types.ts +107 -0
  52. package/template/console/people/PeopleWorkspace.tsx +81 -0
  53. package/template/console/people/types.ts +25 -0
  54. package/template/console/profile/ProfileWorkspace.tsx +136 -0
  55. package/template/console/profile/events.ts +9 -0
  56. package/template/console/profile/types.ts +6 -0
  57. package/template/console/quality/QualityWorkspace.tsx +87 -0
  58. package/template/console/quality/controller.ts +154 -0
  59. package/template/console/quality/events.ts +34 -0
  60. package/template/console/quality/store.ts +36 -0
  61. package/template/console/quality/types.ts +70 -0
  62. package/template/console/queues/QueueEditor.tsx +173 -0
  63. package/template/console/queues/QueueWorkspace.tsx +109 -0
  64. package/template/console/queues/controller.ts +194 -0
  65. package/template/console/queues/events.ts +34 -0
  66. package/template/console/queues/store.ts +37 -0
  67. package/template/console/queues/types.ts +102 -0
  68. package/template/console/registry/RegistryDialog.tsx +198 -0
  69. package/template/console/registry/RegistryWorkspace.tsx +108 -0
  70. package/template/console/registry/events.ts +14 -0
  71. package/template/console/registry/types.ts +52 -0
  72. package/template/console/reports/ReportDrawer.tsx +159 -0
  73. package/template/console/reports/ReportWorkspace.tsx +90 -0
  74. package/template/console/reports/controller.ts +517 -0
  75. package/template/console/reports/events.ts +42 -0
  76. package/template/console/reports/store.ts +39 -0
  77. package/template/console/reports/types.ts +230 -0
  78. package/template/console/settings/BrandEditor.tsx +126 -0
  79. package/template/console/settings/ChannelDialog.tsx +241 -0
  80. package/template/console/settings/SettingsWorkspace.tsx +155 -0
  81. package/template/console/settings/events.ts +19 -0
  82. package/template/console/settings/handoff.ts +22 -0
  83. package/template/console/settings/types.ts +93 -0
  84. package/template/console/shell/WorkspaceShell.tsx +160 -0
  85. package/template/console/shell/controller.ts +182 -0
  86. package/template/console/shell/events.ts +25 -0
  87. package/template/console/shell/navigation.ts +61 -0
  88. package/template/console/shell/store.ts +56 -0
  89. package/template/console/shell/types.ts +86 -0
  90. package/template/console/workflows/CreateWorkflowDialog.tsx +87 -0
  91. package/template/console/workflows/WorkflowCanvas.tsx +42 -0
  92. package/template/console/workflows/WorkflowDialogs.tsx +6 -0
  93. package/template/console/workflows/WorkflowStudio.tsx +331 -0
  94. package/template/console/workflows/WorkflowWorkspace.tsx +82 -0
  95. package/template/console/workflows/events.ts +17 -0
  96. package/template/console/workflows/graph.ts +156 -0
  97. package/template/console/workflows/templates.ts +70 -0
  98. package/template/console/workflows/types.ts +201 -0
  99. package/template/gitignore.template +18 -0
  100. package/template/migrations/0001_reports_foundation.sql +444 -0
  101. package/template/migrations/0002_human_report_loop.sql +65 -0
  102. package/template/migrations/0003_delivery_reliability.sql +18 -0
  103. package/template/migrations/0004_public_intake.sql +14 -0
  104. package/template/migrations/0005_operations_visibility.sql +24 -0
  105. package/template/migrations/0006_ai_governance.sql +198 -0
  106. package/template/migrations/0007_ai_release_gates.sql +6 -0
  107. package/template/migrations/0008_retention_analytics_exports.sql +52 -0
  108. package/template/migrations/0009_retention_derived_copies.sql +14 -0
  109. package/template/migrations/0010_ai_quality_controls.sql +26 -0
  110. package/template/migrations/0011_analyst_presence.sql +28 -0
  111. package/template/migrations/0012_queue_policies.sql +87 -0
  112. package/template/migrations/0013_routing_agents.sql +63 -0
  113. package/template/migrations/0014_webhook_enrichments.sql +122 -0
  114. package/template/migrations/0015_queue_owned_ai.sql +55 -0
  115. package/template/migrations/0016_operator_accounts.sql +67 -0
  116. package/template/migrations/0017_operator_profiles_and_recovery.sql +33 -0
  117. package/template/migrations/0018_platform_configuration.sql +382 -0
  118. package/template/migrations/0019_workflow_authoring_runtime.sql +372 -0
  119. package/template/migrations/0020_tasks_findings_assistant_budgets.sql +427 -0
  120. package/template/migrations/0021_abuse_evidence_operations.sql +324 -0
  121. package/template/migrations/0022_workflow_dispatch_operations.sql +42 -0
  122. package/template/migrations/0023_component_connection_execution.sql +75 -0
  123. package/template/migrations/0024_access_runtime_integrity.sql +72 -0
  124. package/template/migrations/0025_installation_timezone.sql +11 -0
  125. package/template/migrations/0026_ai_and_egress_execution_controls.sql +49 -0
  126. package/template/migrations/0027_prompt_and_ai_registry.sql +37 -0
  127. package/template/migrations/0028_step_attempt_ai_provenance.sql +13 -0
  128. package/template/migrations/0029_evidence_fetch_transport.sql +5 -0
  129. package/template/migrations/0030_evidence_dlq_incidents.sql +45 -0
  130. package/template/migrations/0031_shadow_quality_integrity.sql +7 -0
  131. package/template/migrations/0032_action_delivery_outbox.sql +55 -0
  132. package/template/migrations/0033_configuration_and_assistant_drafts.sql +43 -0
  133. package/template/migrations/0034_installation_integrations.sql +31 -0
  134. package/template/migrations/0035_workspace_governance.sql +21 -0
  135. package/template/migrations/0036_published_routing_baseline.sql +15 -0
  136. package/template/migrations/0037_builtin_phishing_specialist.sql +71 -0
  137. package/template/migrations/0038_remove_deprecated_enrichment_runtime.sql +228 -0
  138. package/template/migrations/0039_secure_reporting_channels.sql +45 -0
  139. package/template/migrations/0040_notification_only_reporting.sql +24 -0
  140. package/template/migrations/0041_better_auth_credentials.sql +17 -0
  141. package/template/package.json +47 -0
  142. package/template/public/_headers +27 -0
  143. package/template/public/app-icon-192.png +0 -0
  144. package/template/public/app-icon-512.png +0 -0
  145. package/template/public/brand-icon.svg +7 -0
  146. package/template/public/brand-tokens.css +80 -0
  147. package/template/public/console/auth-shell.js +19340 -0
  148. package/template/public/customer-brand.js +58 -0
  149. package/template/public/embed/embed.css +139 -0
  150. package/template/public/embed/embed.js +408 -0
  151. package/template/public/embed/index.html +91 -0
  152. package/template/public/favicon.svg +7 -0
  153. package/template/public/fonts/Manrope-Variable.ttf +0 -0
  154. package/template/public/fonts/Newsreader-Italic-Variable.ttf +0 -0
  155. package/template/public/fonts/Newsreader-Variable.ttf +0 -0
  156. package/template/public/index.html +123 -0
  157. package/template/public/logo-primary.svg +7 -0
  158. package/template/public/logo-reversed.svg +7 -0
  159. package/template/public/manifest.webmanifest +21 -0
  160. package/template/public/public-report.js +184 -0
  161. package/template/public/report/index.html +39 -0
  162. package/template/public/report/public-report.css +20 -0
  163. package/template/public/social-card.png +0 -0
  164. package/template/public/styles.css +1521 -0
  165. package/template/public/widget.css +80 -0
  166. package/template/public/widget.js +220 -0
  167. package/template/reports.config.example.json +38 -0
  168. package/template/reports.schema.json +89 -0
  169. package/template/scripts/reports-auth-onboarding.mjs +180 -0
  170. package/template/scripts/reports-backup.mjs +276 -0
  171. package/template/scripts/reports-cloudflare-preflight.mjs +152 -0
  172. package/template/scripts/reports-deploy.mjs +173 -0
  173. package/template/scripts/reports-plan.mjs +226 -0
  174. package/template/scripts/reports-restore.mjs +180 -0
  175. package/template/scripts/reports-secrets.mjs +73 -0
  176. package/template/scripts/reports-uninstall-plan.mjs +32 -0
  177. package/template/src/agent-executor.ts +330 -0
  178. package/template/src/ai-observability.ts +163 -0
  179. package/template/src/ai-registry-validation.ts +244 -0
  180. package/template/src/ai-registry.ts +292 -0
  181. package/template/src/api-cursor.ts +84 -0
  182. package/template/src/assistant.ts +554 -0
  183. package/template/src/audit.ts +39 -0
  184. package/template/src/backup-service.ts +269 -0
  185. package/template/src/budget-control.ts +127 -0
  186. package/template/src/component-executor.ts +845 -0
  187. package/template/src/configuration-registry.ts +550 -0
  188. package/template/src/connection-egress.ts +430 -0
  189. package/template/src/connection-oauth.ts +368 -0
  190. package/template/src/evidence-service.ts +335 -0
  191. package/template/src/human-tasks.ts +316 -0
  192. package/template/src/index.ts +4114 -0
  193. package/template/src/installation-admin.ts +301 -0
  194. package/template/src/intake-abuse.ts +156 -0
  195. package/template/src/platform-registry-validation.ts +367 -0
  196. package/template/src/platform-registry.ts +753 -0
  197. package/template/src/report-admin.ts +342 -0
  198. package/template/src/report-ai-quality.ts +390 -0
  199. package/template/src/report-ai-validation.ts +80 -0
  200. package/template/src/report-ai.ts +857 -0
  201. package/template/src/report-auth.ts +292 -0
  202. package/template/src/report-better-auth.ts +583 -0
  203. package/template/src/report-context-schema.ts +132 -0
  204. package/template/src/report-context.ts +126 -0
  205. package/template/src/report-crypto.ts +142 -0
  206. package/template/src/report-delivery.ts +579 -0
  207. package/template/src/report-form-validation.ts +51 -0
  208. package/template/src/report-governance.ts +510 -0
  209. package/template/src/report-http.ts +90 -0
  210. package/template/src/report-operations.ts +685 -0
  211. package/template/src/report-operator-accounts.ts +810 -0
  212. package/template/src/report-presence.ts +398 -0
  213. package/template/src/report-queue-validation.ts +309 -0
  214. package/template/src/report-queues.ts +478 -0
  215. package/template/src/report-repository.ts +972 -0
  216. package/template/src/report-router-agent.ts +328 -0
  217. package/template/src/report-router-validation.ts +81 -0
  218. package/template/src/report-routing.ts +178 -0
  219. package/template/src/report-turnstile.ts +142 -0
  220. package/template/src/report-types.ts +224 -0
  221. package/template/src/report-validation.ts +279 -0
  222. package/template/src/report-workflow-validation.ts +119 -0
  223. package/template/src/report-workflow.ts +886 -0
  224. package/template/src/shadow-quality.ts +278 -0
  225. package/template/src/workflow-actions.ts +782 -0
  226. package/template/src/workflow-compiler.ts +230 -0
  227. package/template/src/workflow-dynamic-runtime.ts +613 -0
  228. package/template/src/workflow-effects.ts +316 -0
  229. package/template/src/workflow-expressions.ts +191 -0
  230. package/template/src/workflow-platform-types.ts +121 -0
  231. package/template/src/workflow-platform-validation.ts +540 -0
  232. package/template/src/workflow-repository.ts +916 -0
  233. package/template/src/workflow-runs.ts +686 -0
  234. package/template/src/workflow-simulator.ts +211 -0
  235. package/template/src/workspace-branding.ts +128 -0
  236. package/template/src/workspace-governance.ts +279 -0
  237. package/template/tsconfig.console.json +23 -0
  238. package/template/tsconfig.json +22 -0
  239. package/template/vite.console.config.ts +20 -0
  240. package/template/worker-configuration.d.ts +65 -0
@@ -0,0 +1,7 @@
1
+ PRAGMA foreign_keys = ON;
2
+
3
+ CREATE UNIQUE INDEX shadow_comparisons_one_per_shadow_run_idx
4
+ ON shadow_comparisons(shadow_run_id);
5
+
6
+ CREATE INDEX findings_shadow_comparison_idx
7
+ ON findings(run_id, status, created_at DESC, id DESC);
@@ -0,0 +1,55 @@
1
+ PRAGMA foreign_keys = ON;
2
+
3
+ ALTER TABLE action_proposals ADD COLUMN delivery_attempt_count INTEGER NOT NULL DEFAULT 0 CHECK (delivery_attempt_count >= 0);
4
+ ALTER TABLE action_proposals ADD COLUMN next_attempt_at TEXT;
5
+ ALTER TABLE action_proposals ADD COLUMN lease_expires_at TEXT;
6
+ ALTER TABLE action_proposals ADD COLUMN last_error_code TEXT;
7
+ ALTER TABLE action_proposals ADD COLUMN delivery_terminal INTEGER NOT NULL DEFAULT 0 CHECK (delivery_terminal IN (0, 1));
8
+
9
+ CREATE INDEX action_proposals_delivery_due_idx
10
+ ON action_proposals(state, delivery_terminal, next_attempt_at, id);
11
+
12
+ ALTER TABLE dead_letter_items RENAME TO dead_letter_items_v5;
13
+
14
+ CREATE TABLE dead_letter_items (
15
+ id TEXT PRIMARY KEY,
16
+ fingerprint TEXT NOT NULL UNIQUE,
17
+ source_queue TEXT NOT NULL,
18
+ source_message_id TEXT NOT NULL,
19
+ job_type TEXT NOT NULL CHECK (job_type IN (
20
+ 'route_report', 'process_ai_report', 'run_enrichment', 'fetch_evidence',
21
+ 'dispatch_workflow', 'deliver_action', 'deliver_notification', 'deliver_email',
22
+ 'apply_action_proposal', 'invalid'
23
+ )),
24
+ job_id TEXT,
25
+ report_id TEXT REFERENCES reports(id),
26
+ outbox_id TEXT,
27
+ incident_id TEXT REFERENCES operations_incidents(id) ON DELETE SET NULL,
28
+ state TEXT NOT NULL DEFAULT 'open' CHECK (state IN ('open', 'acknowledged', 'resolved')),
29
+ error_code TEXT NOT NULL,
30
+ occurrence_count INTEGER NOT NULL DEFAULT 1 CHECK (occurrence_count > 0),
31
+ details_json TEXT NOT NULL DEFAULT '{}',
32
+ first_seen_at TEXT NOT NULL,
33
+ last_seen_at TEXT NOT NULL,
34
+ resolved_at TEXT
35
+ );
36
+
37
+ INSERT INTO dead_letter_items (
38
+ id, fingerprint, source_queue, source_message_id, job_type, job_id,
39
+ report_id, outbox_id, incident_id, state, error_code, occurrence_count,
40
+ details_json, first_seen_at, last_seen_at, resolved_at
41
+ )
42
+ SELECT
43
+ id, fingerprint, source_queue, source_message_id, job_type, job_id,
44
+ report_id, outbox_id, incident_id, state, error_code, occurrence_count,
45
+ details_json, first_seen_at, last_seen_at, resolved_at
46
+ FROM dead_letter_items_v5;
47
+
48
+ DROP TABLE dead_letter_items_v5;
49
+
50
+ CREATE INDEX dead_letter_items_state_idx
51
+ ON dead_letter_items(state, last_seen_at DESC, id DESC);
52
+ CREATE INDEX dead_letter_items_report_idx
53
+ ON dead_letter_items(report_id, last_seen_at DESC, id DESC);
54
+ CREATE INDEX dead_letter_items_incident_idx
55
+ ON dead_letter_items(incident_id, state, last_seen_at DESC, id DESC);
@@ -0,0 +1,43 @@
1
+ PRAGMA foreign_keys = ON;
2
+
3
+ CREATE TABLE configuration_drafts (
4
+ id TEXT PRIMARY KEY,
5
+ installation_id TEXT NOT NULL REFERENCES installations(id) ON DELETE CASCADE,
6
+ configuration_type TEXT NOT NULL CHECK (configuration_type IN ('form', 'policy', 'template', 'routing_rules')),
7
+ configuration_key TEXT NOT NULL,
8
+ content_json TEXT NOT NULL,
9
+ content_digest TEXT NOT NULL,
10
+ validation_json TEXT NOT NULL DEFAULT '{"valid":false,"errors":[{"code":"not_validated"}]}',
11
+ validation_status TEXT NOT NULL DEFAULT 'not_validated' CHECK (validation_status IN ('not_validated', 'valid', 'invalid')),
12
+ revision INTEGER NOT NULL DEFAULT 1 CHECK (revision >= 1),
13
+ last_published_version_id TEXT,
14
+ created_by TEXT NOT NULL,
15
+ updated_by TEXT NOT NULL,
16
+ created_at TEXT NOT NULL,
17
+ updated_at TEXT NOT NULL,
18
+ UNIQUE (installation_id, configuration_type, configuration_key)
19
+ );
20
+
21
+ CREATE INDEX configuration_drafts_type_idx
22
+ ON configuration_drafts(installation_id, configuration_type, configuration_key);
23
+
24
+ CREATE TABLE assistant_drafts (
25
+ id TEXT PRIMARY KEY,
26
+ installation_id TEXT NOT NULL REFERENCES installations(id) ON DELETE CASCADE,
27
+ session_id TEXT NOT NULL REFERENCES assistant_sessions(id) ON DELETE CASCADE,
28
+ principal_id TEXT NOT NULL,
29
+ draft_type TEXT NOT NULL CHECK (draft_type IN ('workflow', 'form', 'policy', 'template', 'routing_rules')),
30
+ target_id TEXT,
31
+ title TEXT NOT NULL,
32
+ content_json TEXT NOT NULL,
33
+ content_digest TEXT NOT NULL,
34
+ status TEXT NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'adopted', 'expired')),
35
+ idempotency_key TEXT NOT NULL,
36
+ created_at TEXT NOT NULL,
37
+ adopted_at TEXT,
38
+ adopted_target_id TEXT,
39
+ UNIQUE (session_id, idempotency_key)
40
+ );
41
+
42
+ CREATE INDEX assistant_drafts_principal_idx
43
+ ON assistant_drafts(principal_id, status, created_at DESC, id DESC);
@@ -0,0 +1,31 @@
1
+ PRAGMA foreign_keys = ON;
2
+
3
+ ALTER TABLE installations ADD COLUMN settings_json TEXT NOT NULL DEFAULT '{}';
4
+ ALTER TABLE application_integrations ADD COLUMN scopes_json TEXT NOT NULL DEFAULT '["submit_reports","mint_context_tokens"]';
5
+
6
+ CREATE TABLE integration_api_keys (
7
+ id TEXT PRIMARY KEY,
8
+ integration_id TEXT NOT NULL REFERENCES application_integrations(id) ON DELETE CASCADE,
9
+ key_id TEXT NOT NULL UNIQUE,
10
+ key_hash TEXT NOT NULL UNIQUE,
11
+ status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'revoked', 'expired')),
12
+ valid_from TEXT NOT NULL,
13
+ expires_at TEXT,
14
+ created_by TEXT NOT NULL,
15
+ created_at TEXT NOT NULL,
16
+ revoked_by TEXT,
17
+ revoked_at TEXT
18
+ );
19
+
20
+ CREATE INDEX integration_api_keys_auth_idx
21
+ ON integration_api_keys(integration_id, status, valid_from, expires_at, id);
22
+
23
+ INSERT OR IGNORE INTO installation_features (
24
+ installation_id, feature_key, state, capability_json, checked_at, revision
25
+ ) VALUES
26
+ ('default', 'database', 'ready', '{}', strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), 1),
27
+ ('default', 'workflow_runtime', 'setup_required', '{}', strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), 1),
28
+ ('default', 'workers_ai', 'setup_required', '{}', strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), 1),
29
+ ('default', 'object_storage', 'setup_required', '{}', strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), 1),
30
+ ('default', 'queues', 'setup_required', '{}', strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), 1),
31
+ ('default', 'email', 'disabled', '{}', strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), 1);
@@ -0,0 +1,21 @@
1
+ PRAGMA foreign_keys = ON;
2
+
3
+ CREATE TABLE saved_views (
4
+ id TEXT PRIMARY KEY,
5
+ installation_id TEXT NOT NULL REFERENCES installations(id) ON DELETE CASCADE,
6
+ principal_id TEXT NOT NULL,
7
+ name TEXT NOT NULL,
8
+ filters_json TEXT NOT NULL,
9
+ created_at TEXT NOT NULL,
10
+ updated_at TEXT NOT NULL,
11
+ UNIQUE (installation_id, principal_id, name)
12
+ );
13
+
14
+ CREATE INDEX saved_views_principal_idx
15
+ ON saved_views(installation_id, principal_id, updated_at DESC, id DESC);
16
+
17
+ ALTER TABLE export_jobs ADD COLUMN idempotency_key TEXT;
18
+
19
+ CREATE UNIQUE INDEX export_jobs_idempotency_idx
20
+ ON export_jobs(installation_id, requested_by, idempotency_key)
21
+ WHERE idempotency_key IS NOT NULL;
@@ -0,0 +1,15 @@
1
+ PRAGMA foreign_keys = ON;
2
+
3
+ INSERT INTO routing_rule_versions (
4
+ id, installation_id, version, rules_json, fixture_results_json,
5
+ published_at, created_by, created_at
6
+ )
7
+ SELECT
8
+ 'default-routing-v1', 'default', 1,
9
+ '{"default_queue_id":"standard-human","safeguard_queue_id":"urgent-human","intake_enrichment_component_ids":[],"rules":[],"fixtures":[]}',
10
+ '{"valid":true,"tested_at":"migration"}',
11
+ strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), 'system', strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
12
+ WHERE NOT EXISTS (
13
+ SELECT 1 FROM routing_rule_versions
14
+ WHERE installation_id = 'default' AND published_at IS NOT NULL
15
+ );
@@ -0,0 +1,71 @@
1
+ -- Supply the first immutable Safest-owned specialist component.
2
+
3
+ INSERT OR IGNORE INTO component_definitions (
4
+ id, installation_id, component_key, name, description, component_kind,
5
+ effect_class, owner_kind, status, active_version_id, created_by,
6
+ created_at, updated_at
7
+ ) VALUES (
8
+ 'safest-builtin-phishing-url', 'default', 'safest-builtin-phishing-url',
9
+ 'Phishing URL specialist',
10
+ 'Deterministic, read-only URL normalization and phishing-risk signals. It never fetches the submitted URL and records unavailable reputation/content checks as uncertainty.',
11
+ 'specialist_agent', 'read_only', 'safest', 'active', NULL, 'system',
12
+ strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
13
+ );
14
+
15
+ INSERT OR IGNORE INTO component_versions (
16
+ id, definition_id, version, implementation_kind, implementation_reference,
17
+ input_schema_json, output_schema_json, allowed_input_fields_json,
18
+ data_classifications_json, connection_version_id, risk_class,
19
+ timeout_policy_json, retry_policy_json, cache_policy_json,
20
+ concurrency_policy_json, budget_policy_json, approval_policy_json,
21
+ tool_manifest_json, compatibility_json, package_digest,
22
+ signature_metadata_json, published_at, retired_at, created_by, created_at
23
+ )
24
+ SELECT
25
+ 'safest-builtin-phishing-url-v1', 'safest-builtin-phishing-url', 1,
26
+ 'specialist_agent', 'phishing-url-v1',
27
+ '{"type":"object","additionalProperties":false,"required":["url"],"properties":{"url":{"type":"string","minLength":1,"maxLength":2048}}}',
28
+ '{"type":"object","additionalProperties":false,"required":["normalized_url","normalized_url_hash","hostname_hash","scheme","signals","conclusion","summary","uncertainty","confidence"],"properties":{"normalized_url":{"type":"string"},"normalized_url_hash":{"type":"string"},"hostname_hash":{"type":"string"},"scheme":{"type":"string","enum":["http","https"]},"signals":{"type":"array","items":{"type":"string"}},"conclusion":{"type":"string","enum":["likely_phishing","suspicious","no_phishing_signal","unavailable","escalate"]},"summary":{"type":"string"},"uncertainty":{"type":"array","items":{"type":"string"}},"confidence":{"type":"number","minimum":0,"maximum":1}}}',
29
+ '["target.customer_url","answers.url"]',
30
+ '["report_operational","potentially_sensitive_url"]', NULL, 'low',
31
+ '{"timeout_ms":1500}', '{"maximum_attempts":1}',
32
+ '{"enabled":true,"ttl_seconds":3600,"key_fields":["url"]}',
33
+ '{"maximum_concurrency":20}', '{"metric":"calls","maximum_per_day":10000}',
34
+ '{}', '["url_parser","hostname_heuristics"]',
35
+ '{"fixture_evidence":{"passed":true,"validated_by":"safest_release","fixtures":["suspicious-login-url"]},"network_access":false,"runtime_protocol":"1"}',
36
+ 'sha256:a2072d7111273ad5038ae0f2e11c3e3e227972a56b8ed71162a5f402d889829d',
37
+ '{"publisher":"safest","source":"built_in","digest_basis":"src/component-executor.ts"}',
38
+ strftime('%Y-%m-%dT%H:%M:%fZ', 'now'), NULL, 'system',
39
+ strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
40
+ WHERE EXISTS (SELECT 1 FROM component_definitions WHERE id = 'safest-builtin-phishing-url');
41
+
42
+ UPDATE component_definitions
43
+ SET active_version_id = 'safest-builtin-phishing-url-v1',
44
+ updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
45
+ WHERE id = 'safest-builtin-phishing-url'
46
+ AND EXISTS (SELECT 1 FROM component_versions WHERE id = 'safest-builtin-phishing-url-v1');
47
+
48
+ INSERT OR IGNORE INTO component_fixtures (
49
+ id, component_version_id, name, input_json, expected_json,
50
+ expected_status, created_by, created_at
51
+ )
52
+ SELECT
53
+ 'safest-builtin-phishing-url-v1-fixture-suspicious',
54
+ 'safest-builtin-phishing-url-v1', 'suspicious-login-url',
55
+ '{"url":"http://login.verify.example.com/account"}',
56
+ '{"normalized_url":"http://login.verify.example.com/account","normalized_url_hash":"sha256:f19ea3e9f98e298edbff77f8bd16194a45dc0b8677fc43ef1430904cd91a8355","hostname_hash":"sha256:852ead493ae4fd09da4de58d1f1ba7f9f96a464fc73662f110fb8a1044ebd249","scheme":"http","signals":["credential_lure_term","plaintext_transport"],"conclusion":"suspicious","summary":"Observed 2 deterministic phishing-risk signal(s).","uncertainty":["dns_reputation_and_content_not_checked"],"confidence":0.69}',
57
+ 'succeeded', 'system', strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
58
+ WHERE EXISTS (SELECT 1 FROM component_versions WHERE id = 'safest-builtin-phishing-url-v1');
59
+
60
+ INSERT OR IGNORE INTO component_test_runs (
61
+ id, component_version_id, fixture_id, status, output_json,
62
+ error_code, started_by, started_at, finished_at
63
+ )
64
+ SELECT
65
+ 'safest-builtin-phishing-url-v1-test-suspicious',
66
+ 'safest-builtin-phishing-url-v1',
67
+ 'safest-builtin-phishing-url-v1-fixture-suspicious', 'passed',
68
+ '{"mode":"simulated","validated_by":"safest_release","network_access":false}',
69
+ NULL, 'system', strftime('%Y-%m-%dT%H:%M:%fZ', 'now'),
70
+ strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
71
+ WHERE EXISTS (SELECT 1 FROM component_fixtures WHERE id = 'safest-builtin-phishing-url-v1-fixture-suspicious');
@@ -0,0 +1,228 @@
1
+ PRAGMA foreign_keys = ON;
2
+
3
+ -- Preserve webhook definitions created after the component registry was introduced.
4
+ INSERT OR IGNORE INTO connection_definitions (
5
+ id, installation_id, connection_key, name, description, kind, status,
6
+ active_version_id, created_by, created_at, updated_at
7
+ )
8
+ SELECT
9
+ 'legacy-enrichment-connection:' || d.id,
10
+ d.installation_id,
11
+ 'legacy-' || d.enrichment_key,
12
+ d.name || ' connection',
13
+ d.description,
14
+ 'webhook',
15
+ CASE d.status WHEN 'paused' THEN 'paused' WHEN 'archived' THEN 'archived' ELSE 'active' END,
16
+ 'legacy-enrichment-connection-version:' || d.active_version_id,
17
+ d.created_by,
18
+ d.created_at,
19
+ d.updated_at
20
+ FROM enrichment_definitions d;
21
+
22
+ INSERT OR IGNORE INTO connection_versions (
23
+ id, connection_id, version, base_url, service_binding_name,
24
+ allowed_hosts_json, allowed_methods_json, allowed_path_prefixes_json,
25
+ redirect_policy_json, request_limit_bytes, response_limit_bytes,
26
+ response_content_types_json, timeout_ms, concurrency_limit,
27
+ requests_per_window, window_seconds, credential_strategy, secret_reference,
28
+ signing_strategy_json, oauth_configuration_json, published_at, retired_at,
29
+ created_by, created_at
30
+ )
31
+ SELECT
32
+ 'legacy-enrichment-connection-version:' || v.id,
33
+ 'legacy-enrichment-connection:' || v.definition_id,
34
+ v.version,
35
+ v.webhook_url,
36
+ NULL,
37
+ '[]',
38
+ '["POST"]',
39
+ '["/"]',
40
+ '{"follow":false,"maximum":0}',
41
+ 65536,
42
+ 262144,
43
+ '["application/json"]',
44
+ v.timeout_ms,
45
+ 8,
46
+ 60,
47
+ 60,
48
+ 'hmac',
49
+ v.secret_binding,
50
+ '{"kind":"safest_hmac_v1"}',
51
+ '{}',
52
+ v.published_at,
53
+ NULL,
54
+ v.created_by,
55
+ v.created_at
56
+ FROM enrichment_definition_versions v;
57
+
58
+ UPDATE connection_versions
59
+ SET allowed_hosts_json = json_array(
60
+ substr(
61
+ base_url,
62
+ instr(base_url, '://') + 3,
63
+ CASE
64
+ WHEN instr(substr(base_url, instr(base_url, '://') + 3), '/') = 0
65
+ THEN length(base_url)
66
+ ELSE instr(substr(base_url, instr(base_url, '://') + 3), '/') - 1
67
+ END
68
+ )
69
+ )
70
+ WHERE id LIKE 'legacy-enrichment-connection-version:%';
71
+
72
+ INSERT OR IGNORE INTO connection_health (
73
+ connection_version_id, state, consecutive_failures, revision, updated_at
74
+ )
75
+ SELECT
76
+ 'legacy-enrichment-connection-version:' || v.id,
77
+ 'unknown',
78
+ 0,
79
+ 1,
80
+ v.created_at
81
+ FROM enrichment_definition_versions v;
82
+
83
+ INSERT OR IGNORE INTO component_definitions (
84
+ id, installation_id, component_key, name, description, component_kind,
85
+ effect_class, owner_kind, status, active_version_id, created_by, created_at, updated_at
86
+ )
87
+ SELECT
88
+ d.id,
89
+ d.installation_id,
90
+ d.enrichment_key,
91
+ d.name,
92
+ d.description,
93
+ 'webhook_enrichment',
94
+ 'read_only',
95
+ 'customer',
96
+ CASE d.status WHEN 'paused' THEN 'paused' WHEN 'archived' THEN 'archived' ELSE 'active' END,
97
+ d.active_version_id,
98
+ d.created_by,
99
+ d.created_at,
100
+ d.updated_at
101
+ FROM enrichment_definitions d;
102
+
103
+ INSERT OR IGNORE INTO component_versions (
104
+ id, definition_id, version, implementation_kind, implementation_reference,
105
+ input_schema_json, output_schema_json, allowed_input_fields_json,
106
+ data_classifications_json, connection_version_id, risk_class,
107
+ timeout_policy_json, retry_policy_json, cache_policy_json,
108
+ concurrency_policy_json, budget_policy_json, approval_policy_json,
109
+ tool_manifest_json, compatibility_json, published_at, created_by, created_at
110
+ )
111
+ SELECT
112
+ v.id,
113
+ v.definition_id,
114
+ v.version,
115
+ 'webhook',
116
+ v.webhook_url,
117
+ json_object('type', 'object', 'properties', json(v.input_fields_json)),
118
+ v.output_schema_json,
119
+ v.input_fields_json,
120
+ '["report_operational"]',
121
+ 'legacy-enrichment-connection-version:' || v.id,
122
+ 'low',
123
+ json_object('timeout_ms', v.timeout_ms),
124
+ json_object('maximum_attempts', v.max_attempts, 'backoff', 'exponential'),
125
+ json_object('enabled', CASE WHEN v.ttl_seconds > 0 THEN json('true') ELSE json('false') END, 'ttl_seconds', v.ttl_seconds),
126
+ '{"maximum_concurrency":8}',
127
+ '{}',
128
+ '{}',
129
+ '[]',
130
+ '{}',
131
+ v.published_at,
132
+ v.created_by,
133
+ v.created_at
134
+ FROM enrichment_definition_versions v;
135
+
136
+ UPDATE component_versions
137
+ SET compatibility_json = json_remove(compatibility_json, '$.legacy_enrichment')
138
+ WHERE json_type(compatibility_json, '$.legacy_enrichment') IS NOT NULL;
139
+
140
+ -- Convert the pre-mapping routing field, then make the explicit mapping shape canonical.
141
+ UPDATE routing_rule_versions
142
+ SET rules_json = json_set(
143
+ rules_json,
144
+ '$.intake_enrichments',
145
+ COALESCE(
146
+ (
147
+ SELECT json_group_array(json_object(
148
+ 'component_version_id', value,
149
+ 'input_mapping', json('{}')
150
+ ))
151
+ FROM json_each(routing_rule_versions.rules_json, '$.intake_enrichment_component_ids')
152
+ WHERE type = 'text'
153
+ ),
154
+ json('[]')
155
+ )
156
+ )
157
+ WHERE json_type(rules_json, '$.intake_enrichment_component_ids') = 'array'
158
+ AND json_type(rules_json, '$.intake_enrichments') IS NULL;
159
+
160
+ UPDATE routing_rule_versions
161
+ SET rules_json = json_remove(rules_json, '$.intake_enrichment_component_ids')
162
+ WHERE json_type(rules_json, '$.intake_enrichment_component_ids') IS NOT NULL;
163
+
164
+ UPDATE queue_versions
165
+ SET routing_criteria_json = '{"match":"all","conditions":[]}',
166
+ enrichment_requirements_json = '[]';
167
+
168
+ DROP TABLE enrichment_results;
169
+ DROP TABLE enrichment_attempts;
170
+ DROP TABLE enrichment_requests;
171
+ DROP TABLE enrichment_definition_versions;
172
+ DROP TABLE enrichment_definitions;
173
+
174
+ -- Retain direct human-decision and appeal action delivery as a distinct, accurately named outbox.
175
+ DROP INDEX action_outbox_due_idx;
176
+ DROP INDEX action_outbox_reconcile_idx;
177
+ ALTER TABLE action_outbox RENAME TO decision_action_outbox;
178
+ ALTER TABLE action_attempts RENAME TO decision_action_attempts;
179
+ CREATE INDEX decision_action_outbox_due_idx
180
+ ON decision_action_outbox(status, next_attempt_at, id);
181
+ CREATE INDEX decision_action_outbox_reconcile_idx
182
+ ON decision_action_outbox(terminal, status, next_attempt_at, lease_expires_at, id);
183
+
184
+ ALTER TABLE dead_letter_items RENAME TO dead_letter_items_v6;
185
+
186
+ CREATE TABLE dead_letter_items (
187
+ id TEXT PRIMARY KEY,
188
+ fingerprint TEXT NOT NULL UNIQUE,
189
+ source_queue TEXT NOT NULL,
190
+ source_message_id TEXT NOT NULL,
191
+ job_type TEXT NOT NULL CHECK (job_type IN (
192
+ 'route_report', 'process_ai_report', 'fetch_evidence',
193
+ 'dispatch_workflow', 'deliver_action', 'deliver_notification', 'deliver_email',
194
+ 'apply_action_proposal', 'invalid'
195
+ )),
196
+ job_id TEXT,
197
+ report_id TEXT REFERENCES reports(id),
198
+ outbox_id TEXT,
199
+ incident_id TEXT REFERENCES operations_incidents(id) ON DELETE SET NULL,
200
+ state TEXT NOT NULL DEFAULT 'open' CHECK (state IN ('open', 'acknowledged', 'resolved')),
201
+ error_code TEXT NOT NULL,
202
+ occurrence_count INTEGER NOT NULL DEFAULT 1 CHECK (occurrence_count > 0),
203
+ details_json TEXT NOT NULL DEFAULT '{}',
204
+ first_seen_at TEXT NOT NULL,
205
+ last_seen_at TEXT NOT NULL,
206
+ resolved_at TEXT
207
+ );
208
+
209
+ INSERT INTO dead_letter_items (
210
+ id, fingerprint, source_queue, source_message_id, job_type, job_id,
211
+ report_id, outbox_id, incident_id, state, error_code, occurrence_count,
212
+ details_json, first_seen_at, last_seen_at, resolved_at
213
+ )
214
+ SELECT
215
+ id, fingerprint, source_queue, source_message_id,
216
+ CASE job_type WHEN 'run_enrichment' THEN 'invalid' ELSE job_type END,
217
+ job_id, report_id, outbox_id, incident_id, state, error_code, occurrence_count,
218
+ details_json, first_seen_at, last_seen_at, resolved_at
219
+ FROM dead_letter_items_v6;
220
+
221
+ DROP TABLE dead_letter_items_v6;
222
+
223
+ CREATE INDEX dead_letter_items_state_idx
224
+ ON dead_letter_items(state, last_seen_at DESC, id DESC);
225
+ CREATE INDEX dead_letter_items_report_idx
226
+ ON dead_letter_items(report_id, last_seen_at DESC, id DESC);
227
+ CREATE INDEX dead_letter_items_incident_idx
228
+ ON dead_letter_items(incident_id, state, last_seen_at DESC, id DESC);
@@ -0,0 +1,45 @@
1
+ PRAGMA foreign_keys = ON;
2
+
3
+ ALTER TABLE application_integrations
4
+ ADD COLUMN channel_mode TEXT NOT NULL DEFAULT 'contextual'
5
+ CHECK (channel_mode IN ('contextual', 'anonymous'));
6
+
7
+ ALTER TABLE application_integrations
8
+ ADD COLUMN form_version_id TEXT REFERENCES report_form_versions(id);
9
+
10
+ ALTER TABLE application_integrations
11
+ ADD COLUMN context_schema_json TEXT NOT NULL
12
+ DEFAULT '{"version":1,"allow_unknown":true,"fields":[]}';
13
+
14
+ ALTER TABLE report_targets
15
+ ADD COLUMN routing_facts_json TEXT NOT NULL DEFAULT '{}';
16
+
17
+ UPDATE report_targets SET routing_facts_json = signed_facts_json;
18
+
19
+ CREATE TABLE report_contexts (
20
+ id TEXT PRIMARY KEY,
21
+ installation_id TEXT NOT NULL REFERENCES installations(id) ON DELETE CASCADE,
22
+ integration_id TEXT NOT NULL REFERENCES application_integrations(id) ON DELETE CASCADE,
23
+ form_version_id TEXT NOT NULL REFERENCES report_form_versions(id),
24
+ origin TEXT NOT NULL,
25
+ reporter_reference TEXT,
26
+ target_type TEXT NOT NULL,
27
+ target_reference TEXT NOT NULL,
28
+ target_owner_reference TEXT,
29
+ target_customer_url TEXT,
30
+ trusted_facts_json TEXT NOT NULL DEFAULT '{}',
31
+ routing_facts_json TEXT NOT NULL DEFAULT '{}',
32
+ context_schema_version INTEGER NOT NULL DEFAULT 1 CHECK (context_schema_version > 0),
33
+ assertion_source TEXT NOT NULL DEFAULT 'customer_backend'
34
+ CHECK (assertion_source IN ('customer_backend', 'resolve_hosted')),
35
+ created_at TEXT NOT NULL,
36
+ expires_at TEXT NOT NULL,
37
+ used_at TEXT,
38
+ report_id TEXT REFERENCES reports(id) ON DELETE SET NULL
39
+ );
40
+
41
+ CREATE INDEX report_contexts_expiry_idx
42
+ ON report_contexts(expires_at, used_at, id);
43
+
44
+ CREATE INDEX report_contexts_integration_idx
45
+ ON report_contexts(integration_id, created_at DESC, id);
@@ -0,0 +1,24 @@
1
+ -- Status portals and bearer capabilities are intentionally retired.
2
+ -- Reporter communication now leaves Resolve only through signed webhooks or email delivery.
3
+ DROP TABLE portal_sessions;
4
+
5
+ UPDATE report_participants
6
+ SET contact_mode = CASE
7
+ WHEN reference IS NOT NULL OR contact_ciphertext IS NOT NULL THEN 'customer_notification'
8
+ ELSE 'none'
9
+ END
10
+ WHERE contact_mode = 'portal';
11
+
12
+ CREATE TRIGGER report_participants_reject_portal_insert
13
+ BEFORE INSERT ON report_participants
14
+ WHEN NEW.contact_mode = 'portal'
15
+ BEGIN
16
+ SELECT RAISE(ABORT, 'portal contact mode has been removed');
17
+ END;
18
+
19
+ CREATE TRIGGER report_participants_reject_portal_update
20
+ BEFORE UPDATE OF contact_mode ON report_participants
21
+ WHEN NEW.contact_mode = 'portal'
22
+ BEGIN
23
+ SELECT RAISE(ABORT, 'portal contact mode has been removed');
24
+ END;
@@ -0,0 +1,17 @@
1
+ PRAGMA foreign_keys = ON;
2
+
3
+ DROP TABLE operator_password_reset_limits;
4
+ DROP TABLE operator_password_resets;
5
+ DROP TABLE operator_login_limits;
6
+
7
+ ALTER TABLE operator_sessions RENAME TO infrastructure_owner_sessions;
8
+ DROP INDEX operator_sessions_user_idx;
9
+ DROP INDEX operator_sessions_expiry_idx;
10
+ CREATE INDEX infrastructure_owner_sessions_user_idx
11
+ ON infrastructure_owner_sessions(user_id, revoked_at, expires_at DESC, id);
12
+ CREATE INDEX infrastructure_owner_sessions_expiry_idx
13
+ ON infrastructure_owner_sessions(revoked_at, expires_at, id);
14
+
15
+ ALTER TABLE operator_users DROP COLUMN password_hash;
16
+ ALTER TABLE operator_users DROP COLUMN password_salt;
17
+ ALTER TABLE operator_users DROP COLUMN password_iterations;
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "safest-resolve-installation",
3
+ "version": "0.2.0",
4
+ "safestToolsVersion": "0.2.0-resolve",
5
+ "private": true,
6
+ "license": "Apache-2.0",
7
+ "type": "module",
8
+ "scripts": {
9
+ "build": "npm run build:console",
10
+ "build:console": "vite build --config vite.console.config.ts",
11
+ "secrets:init": "node scripts/reports-secrets.mjs",
12
+ "setup": "npm run build:console && node scripts/reports-deploy.mjs",
13
+ "setup:plan": "node scripts/reports-deploy.mjs --plan",
14
+ "upgrade": "npm run backup && npm run build:console && node scripts/reports-deploy.mjs --upgrade",
15
+ "upgrade:plan": "node scripts/reports-deploy.mjs --upgrade --plan",
16
+ "backup": "node scripts/reports-backup.mjs",
17
+ "backup:plan": "node scripts/reports-backup.mjs --plan",
18
+ "restore:verify": "node scripts/reports-restore.mjs --verify",
19
+ "restore:plan": "node scripts/reports-restore.mjs --plan",
20
+ "uninstall:plan": "node scripts/reports-uninstall-plan.mjs",
21
+ "check:browser": "node --check public/console/auth-shell.js && node --check public/widget.js && node --check public/embed/embed.js && node --check public/public-report.js",
22
+ "check:console": "tsc --project tsconfig.console.json --noEmit",
23
+ "check": "npm run check:browser && npm run check:console && tsc --noEmit",
24
+ "console:dev": "vite build --config vite.console.config.ts --watch",
25
+ "deploy:dry-run": "npm run build:console && wrangler deploy --dry-run --outdir dist/reports-worker"
26
+ },
27
+ "dependencies": {
28
+ "@clack/prompts": "^1.7.0",
29
+ "@cloudflare/dynamic-workflows": "^0.1.1",
30
+ "better-auth": "^1.7.2",
31
+ "jose": "^6.2.10",
32
+ "react": "^19.2.8",
33
+ "react-dom": "^19.2.8"
34
+ },
35
+ "devDependencies": {
36
+ "@cloudflare/workers-types": "^5.20260828.1",
37
+ "@types/react": "^19.2.18",
38
+ "@types/react-dom": "^19.2.5",
39
+ "@vitejs/plugin-react": "^6.1.1",
40
+ "typescript": "^7.0.2",
41
+ "vite": "^8.2.2",
42
+ "wrangler": "^4.127.0"
43
+ },
44
+ "engines": {
45
+ "node": ">=20.12.0"
46
+ }
47
+ }
@@ -0,0 +1,27 @@
1
+ /*
2
+ Content-Security-Policy: default-src 'self'; script-src 'self' https://challenges.cloudflare.com; style-src 'self' 'unsafe-inline' https:; font-src 'self' data: https:; img-src 'self' data: https:; connect-src 'self' https://challenges.cloudflare.com; frame-src https://challenges.cloudflare.com; object-src 'none'; base-uri 'none'; frame-ancestors 'none'; form-action 'self'
3
+ Referrer-Policy: no-referrer
4
+ X-Content-Type-Options: nosniff
5
+ X-Frame-Options: DENY
6
+ Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()
7
+
8
+ /
9
+ Cache-Control: public, max-age=0, must-revalidate
10
+
11
+ /widget.js
12
+ Cache-Control: public, max-age=0, must-revalidate
13
+
14
+ /widget.css
15
+ Cache-Control: public, max-age=0, must-revalidate
16
+
17
+ /embed/*
18
+ Cache-Control: no-store
19
+
20
+ /customer-brand.js
21
+ Cache-Control: public, max-age=0, must-revalidate
22
+
23
+ /styles.css
24
+ Cache-Control: public, max-age=0, must-revalidate
25
+
26
+ /report/*
27
+ Cache-Control: no-store
Binary file
Binary file
@@ -0,0 +1,7 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-labelledby="title desc">
2
+ <title id="title">Safest app icon</title>
3
+ <desc id="desc">The Safest open-boundary mark on a deep evergreen tile.</desc>
4
+ <rect x="2" y="2" width="60" height="60" rx="17" fill="#0B2B20"/>
5
+ <path d="M 35.000 14.000 H 29.000 C 20.716 14.000 14.000 20.716 14.000 29.000 V 32.000" fill="none" stroke="#FFFFFF" stroke-width="11.500" stroke-linecap="round" stroke-linejoin="round"/>
6
+ <path d="M 29.000 50.000 H 35.000 C 43.284 50.000 50.000 43.284 50.000 35.000 V 32.000" fill="none" stroke="#CBEF68" stroke-width="11.500" stroke-linecap="round" stroke-linejoin="round"/>
7
+ </svg>