insika 0.1.0 → 0.3.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 (280) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +199 -5
  3. data/README.md +8 -2
  4. data/bin/insika +231 -13
  5. data/docs/AGENTS.md +505 -6
  6. data/docs/API.md +56 -0
  7. data/docs/CHANNELS.md +100 -10
  8. data/docs/CONTEXT.md +147 -19
  9. data/docs/DEPLOY.md +34 -11
  10. data/docs/EMBEDDING.md +11 -7
  11. data/docs/EVALS.md +20 -1
  12. data/docs/FACTS.md +135 -0
  13. data/docs/HARVEST.md +117 -0
  14. data/docs/LOADTEST.md +17 -10
  15. data/docs/OBSERVABILITY.md +65 -2
  16. data/docs/REFINEMENT.md +9 -9
  17. data/docs/RELEASING.md +34 -7
  18. data/docs/RUNNING-LOCAL.md +4 -4
  19. data/docs/SECURITY.md +85 -11
  20. data/docs/SKILLS.md +189 -3
  21. data/docs/SOAK.md +127 -0
  22. data/docs/TOOLS.md +70 -2
  23. data/docs/WHY.md +1 -1
  24. data/docs/WORKFLOWS.md +2 -2
  25. data/docs/domain.md +115 -0
  26. data/docs/index.md +2 -2
  27. data/docs/onboarding/start.md +1 -1
  28. data/lib/insika/agent_profile.rb +228 -26
  29. data/lib/insika/alert_dispatcher.rb +139 -0
  30. data/lib/insika/balloon_splitter.rb +102 -0
  31. data/lib/insika/baseline_store.rb +2 -2
  32. data/lib/insika/budget_ledger.rb +166 -0
  33. data/lib/insika/cache_series_store.rb +49 -0
  34. data/lib/insika/channel_delivery.rb +132 -24
  35. data/lib/insika/channel_registry.rb +1 -1
  36. data/lib/insika/channels/relay.rb +80 -6
  37. data/lib/insika/channels/web/widget.js +2 -2
  38. data/lib/insika/channels/web.rb +9 -9
  39. data/lib/insika/channels/webhook.rb +58 -0
  40. data/lib/insika/chat_builder.rb +145 -13
  41. data/lib/insika/checkpoint_store.rb +16 -0
  42. data/lib/insika/circuit_state.rb +114 -0
  43. data/lib/insika/coercion.rb +8 -0
  44. data/lib/insika/commands/agent_payload.rb +6 -4
  45. data/lib/insika/commands/cancel_followup.rb +49 -0
  46. data/lib/insika/commands/create_agent.rb +2 -2
  47. data/lib/insika/commands/create_session.rb +1 -1
  48. data/lib/insika/commands/delete_llm_provider.rb +1 -1
  49. data/lib/insika/commands/delete_skill.rb +43 -0
  50. data/lib/insika/commands/delete_tenant_data.rb +95 -0
  51. data/lib/insika/commands/export_customer_memory.rb +48 -0
  52. data/lib/insika/commands/forget_customer.rb +117 -0
  53. data/lib/insika/commands/freeze_funnel_baseline.rb +113 -0
  54. data/lib/insika/commands/gate_harvest.rb +138 -0
  55. data/lib/insika/commands/gate_refinement.rb +12 -12
  56. data/lib/insika/commands/import_mcp_tools.rb +1 -1
  57. data/lib/insika/commands/import_tools.rb +4 -4
  58. data/lib/insika/commands/issue_tenant_token.rb +41 -0
  59. data/lib/insika/commands/judge_shadow_pairs.rb +124 -0
  60. data/lib/insika/commands/memory_forget_fact.rb +20 -4
  61. data/lib/insika/commands/memory_put_fact.rb +23 -4
  62. data/lib/insika/commands/promote_harvest.rb +130 -0
  63. data/lib/insika/commands/record_outcome.rb +46 -0
  64. data/lib/insika/commands/record_shadow_reply.rb +68 -0
  65. data/lib/insika/commands/reject_harvest.rb +38 -0
  66. data/lib/insika/commands/resolve_proposal.rb +108 -0
  67. data/lib/insika/commands/resolve_refinement.rb +1 -1
  68. data/lib/insika/commands/revoke_contact.rb +49 -0
  69. data/lib/insika/commands/revoke_token.rb +39 -0
  70. data/lib/insika/commands/rollback_harvest.rb +86 -0
  71. data/lib/insika/commands/rotate_tenant_token.rb +43 -0
  72. data/lib/insika/commands/run_distillation.rb +186 -0
  73. data/lib/insika/commands/run_harvest.rb +393 -0
  74. data/lib/insika/commands/run_refinement.rb +5 -5
  75. data/lib/insika/commands/send_message.rb +112 -15
  76. data/lib/insika/commands/session_purge.rb +67 -0
  77. data/lib/insika/commands/set_agent_tools.rb +1 -1
  78. data/lib/insika/commands/set_skill_agents.rb +60 -19
  79. data/lib/insika/commands/trigger_workflow.rb +1 -1
  80. data/lib/insika/commands/update_agent.rb +1 -1
  81. data/lib/insika/commands/write_data_tool.rb +1 -1
  82. data/lib/insika/commands/write_golden.rb +1 -1
  83. data/lib/insika/commands/write_skill.rb +19 -9
  84. data/lib/insika/config_store.rb +8 -4
  85. data/lib/insika/contact_store.rb +183 -0
  86. data/lib/insika/context/builder.rb +23 -5
  87. data/lib/insika/context/fragment.rb +31 -3
  88. data/lib/insika/context/priority.rb +6 -2
  89. data/lib/insika/context/provider.rb +17 -3
  90. data/lib/insika/context/providers/briefing.rb +96 -0
  91. data/lib/insika/context/providers/memory.rb +16 -7
  92. data/lib/insika/context/providers/prompt.rb +30 -2
  93. data/lib/insika/context/providers/request.rb +1 -1
  94. data/lib/insika/context/providers/session.rb +17 -2
  95. data/lib/insika/context/providers/skill.rb +7 -1
  96. data/lib/insika/context/providers/skill_trigger.rb +128 -0
  97. data/lib/insika/context/providers/tool_search.rb +2 -0
  98. data/lib/insika/context_trace_store.rb +128 -0
  99. data/lib/insika/delegation_store.rb +2 -2
  100. data/lib/insika/distill.rb +224 -0
  101. data/lib/insika/distill_engine.rb +169 -0
  102. data/lib/insika/doctor.rb +962 -7
  103. data/lib/insika/dsl/runtime.rb +20 -11
  104. data/lib/insika/dsl/server_boot.rb +74 -4
  105. data/lib/insika/dsl/system.rb +1 -1
  106. data/lib/insika/dsl.rb +152 -15
  107. data/lib/insika/edge_limiter.rb +167 -8
  108. data/lib/insika/egress_guard.rb +3 -3
  109. data/lib/insika/env_schema.rb +22 -12
  110. data/lib/insika/errors.rb +72 -5
  111. data/lib/insika/evals/assertions.rb +15 -14
  112. data/lib/insika/evals/baseline.rb +3 -3
  113. data/lib/insika/evals/golden.rb +8 -8
  114. data/lib/insika/evals/judge.rb +7 -7
  115. data/lib/insika/evals/pairwise.rb +21 -9
  116. data/lib/insika/evals/report.rb +2 -2
  117. data/lib/insika/evals/runner.rb +6 -6
  118. data/lib/insika/evals/transport.rb +2 -2
  119. data/lib/insika/event_stream.rb +23 -5
  120. data/lib/insika/evidence.rb +183 -0
  121. data/lib/insika/executor.rb +1092 -160
  122. data/lib/insika/followup_engine.rb +207 -0
  123. data/lib/insika/followup_policy.rb +221 -0
  124. data/lib/insika/followup_store.rb +306 -0
  125. data/lib/insika/frontmatter.rb +1 -1
  126. data/lib/insika/funnel_declaration.rb +106 -0
  127. data/lib/insika/funnel_fold.rb +179 -0
  128. data/lib/insika/funnel_store.rb +163 -0
  129. data/lib/insika/golden_store.rb +3 -3
  130. data/lib/insika/grounding/matcher.rb +69 -0
  131. data/lib/insika/grounding.rb +44 -0
  132. data/lib/insika/harvest/conversion_gate.rb +159 -0
  133. data/lib/insika/harvest/criterion.rb +98 -0
  134. data/lib/insika/harvest/gate.rb +194 -0
  135. data/lib/insika/harvest/negative_list.rb +199 -0
  136. data/lib/insika/harvest.rb +241 -0
  137. data/lib/insika/harvest_engine.rb +193 -0
  138. data/lib/insika/harvest_store.rb +548 -0
  139. data/lib/insika/http_client.rb +3 -3
  140. data/lib/insika/inbound_log.rb +1 -1
  141. data/lib/insika/llm_configurator.rb +3 -3
  142. data/lib/insika/loop_detector.rb +143 -0
  143. data/lib/insika/mcp_http_client.rb +4 -4
  144. data/lib/insika/mcp_tool_ingestor.rb +6 -6
  145. data/lib/insika/media.rb +298 -0
  146. data/lib/insika/memory_audit_store.rb +85 -0
  147. data/lib/insika/memory_store.rb +264 -23
  148. data/lib/insika/message_origin.rb +8 -3
  149. data/lib/insika/model_resolver.rb +1 -1
  150. data/lib/insika/model_selection.rb +5 -4
  151. data/lib/insika/model_visible.rb +87 -0
  152. data/lib/insika/model_visible_trace_store.rb +66 -0
  153. data/lib/insika/onboarding.rb +8 -3
  154. data/lib/insika/outbox_store.rb +44 -6
  155. data/lib/insika/outcome_store.rb +147 -0
  156. data/lib/insika/overlay_tool_registry.rb +3 -4
  157. data/lib/insika/pack.rb +3 -3
  158. data/lib/insika/pack_importer.rb +17 -15
  159. data/lib/insika/packaging.rb +163 -0
  160. data/lib/insika/parity/criterion.rb +79 -0
  161. data/lib/insika/parity/verdict.rb +318 -0
  162. data/lib/insika/pending_action_store.rb +1 -1
  163. data/lib/insika/plugin/loader.rb +2 -2
  164. data/lib/insika/policy/policy.rb +1 -1
  165. data/lib/insika/prefix_fingerprint.rb +58 -0
  166. data/lib/insika/profile_source.rb +34 -7
  167. data/lib/insika/proposal_store.rb +271 -0
  168. data/lib/insika/provider_error_classifier.rb +160 -0
  169. data/lib/insika/queue_policy.rb +6 -3
  170. data/lib/insika/recovery.rb +47 -6
  171. data/lib/insika/refinement/candidate.rb +4 -4
  172. data/lib/insika/refinement/evidence_collector.rb +6 -6
  173. data/lib/insika/refinement/gate.rb +7 -7
  174. data/lib/insika/refinement/panel.rb +7 -7
  175. data/lib/insika/refinement/proposer.rb +10 -10
  176. data/lib/insika/refinement_store.rb +12 -12
  177. data/lib/insika/reliability.rb +211 -0
  178. data/lib/insika/retention.rb +281 -0
  179. data/lib/insika/routing.rb +101 -0
  180. data/lib/insika/safety/config.rb +46 -6
  181. data/lib/insika/safety/corpus.rb +255 -0
  182. data/lib/insika/safety/detectors.rb +34 -115
  183. data/lib/insika/safety/factory.rb +18 -5
  184. data/lib/insika/safety/grounding_enforcer.rb +59 -0
  185. data/lib/insika/safety/grounding_validator.rb +49 -0
  186. data/lib/insika/safety/input_guardrail.rb +20 -5
  187. data/lib/insika/safety/moderator.rb +19 -11
  188. data/lib/insika/safety/output_filter.rb +10 -6
  189. data/lib/insika/safety/output_validator.rb +13 -7
  190. data/lib/insika/safety/safe_responses.rb +1 -1
  191. data/lib/insika/sandbox/boundary.rb +2 -2
  192. data/lib/insika/sandbox.rb +1 -1
  193. data/lib/insika/schema_guard.rb +35 -0
  194. data/lib/insika/server/app.rb +366 -54
  195. data/lib/insika/server/boot.rb +4 -4
  196. data/lib/insika/server/rack_app.rb +31 -7
  197. data/lib/insika/server/responses.rb +58 -9
  198. data/lib/insika/server/tenant_auth.rb +61 -0
  199. data/lib/insika/session_actor.rb +11 -7
  200. data/lib/insika/session_store.rb +66 -3
  201. data/lib/insika/settings_store.rb +15 -5
  202. data/lib/insika/shadow_pair_store.rb +258 -0
  203. data/lib/insika/shutdown.rb +4 -4
  204. data/lib/insika/skill_catalog.rb +131 -20
  205. data/lib/insika/skill_store.rb +70 -22
  206. data/lib/insika/soak/envelope.rb +140 -0
  207. data/lib/insika/soak/report.rb +392 -0
  208. data/lib/insika/soak/runner.rb +554 -0
  209. data/lib/insika/steer_injector.rb +1 -1
  210. data/lib/insika/store.rb +11 -2
  211. data/lib/insika/stores/memory.rb +6 -0
  212. data/lib/insika/stores/sqlite.rb +8 -0
  213. data/lib/insika/studio/app.rb +1058 -75
  214. data/lib/insika/studio/assets/dist/application.css +1 -1
  215. data/lib/insika/studio/assets/dist/application.js +27 -26
  216. data/lib/insika/studio/assets/dist/favicon.svg +6 -0
  217. data/lib/insika/studio/forms.rb +274 -22
  218. data/lib/insika/studio/nav_icons.rb +7 -2
  219. data/lib/insika/studio/views/_message.erb +2 -2
  220. data/lib/insika/studio/views/agent_detail.erb +629 -86
  221. data/lib/insika/studio/views/agents.erb +11 -7
  222. data/lib/insika/studio/views/approvals.erb +4 -1
  223. data/lib/insika/studio/views/chats.erb +4 -1
  224. data/lib/insika/studio/views/customer.erb +94 -0
  225. data/lib/insika/studio/views/customers.erb +32 -0
  226. data/lib/insika/studio/views/evals.erb +4 -1
  227. data/lib/insika/studio/views/facts.erb +133 -0
  228. data/lib/insika/studio/views/followups.erb +125 -0
  229. data/lib/insika/studio/views/funnel.erb +106 -0
  230. data/lib/insika/studio/views/harvest.erb +234 -0
  231. data/lib/insika/studio/views/home.erb +2 -1
  232. data/lib/insika/studio/views/layout.erb +1 -0
  233. data/lib/insika/studio/views/parity.erb +147 -0
  234. data/lib/insika/studio/views/playground.erb +7 -1
  235. data/lib/insika/studio/views/refinement.erb +4 -4
  236. data/lib/insika/studio/views/session.erb +133 -3
  237. data/lib/insika/studio/views/settings.erb +9 -12
  238. data/lib/insika/studio/views/skills.erb +66 -12
  239. data/lib/insika/studio/views/system_files.erb +1 -1
  240. data/lib/insika/studio/views/task.erb +13 -0
  241. data/lib/insika/studio/views/tasks.erb +4 -1
  242. data/lib/insika/studio/views/tools.erb +0 -1
  243. data/lib/insika/subagent_graph.rb +3 -3
  244. data/lib/insika/task_actor.rb +3 -3
  245. data/lib/insika/task_store.rb +22 -2
  246. data/lib/insika/telemetry/pricing.rb +3 -3
  247. data/lib/insika/telemetry/recorder.rb +1 -1
  248. data/lib/insika/telemetry.rb +2 -2
  249. data/lib/insika/testing/store_contract.rb +54 -33
  250. data/lib/insika/tick.rb +146 -0
  251. data/lib/insika/token_store.rb +168 -0
  252. data/lib/insika/tool_assembly.rb +5 -5
  253. data/lib/insika/tool_definition.rb +25 -15
  254. data/lib/insika/tool_envelope.rb +70 -1
  255. data/lib/insika/tool_manifest.rb +11 -7
  256. data/lib/insika/tool_output_compressor.rb +100 -0
  257. data/lib/insika/tool_store.rb +1 -1
  258. data/lib/insika/tool_trace_store.rb +1 -1
  259. data/lib/insika/tools/concurrency.rb +2 -2
  260. data/lib/insika/tools/data_defined_tool.rb +14 -5
  261. data/lib/insika/tools/generate_image.rb +44 -0
  262. data/lib/insika/tools/load_skill.rb +61 -3
  263. data/lib/insika/tools/schedule_followup.rb +164 -0
  264. data/lib/insika/tools/stuck_signal.rb +44 -0
  265. data/lib/insika/tools/subagent.rb +4 -4
  266. data/lib/insika/tools/subagents.rb +1 -1
  267. data/lib/insika/tools/tts.rb +47 -0
  268. data/lib/insika/tools/update_briefing.rb +126 -0
  269. data/lib/insika/turn_output.rb +2 -2
  270. data/lib/insika/turn_state.rb +54 -13
  271. data/lib/insika/turn_timing.rb +24 -4
  272. data/lib/insika/usage_ledger.rb +1 -1
  273. data/lib/insika/version.rb +1 -1
  274. data/lib/insika/vitals.rb +84 -0
  275. data/lib/insika/wiring/graph.rb +372 -34
  276. data/lib/insika/workflow.rb +1 -1
  277. data/lib/insika/workflow_registry.rb +1 -1
  278. data/lib/insika.rb +122 -16
  279. metadata +95 -2
  280. data/lib/insika/server/admin_auth.rb +0 -29
data/lib/insika.rb CHANGED
@@ -2,6 +2,33 @@
2
2
 
3
3
  require_relative "insika/version"
4
4
  require_relative "insika/errors"
5
+ # the payload selection + the domain-boundary audit yardstick.
6
+ # Pure module — loaded by the gemspec too, so it carries no app requires.
7
+ require_relative "insika/packaging"
8
+ require_relative "insika/provider_error_classifier"
9
+ require_relative "insika/token_store"
10
+ require_relative "insika/budget_ledger"
11
+ require_relative "insika/circuit_state"
12
+ require_relative "insika/reliability"
13
+ require_relative "insika/routing"
14
+ require_relative "insika/media"
15
+ require_relative "insika/alert_dispatcher"
16
+ require_relative "insika/outcome_store"
17
+ require_relative "insika/retention"
18
+ require_relative "insika/funnel_declaration"
19
+ require_relative "insika/funnel_store"
20
+ require_relative "insika/funnel_fold"
21
+ # the parsed follow-up policy of ONE agent — the ONLY shape the
22
+ # engine accepts (tool/engine/doctor/Studio share it). Pure value object.
23
+ require_relative "insika/followup_policy"
24
+ # the contact-state cells and the follow-up schedule records.
25
+ # Both are dumb domain stores over the injected backend.
26
+ require_relative "insika/contact_store"
27
+ require_relative "insika/followup_store"
28
+ # the tick-driven firer — rides the same tick as retention/funnel.
29
+ require_relative "insika/followup_engine"
30
+ require_relative "insika/commands/freeze_funnel_baseline"
31
+ require_relative "insika/channels/webhook"
5
32
  require_relative "insika/coercion"
6
33
  require_relative "insika/message_origin"
7
34
  require_relative "insika/env_schema"
@@ -14,19 +41,27 @@ require_relative "insika/model_selection"
14
41
  require_relative "insika/model_resolver"
15
42
  require_relative "insika/tool_definition"
16
43
  require_relative "insika/tool_manifest"
44
+ # the pack's grounding policy (Insika::Grounding + the
45
+ # GroundingMatcher it wraps). Pure Ruby — profile data, parsed per turn.
46
+ require_relative "insika/grounding"
17
47
  require_relative "insika/frontmatter"
18
48
  require_relative "insika/token_estimator"
19
49
  require_relative "insika/checkpoint"
20
50
  require_relative "insika/command"
21
51
  require_relative "insika/hooks"
22
52
  require_relative "insika/middleware"
23
- # Production edge (item 33 / §12 G7): windowed counters + the rate-limit/cost
53
+ # Production edge: windowed counters + the rate-limit/cost
24
54
  # Middleware. Both inert until configured (nil/0 = off).
25
55
  require_relative "insika/usage_ledger"
56
+ require_relative "insika/budget_ledger"
26
57
  require_relative "insika/edge_limiter"
27
- # Content safety / guardrails (RFC-0009). detectors.rb is self-contained (the eval
28
- # requires it directly, D4); the rest hang off Middleware/hooks seams. No ruby_llm
29
- # at load-time — Factory requires the gem lazily, like the Executor's create_chat.
58
+ require_relative "insika/tool_output_compressor"
59
+ # Content safety / guardrails. The pattern SOURCE is the
60
+ # language-tagged data in safety/corpus.rb; detectors.rb compiles it. Both are
61
+ # self-contained (the eval requires detectors.rb directly); the rest hang off
62
+ # Middleware/hooks seams. No ruby_llm at load-time — Factory requires the gem
63
+ # lazily, like the Executor's create_chat.
64
+ require_relative "insika/safety/corpus"
30
65
  require_relative "insika/safety/detectors"
31
66
  require_relative "insika/safety/safe_responses"
32
67
  require_relative "insika/safety/config"
@@ -43,9 +78,15 @@ require_relative "insika/context/builder"
43
78
  require_relative "insika/context/providers/request"
44
79
  require_relative "insika/context/providers/prompt"
45
80
  require_relative "insika/context/providers/skill"
81
+ require_relative "insika/context/providers/skill_trigger"
46
82
  require_relative "insika/context/providers/tool_search"
47
83
  require_relative "insika/context/providers/memory"
48
84
  require_relative "insika/context/providers/session"
85
+ require_relative "insika/context/providers/briefing"
86
+ # the cache-prefix hash chain + the per-agent cache-hit series.
87
+ # Both are referenced by the Executor at runtime, so they load before it.
88
+ require_relative "insika/prefix_fingerprint"
89
+ require_relative "insika/cache_series_store"
49
90
  require_relative "insika/policy/policy"
50
91
  require_relative "insika/policy/engine"
51
92
  require_relative "insika/registry"
@@ -65,11 +106,15 @@ require_relative "insika/task_store"
65
106
  require_relative "insika/checkpoint_store"
66
107
  require_relative "insika/pending_action_store"
67
108
  require_relative "insika/delegation_store"
68
- # Channels (RFC-0011): the outbound record + the inbound retry window. Both are
109
+ # Channels: the outbound record + the inbound retry window. Both are
69
110
  # plain stores; the channel objects themselves come after the HTTP client.
70
111
  require_relative "insika/outbox_store"
112
+ require_relative "insika/shadow_pair_store"
71
113
  require_relative "insika/inbound_log"
72
114
  require_relative "insika/memory_store"
115
+ # the operator-mutation audit trail. After memory_store (no
116
+ # mutual deps). Pure stdlib — `load_guard_spec` stays green.
117
+ require_relative "insika/memory_audit_store"
73
118
  require_relative "insika/config_store"
74
119
  require_relative "insika/profile_source"
75
120
  require_relative "insika/agent_file_store"
@@ -77,7 +122,12 @@ require_relative "insika/skill_store"
77
122
  require_relative "insika/secret_masking"
78
123
  require_relative "insika/tool_store"
79
124
  require_relative "insika/tool_trace_store"
80
- # Refinement (RFC-0013 phase A): the run record + the evidence half of the loop.
125
+ require_relative "insika/context_trace_store"
126
+ # the model-visible payload of one ask + its durable trace —
127
+ # "model-visible means logged" (the conformance suite's reconstruction half).
128
+ require_relative "insika/model_visible"
129
+ require_relative "insika/model_visible_trace_store"
130
+ # Refinement: the run record + the evidence half of the loop.
81
131
  # Reads sessions/tasks/traces above; requires Safety::Detectors (loaded earlier) for
82
132
  # the PII redaction of the snippets it puts in a report.
83
133
  require_relative "insika/refinement_store"
@@ -90,9 +140,12 @@ require_relative "insika/refinement/candidate"
90
140
  require_relative "insika/refinement/proposer"
91
141
  require_relative "insika/egress_guard"
92
142
  require_relative "insika/schema_guard"
143
+ # the evidence contract (Spec + Processor + EvidenceLedger). Pure Ruby.
144
+ # Required BEFORE tool_envelope.rb — the envelope references it at runtime.
145
+ require_relative "insika/evidence"
93
146
  require_relative "insika/sandbox"
94
147
  require_relative "insika/http_client"
95
- # Channels (RFC-0011 §4/§6): the registry, the bundled relay adapter and the
148
+ # Channels: the registry, the bundled relay adapter and the
96
149
  # out-of-band dispatcher. After http_client and egress_guard — the relay POSTs
97
150
  # through both — and after registry.rb, which ChannelRegistry extends.
98
151
  require_relative "insika/channel_registry"
@@ -103,11 +156,11 @@ require_relative "insika/overlay_tool_registry"
103
156
  require_relative "insika/settings_store"
104
157
  require_relative "insika/llm_provider_store"
105
158
  require_relative "insika/llm_configurator"
106
- # LLM-first onboarding surface (item 20 / §5.6): serves start.md + models.json + the
159
+ # LLM-first onboarding surface: serves start.md + models.json + the
107
160
  # public docs. Reads the settings/provider stores above at call-time (order is free).
108
161
  require_relative "insika/onboarding"
109
- # Evals (RFC-0008) — the quality harness, moved under lib/ so the engine can call it
110
- # (the RFC-0013 refinement gate scores a candidate agent with the SAME judge the CLI
162
+ # Evals — the quality harness, moved under lib/ so the engine can call it
163
+ # (the refinement gate scores a candidate agent with the SAME judge the CLI
111
164
  # uses; a second copy would be the worst outcome). It stays a CLIENT of the engine:
112
165
  # HttpTransport talks to a running deployment, nothing here reads a store. Pure Ruby +
113
166
  # stdlib; the judge's provider call is injected, so no ruby_llm at load time.
@@ -119,14 +172,18 @@ require_relative "insika/evals/runner"
119
172
  require_relative "insika/evals/report"
120
173
  require_relative "insika/evals/baseline"
121
174
  require_relative "insika/evals/transport"
122
- # Authored eval cases (RFC-0013 §3.7): the corpus becomes editable without a
175
+ # shadow parity: the frozen criterion and the mechanical
176
+ # fold over the pair store (C6). Pure — no store, no provider gem.
177
+ require_relative "insika/parity/criterion"
178
+ require_relative "insika/parity/verdict"
179
+ # Authored eval cases: the corpus becomes editable without a
123
180
  # checkout. Requires the loader above (it is the one validator).
124
181
  require_relative "insika/golden_store"
125
182
  require_relative "insika/baseline_store"
126
- # RFC-0013 §3.5: scores a candidate by REPLAYING it. After evals (the runner and
183
+ # scores a candidate by REPLAYING it. After evals (the runner and
127
184
  # the baseline comparison) and after the stores it clones an agent through.
128
185
  require_relative "insika/refinement/gate"
129
- # RFC-0013 §3.9 (phase D): the proposer PANEL and the run's token budget. Needs the
186
+ # the proposer PANEL and the run's token budget. Needs the
130
187
  # candidate format and the gate's Report shape, so it loads after both.
131
188
  require_relative "insika/refinement/panel"
132
189
  require_relative "insika/mcp_store"
@@ -151,6 +208,7 @@ require_relative "insika/commands/write_agent_file"
151
208
  require_relative "insika/commands/delete_agent_file"
152
209
  require_relative "insika/commands/restore_agent_file"
153
210
  require_relative "insika/commands/write_skill"
211
+ require_relative "insika/commands/delete_skill"
154
212
  require_relative "insika/commands/set_skill_agents"
155
213
  require_relative "insika/commands/memory_put_fact"
156
214
  require_relative "insika/commands/memory_forget_fact"
@@ -162,6 +220,45 @@ require_relative "insika/commands/write_golden"
162
220
  require_relative "insika/commands/update_settings"
163
221
  require_relative "insika/commands/upsert_llm_provider"
164
222
  require_relative "insika/commands/delete_llm_provider"
223
+ require_relative "insika/commands/issue_tenant_token"
224
+ require_relative "insika/commands/revoke_token"
225
+ require_relative "insika/commands/rotate_tenant_token"
226
+ require_relative "insika/commands/record_outcome"
227
+ require_relative "insika/commands/record_shadow_reply"
228
+ require_relative "insika/commands/judge_shadow_pairs"
229
+ require_relative "insika/commands/session_purge"
230
+ require_relative "insika/commands/forget_customer"
231
+ require_relative "insika/commands/delete_tenant_data"
232
+ # the LGPD access right — export one customer's memory cell as
233
+ # content (the Studio download); the event stays counts-only.
234
+ require_relative "insika/commands/export_customer_memory"
235
+ # the operator/integration follow-up mutations (cancel one
236
+ # record; revoke a contact + fall its pending records atomically).
237
+ require_relative "insika/commands/cancel_followup"
238
+ require_relative "insika/commands/revoke_contact"
239
+ # session distillation — the distiller (pure, injected ask)
240
+ # and the proposal store (proposals + the latched dedup ledger + the
241
+ # per-session distilled marker).
242
+ require_relative "insika/distill"
243
+ require_relative "insika/proposal_store"
244
+ require_relative "insika/commands/run_distillation"
245
+ require_relative "insika/distill_engine"
246
+ require_relative "insika/commands/resolve_proposal"
247
+ # the gated harvest — the miner (pure, injected ask), the
248
+ # frozen conversion criterion and the versioned negative list. The provider
249
+ # touch stays inside MinerFactory's lazy ask (load_guard stays green).
250
+ require_relative "insika/harvest"
251
+ require_relative "insika/harvest/criterion"
252
+ require_relative "insika/harvest/negative_list"
253
+ require_relative "insika/harvest/conversion_gate"
254
+ require_relative "insika/harvest/gate"
255
+ require_relative "insika/harvest_store"
256
+ require_relative "insika/commands/run_harvest"
257
+ require_relative "insika/commands/gate_harvest"
258
+ require_relative "insika/commands/promote_harvest"
259
+ require_relative "insika/commands/rollback_harvest"
260
+ require_relative "insika/commands/reject_harvest"
261
+ require_relative "insika/harvest_engine"
165
262
  require_relative "insika/commands/upsert_mcp"
166
263
  require_relative "insika/commands/delete_mcp"
167
264
  require_relative "insika/commands/write_system_file"
@@ -179,6 +276,8 @@ require_relative "insika/session_actor"
179
276
  require_relative "insika/skill_catalog"
180
277
  require_relative "insika/tool_catalog"
181
278
  require_relative "insika/steer_injector"
279
+ require_relative "insika/loop_detector"
280
+ require_relative "insika/balloon_splitter"
182
281
  require_relative "insika/turn_output"
183
282
  require_relative "insika/turn_state"
184
283
  require_relative "insika/turn_timing"
@@ -188,19 +287,26 @@ require_relative "insika/tool_assembly"
188
287
  require_relative "insika/chat_builder"
189
288
  require_relative "insika/executor"
190
289
  require_relative "insika/shutdown"
290
+ require_relative "insika/tick"
191
291
  require_relative "insika/pack"
192
292
  require_relative "insika/pack_importer"
193
293
  require_relative "insika/telemetry"
194
- # Strict config + diagnosis (item 23 / §8.1). Doctor reads the config stores above;
294
+ # Strict config + diagnosis. Doctor reads the config stores above;
195
295
  # EnvSchema (required at the top) is its env layer.
196
296
  require_relative "insika/doctor"
297
+ # Soak: the 72h uptime-degradation harness. Pure stdlib — the
298
+ # envelope and the report fold are deterministic, the runner only talks Net::HTTP.
299
+ require_relative "insika/soak/envelope"
300
+ require_relative "insika/soak/report"
301
+ require_relative "insika/soak/runner"
302
+ require_relative "insika/vitals"
197
303
  # Shared composition core for both roots (config/wiring.rb + config/deployment.rb).
198
304
  # Only references the classes above at call-time, so require order is unconstrained.
199
305
  require_relative "insika/wiring/graph"
200
- # Public Ruby DSL (item 36): Insika.agent { … }. The Builder is gem-free (it only
306
+ # Public Ruby DSL: Insika.agent { … }. The Builder is gem-free (it only
201
307
  # generates a Pack); the runtime (chat/serve) is required lazily by Definition, so
202
308
  # `require "insika"` stays free of ruby_llm and the HTTP server.
203
309
  require_relative "insika/dsl"
204
310
  # Do NOT require "insika/tools/load_skill" here: it does `require "ruby_llm"` at
205
311
  # the top (inherits from RubyLLM::Tool) and would pull the gem in at load-time. The
206
- # Executor loads it lazily inside create_chat (D9).
312
+ # Executor loads it lazily inside create_chat.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: insika
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Guilherme Lages Santos
@@ -151,6 +151,7 @@ files:
151
151
  - README.md
152
152
  - bin/insika
153
153
  - docs/AGENTS.md
154
+ - docs/API.md
154
155
  - docs/ARCHITECTURE.md
155
156
  - docs/BENCHMARK.md
156
157
  - docs/CHANNELS.md
@@ -158,6 +159,8 @@ files:
158
159
  - docs/DEPLOY.md
159
160
  - docs/EMBEDDING.md
160
161
  - docs/EVALS.md
162
+ - docs/FACTS.md
163
+ - docs/HARVEST.md
161
164
  - docs/LOADTEST.md
162
165
  - docs/OBSERVABILITY.md
163
166
  - docs/PLUGINS.md
@@ -167,10 +170,12 @@ files:
167
170
  - docs/SANDBOX.md
168
171
  - docs/SECURITY.md
169
172
  - docs/SKILLS.md
173
+ - docs/SOAK.md
170
174
  - docs/TOOLS.md
171
175
  - docs/WHY.md
172
176
  - docs/WORKFLOWS.md
173
177
  - docs/build.md
178
+ - docs/domain.md
174
179
  - docs/index.md
175
180
  - docs/onboarding/start.md
176
181
  - docs/operate.md
@@ -179,8 +184,12 @@ files:
179
184
  - lib/insika.rb
180
185
  - lib/insika/agent_file_store.rb
181
186
  - lib/insika/agent_profile.rb
187
+ - lib/insika/alert_dispatcher.rb
182
188
  - lib/insika/allowlist.rb
189
+ - lib/insika/balloon_splitter.rb
183
190
  - lib/insika/baseline_store.rb
191
+ - lib/insika/budget_ledger.rb
192
+ - lib/insika/cache_series_store.rb
184
193
  - lib/insika/capability/resolved_tool.rb
185
194
  - lib/insika/capability_registry.rb
186
195
  - lib/insika/channel_delivery.rb
@@ -188,14 +197,17 @@ files:
188
197
  - lib/insika/channels/relay.rb
189
198
  - lib/insika/channels/web.rb
190
199
  - lib/insika/channels/web/widget.js
200
+ - lib/insika/channels/webhook.rb
191
201
  - lib/insika/chat_builder.rb
192
202
  - lib/insika/checkpoint.rb
193
203
  - lib/insika/checkpoint_store.rb
204
+ - lib/insika/circuit_state.rb
194
205
  - lib/insika/coercion.rb
195
206
  - lib/insika/command.rb
196
207
  - lib/insika/command_bus.rb
197
208
  - lib/insika/commands/agent_payload.rb
198
209
  - lib/insika/commands/approve_action.rb
210
+ - lib/insika/commands/cancel_followup.rb
199
211
  - lib/insika/commands/cancel_task.rb
200
212
  - lib/insika/commands/create_agent.rb
201
213
  - lib/insika/commands/create_session.rb
@@ -204,21 +216,41 @@ files:
204
216
  - lib/insika/commands/delete_data_tool.rb
205
217
  - lib/insika/commands/delete_llm_provider.rb
206
218
  - lib/insika/commands/delete_mcp.rb
219
+ - lib/insika/commands/delete_skill.rb
207
220
  - lib/insika/commands/delete_system_file.rb
221
+ - lib/insika/commands/delete_tenant_data.rb
222
+ - lib/insika/commands/export_customer_memory.rb
223
+ - lib/insika/commands/forget_customer.rb
224
+ - lib/insika/commands/freeze_funnel_baseline.rb
225
+ - lib/insika/commands/gate_harvest.rb
208
226
  - lib/insika/commands/gate_refinement.rb
209
227
  - lib/insika/commands/import_mcp_tools.rb
210
228
  - lib/insika/commands/import_tools.rb
229
+ - lib/insika/commands/issue_tenant_token.rb
230
+ - lib/insika/commands/judge_shadow_pairs.rb
211
231
  - lib/insika/commands/memory_add_note.rb
212
232
  - lib/insika/commands/memory_forget_fact.rb
213
233
  - lib/insika/commands/memory_put_fact.rb
214
234
  - lib/insika/commands/pause_task.rb
235
+ - lib/insika/commands/promote_harvest.rb
236
+ - lib/insika/commands/record_outcome.rb
237
+ - lib/insika/commands/record_shadow_reply.rb
238
+ - lib/insika/commands/reject_harvest.rb
239
+ - lib/insika/commands/resolve_proposal.rb
215
240
  - lib/insika/commands/resolve_refinement.rb
216
241
  - lib/insika/commands/restore_agent_file.rb
217
242
  - lib/insika/commands/restore_data_tool.rb
218
243
  - lib/insika/commands/restore_system_file.rb
219
244
  - lib/insika/commands/resume_task.rb
245
+ - lib/insika/commands/revoke_contact.rb
246
+ - lib/insika/commands/revoke_token.rb
247
+ - lib/insika/commands/rollback_harvest.rb
248
+ - lib/insika/commands/rotate_tenant_token.rb
249
+ - lib/insika/commands/run_distillation.rb
250
+ - lib/insika/commands/run_harvest.rb
220
251
  - lib/insika/commands/run_refinement.rb
221
252
  - lib/insika/commands/send_message.rb
253
+ - lib/insika/commands/session_purge.rb
222
254
  - lib/insika/commands/set_agent_tools.rb
223
255
  - lib/insika/commands/set_skill_agents.rb
224
256
  - lib/insika/commands/trigger_workflow.rb
@@ -232,18 +264,24 @@ files:
232
264
  - lib/insika/commands/write_skill.rb
233
265
  - lib/insika/commands/write_system_file.rb
234
266
  - lib/insika/config_store.rb
267
+ - lib/insika/contact_store.rb
235
268
  - lib/insika/context/builder.rb
236
269
  - lib/insika/context/catalog_provider.rb
237
270
  - lib/insika/context/fragment.rb
238
271
  - lib/insika/context/priority.rb
239
272
  - lib/insika/context/provider.rb
273
+ - lib/insika/context/providers/briefing.rb
240
274
  - lib/insika/context/providers/memory.rb
241
275
  - lib/insika/context/providers/prompt.rb
242
276
  - lib/insika/context/providers/request.rb
243
277
  - lib/insika/context/providers/session.rb
244
278
  - lib/insika/context/providers/skill.rb
279
+ - lib/insika/context/providers/skill_trigger.rb
245
280
  - lib/insika/context/providers/tool_search.rb
281
+ - lib/insika/context_trace_store.rb
246
282
  - lib/insika/delegation_store.rb
283
+ - lib/insika/distill.rb
284
+ - lib/insika/distill_engine.rb
247
285
  - lib/insika/doctor.rb
248
286
  - lib/insika/dsl.rb
249
287
  - lib/insika/dsl/definition.rb
@@ -265,36 +303,64 @@ files:
265
303
  - lib/insika/evals/transport.rb
266
304
  - lib/insika/event.rb
267
305
  - lib/insika/event_stream.rb
306
+ - lib/insika/evidence.rb
268
307
  - lib/insika/executor.rb
308
+ - lib/insika/followup_engine.rb
309
+ - lib/insika/followup_policy.rb
310
+ - lib/insika/followup_store.rb
269
311
  - lib/insika/frontmatter.rb
312
+ - lib/insika/funnel_declaration.rb
313
+ - lib/insika/funnel_fold.rb
314
+ - lib/insika/funnel_store.rb
270
315
  - lib/insika/golden_store.rb
316
+ - lib/insika/grounding.rb
317
+ - lib/insika/grounding/matcher.rb
318
+ - lib/insika/harvest.rb
319
+ - lib/insika/harvest/conversion_gate.rb
320
+ - lib/insika/harvest/criterion.rb
321
+ - lib/insika/harvest/gate.rb
322
+ - lib/insika/harvest/negative_list.rb
323
+ - lib/insika/harvest_engine.rb
324
+ - lib/insika/harvest_store.rb
271
325
  - lib/insika/hooks.rb
272
326
  - lib/insika/http_client.rb
273
327
  - lib/insika/inbound_log.rb
274
328
  - lib/insika/llm_configurator.rb
275
329
  - lib/insika/llm_provider_store.rb
330
+ - lib/insika/loop_detector.rb
276
331
  - lib/insika/mcp_http_client.rb
277
332
  - lib/insika/mcp_store.rb
278
333
  - lib/insika/mcp_tool_ingestor.rb
334
+ - lib/insika/media.rb
335
+ - lib/insika/memory_audit_store.rb
279
336
  - lib/insika/memory_store.rb
280
337
  - lib/insika/message_origin.rb
281
338
  - lib/insika/middleware.rb
282
339
  - lib/insika/model_policy.rb
283
340
  - lib/insika/model_resolver.rb
284
341
  - lib/insika/model_selection.rb
342
+ - lib/insika/model_visible.rb
343
+ - lib/insika/model_visible_trace_store.rb
285
344
  - lib/insika/onboarding.rb
286
345
  - lib/insika/outbox_store.rb
346
+ - lib/insika/outcome_store.rb
287
347
  - lib/insika/overlay_tool_registry.rb
288
348
  - lib/insika/pack.rb
289
349
  - lib/insika/pack_importer.rb
350
+ - lib/insika/packaging.rb
351
+ - lib/insika/parity/criterion.rb
352
+ - lib/insika/parity/verdict.rb
290
353
  - lib/insika/pending_action_store.rb
291
354
  - lib/insika/plugin.rb
292
355
  - lib/insika/plugin/loader.rb
293
356
  - lib/insika/policy/engine.rb
294
357
  - lib/insika/policy/policy.rb
295
358
  - lib/insika/policy_registry.rb
359
+ - lib/insika/prefix_fingerprint.rb
296
360
  - lib/insika/profile_source.rb
297
361
  - lib/insika/prompt_catalog.rb
362
+ - lib/insika/proposal_store.rb
363
+ - lib/insika/provider_error_classifier.rb
298
364
  - lib/insika/queue_policy.rb
299
365
  - lib/insika/recovery.rb
300
366
  - lib/insika/refinement/candidate.rb
@@ -304,9 +370,15 @@ files:
304
370
  - lib/insika/refinement/proposer.rb
305
371
  - lib/insika/refinement_store.rb
306
372
  - lib/insika/registry.rb
373
+ - lib/insika/reliability.rb
374
+ - lib/insika/retention.rb
375
+ - lib/insika/routing.rb
307
376
  - lib/insika/safety/config.rb
377
+ - lib/insika/safety/corpus.rb
308
378
  - lib/insika/safety/detectors.rb
309
379
  - lib/insika/safety/factory.rb
380
+ - lib/insika/safety/grounding_enforcer.rb
381
+ - lib/insika/safety/grounding_validator.rb
310
382
  - lib/insika/safety/input_guardrail.rb
311
383
  - lib/insika/safety/moderator.rb
312
384
  - lib/insika/safety/output_filter.rb
@@ -328,18 +400,22 @@ files:
328
400
  - lib/insika/server/a2a/protocol.rb
329
401
  - lib/insika/server/a2a/remotes.rb
330
402
  - lib/insika/server/a2a/task_projection.rb
331
- - lib/insika/server/admin_auth.rb
332
403
  - lib/insika/server/app.rb
333
404
  - lib/insika/server/boot.rb
334
405
  - lib/insika/server/rack_app.rb
335
406
  - lib/insika/server/responses.rb
336
407
  - lib/insika/server/sse_body.rb
408
+ - lib/insika/server/tenant_auth.rb
337
409
  - lib/insika/session_actor.rb
338
410
  - lib/insika/session_store.rb
339
411
  - lib/insika/settings_store.rb
412
+ - lib/insika/shadow_pair_store.rb
340
413
  - lib/insika/shutdown.rb
341
414
  - lib/insika/skill_catalog.rb
342
415
  - lib/insika/skill_store.rb
416
+ - lib/insika/soak/envelope.rb
417
+ - lib/insika/soak/report.rb
418
+ - lib/insika/soak/runner.rb
343
419
  - lib/insika/steer_injector.rb
344
420
  - lib/insika/store.rb
345
421
  - lib/insika/stores/memory.rb
@@ -347,6 +423,7 @@ files:
347
423
  - lib/insika/studio/app.rb
348
424
  - lib/insika/studio/assets/dist/application.css
349
425
  - lib/insika/studio/assets/dist/application.js
426
+ - lib/insika/studio/assets/dist/favicon.svg
350
427
  - lib/insika/studio/forms.rb
351
428
  - lib/insika/studio/nav_icons.rb
352
429
  - lib/insika/studio/views/_message.erb
@@ -354,12 +431,19 @@ files:
354
431
  - lib/insika/studio/views/agents.erb
355
432
  - lib/insika/studio/views/approvals.erb
356
433
  - lib/insika/studio/views/chats.erb
434
+ - lib/insika/studio/views/customer.erb
435
+ - lib/insika/studio/views/customers.erb
357
436
  - lib/insika/studio/views/evals.erb
437
+ - lib/insika/studio/views/facts.erb
438
+ - lib/insika/studio/views/followups.erb
439
+ - lib/insika/studio/views/funnel.erb
440
+ - lib/insika/studio/views/harvest.erb
358
441
  - lib/insika/studio/views/home.erb
359
442
  - lib/insika/studio/views/layout.erb
360
443
  - lib/insika/studio/views/login.erb
361
444
  - lib/insika/studio/views/mcp.erb
362
445
  - lib/insika/studio/views/not_found.erb
446
+ - lib/insika/studio/views/parity.erb
363
447
  - lib/insika/studio/views/playground.erb
364
448
  - lib/insika/studio/views/refinement.erb
365
449
  - lib/insika/studio/views/session.erb
@@ -378,12 +462,15 @@ files:
378
462
  - lib/insika/telemetry/pricing.rb
379
463
  - lib/insika/telemetry/recorder.rb
380
464
  - lib/insika/testing/store_contract.rb
465
+ - lib/insika/tick.rb
381
466
  - lib/insika/token_estimator.rb
467
+ - lib/insika/token_store.rb
382
468
  - lib/insika/tool_assembly.rb
383
469
  - lib/insika/tool_catalog.rb
384
470
  - lib/insika/tool_definition.rb
385
471
  - lib/insika/tool_envelope.rb
386
472
  - lib/insika/tool_manifest.rb
473
+ - lib/insika/tool_output_compressor.rb
387
474
  - lib/insika/tool_registry.rb
388
475
  - lib/insika/tool_store.rb
389
476
  - lib/insika/tool_trace_store.rb
@@ -391,16 +478,22 @@ files:
391
478
  - lib/insika/tools/agent_enum.rb
392
479
  - lib/insika/tools/concurrency.rb
393
480
  - lib/insika/tools/data_defined_tool.rb
481
+ - lib/insika/tools/generate_image.rb
394
482
  - lib/insika/tools/load_skill.rb
395
483
  - lib/insika/tools/remember.rb
484
+ - lib/insika/tools/schedule_followup.rb
485
+ - lib/insika/tools/stuck_signal.rb
396
486
  - lib/insika/tools/subagent.rb
397
487
  - lib/insika/tools/subagents.rb
398
488
  - lib/insika/tools/tool_search.rb
489
+ - lib/insika/tools/tts.rb
490
+ - lib/insika/tools/update_briefing.rb
399
491
  - lib/insika/turn_output.rb
400
492
  - lib/insika/turn_state.rb
401
493
  - lib/insika/turn_timing.rb
402
494
  - lib/insika/usage_ledger.rb
403
495
  - lib/insika/version.rb
496
+ - lib/insika/vitals.rb
404
497
  - lib/insika/wiring/graph.rb
405
498
  - lib/insika/workflow.rb
406
499
  - lib/insika/workflow_registry.rb
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rack"
4
- require "rack/utils"
5
-
6
- module Insika
7
- module Server
8
- # Minimal operator auth. Fail-closed BY CONSTRUCTION: with no
9
- # token configured, /admin does not exist to the world (503) — never open
10
- # by omission. Pure module, testable without a Rack env.
11
- module AdminAuth
12
- module_function
13
-
14
- # config_token: config[:admin_token] (the wiring reads ADMIN_TOKEN).
15
- # header: raw Authorization value.
16
- # -> :disabled | :unauthorized | :ok
17
- def check(config_token, header)
18
- return :disabled if config_token.nil? || config_token.empty?
19
-
20
- provided = header.to_s[/\ABearer (.+)\z/, 1]
21
- return :unauthorized if provided.nil?
22
- # Constant-time comparison: the operator token doesn't leak via timing.
23
- return :unauthorized unless Rack::Utils.secure_compare(config_token, provided)
24
-
25
- :ok
26
- end
27
- end
28
- end
29
- end