legion-data 1.7.4 → 1.8.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.
- checksums.yaml +4 -4
- data/AGENTS.md +66 -13
- data/CHANGELOG.md +19 -0
- data/CLAUDE.md +44 -307
- data/README.md +100 -6
- data/lib/legion/data/migrations/077_create_llm_conversations.rb +32 -0
- data/lib/legion/data/migrations/078_create_llm_messages.rb +33 -0
- data/lib/legion/data/migrations/079_create_llm_message_inference_requests.rb +47 -0
- data/lib/legion/data/migrations/080_create_llm_message_inference_responses.rb +39 -0
- data/lib/legion/data/migrations/081_add_llm_message_inference_foreign_keys.rb +17 -0
- data/lib/legion/data/migrations/082_create_llm_route_attempts.rb +31 -0
- data/lib/legion/data/migrations/083_create_llm_message_inference_metrics.rb +36 -0
- data/lib/legion/data/migrations/084_create_llm_tool_calls.rb +32 -0
- data/lib/legion/data/migrations/085_add_llm_message_tool_call_foreign_key.rb +15 -0
- data/lib/legion/data/migrations/086_create_llm_tool_call_attempts.rb +30 -0
- data/lib/legion/data/migrations/087_create_llm_conversation_compactions.rb +31 -0
- data/lib/legion/data/migrations/088_create_llm_policy_evaluations.rb +33 -0
- data/lib/legion/data/migrations/089_create_llm_security_events.rb +33 -0
- data/lib/legion/data/migrations/090_create_llm_registry_events.rb +23 -0
- data/lib/legion/data/migrations/091_create_portable_identity_providers.rb +35 -0
- data/lib/legion/data/migrations/092_create_portable_identity_principals.rb +25 -0
- data/lib/legion/data/migrations/093_create_portable_identities.rb +31 -0
- data/lib/legion/data/migrations/094_create_portable_identity_groups.rb +21 -0
- data/lib/legion/data/migrations/095_create_portable_identity_group_memberships.rb +25 -0
- data/lib/legion/data/migrations/096_create_portable_identity_audit_log.rb +26 -0
- data/lib/legion/data/migrations/097_add_llm_dispatch_fields.rb +16 -0
- data/lib/legion/data/model.rb +11 -1
- data/lib/legion/data/models/apollo/access_log.rb +17 -0
- data/lib/legion/data/models/apollo/entries.rb +22 -0
- data/lib/legion/data/models/apollo/expertise.rb +16 -0
- data/lib/legion/data/models/apollo/model_helpers.rb +17 -0
- data/lib/legion/data/models/apollo/operation.rb +16 -0
- data/lib/legion/data/models/apollo/relation.rb +18 -0
- data/lib/legion/data/models/function.rb +1 -0
- data/lib/legion/data/models/identity/audit_log.rb +20 -0
- data/lib/legion/data/models/identity/group.rb +28 -0
- data/lib/legion/data/models/identity/group_memberships.rb +28 -0
- data/lib/legion/data/models/identity/identity.rb +24 -0
- data/lib/legion/data/models/identity/model_helpers.rb +86 -0
- data/lib/legion/data/models/identity/principal.rb +37 -0
- data/lib/legion/data/models/identity/providers.rb +34 -0
- data/lib/legion/data/models/identity.rb +8 -0
- data/lib/legion/data/models/identity_group.rb +13 -0
- data/lib/legion/data/models/identity_provider.rb +8 -0
- data/lib/legion/data/models/llm/conversation.rb +25 -0
- data/lib/legion/data/models/llm/conversation_compaction.rb +22 -0
- data/lib/legion/data/models/llm/message.rb +105 -0
- data/lib/legion/data/models/llm/message_inference_metric.rb +46 -0
- data/lib/legion/data/models/llm/message_inference_request.rb +80 -0
- data/lib/legion/data/models/llm/message_inference_response.rb +23 -0
- data/lib/legion/data/models/llm/model_helpers.rb +18 -0
- data/lib/legion/data/models/llm/policy_evaluation.rb +20 -0
- data/lib/legion/data/models/llm/registry_event.rb +15 -0
- data/lib/legion/data/models/llm/route_attempt.rb +18 -0
- data/lib/legion/data/models/llm/security_event.rb +66 -0
- data/lib/legion/data/models/llm/tool_call.rb +21 -0
- data/lib/legion/data/models/llm/tool_call_attempt.rb +18 -0
- data/lib/legion/data/models/node.rb +2 -1
- data/lib/legion/data/models/principal.rb +13 -0
- data/lib/legion/data/models/rbac/cross_team_grants.rb +25 -0
- data/lib/legion/data/models/rbac/model_helpers.rb +25 -0
- data/lib/legion/data/models/rbac/role_assignments.rb +25 -0
- data/lib/legion/data/models/rbac/runner_grants.rb +23 -0
- data/lib/legion/data/models/relationship.rb +1 -0
- data/lib/legion/data/models/runner.rb +24 -2
- data/lib/legion/data/models/task.rb +4 -0
- data/lib/legion/data/version.rb +1 -1
- metadata +52 -1
data/README.md
CHANGED
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
# legion-data
|
|
2
2
|
|
|
3
|
-
Persistent database storage for the [LegionIO](https://github.com/LegionIO/LegionIO) async job engine and AI coding assistant platform. Provides database connectivity via the [Sequel ORM](https://sequel.jeremyevans.net/), automatic schema migrations (
|
|
3
|
+
Persistent database storage for the [LegionIO](https://github.com/LegionIO/LegionIO) async job engine and AI coding assistant platform. Provides database connectivity via the [Sequel ORM](https://sequel.jeremyevans.net/), automatic schema migrations (97 numbered migrations), Sequel models for the full LegionIO control plane, and a parallel local SQLite database for on-node agentic cognitive state.
|
|
4
4
|
|
|
5
|
-
**Version**: 1.
|
|
5
|
+
**Version**: 1.8.0 | **Ruby**: >= 3.4 | **License**: Apache-2.0
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## What It Owns
|
|
10
|
+
|
|
11
|
+
`legion-data` is the data contract for LegionIO. It owns database connectivity, migrations, model loading, and portable Sequel model definitions for shared platform state. HTTP routes, runtime orchestration, and extension behavior live in other LegionIO repos and call into these models.
|
|
12
|
+
|
|
13
|
+
Core responsibilities:
|
|
14
|
+
|
|
15
|
+
| Area | Tables and models |
|
|
16
|
+
|------|-------------------|
|
|
17
|
+
| Control plane | extensions, functions, runners, nodes, tasks, settings, workers, relationships, chains |
|
|
18
|
+
| Audit and governance | `audit_log`, `audit_records`, `governance_events`, archive manifests |
|
|
19
|
+
| Identity and RBAC | providers, principals, identities, groups, memberships, role grants, runner grants |
|
|
20
|
+
| LLM ledger | conversations, model-visible messages, inference requests/responses, routing, metrics, tool calls, policy/security events |
|
|
21
|
+
| Apollo knowledge | PostgreSQL `pgvector` knowledge entries, relations, expertise, access logs |
|
|
22
|
+
| Local state | on-node SQLite cognitive state, independent of the shared database |
|
|
23
|
+
|
|
24
|
+
The schema is portable by default across SQLite, MySQL, and PostgreSQL. PostgreSQL-only behavior is isolated to features that need PostgreSQL, such as Apollo vector columns.
|
|
25
|
+
|
|
9
26
|
## Supported Databases
|
|
10
27
|
|
|
11
28
|
| Database | Adapter | Gem | Default |
|
|
@@ -56,15 +73,20 @@ Legion::Data (singleton module)
|
|
|
56
73
|
│ ├── .stats # Pool metrics, tuning snapshot, adapter-specific DB stats
|
|
57
74
|
│ └── .shutdown # Disconnect and close query file logger
|
|
58
75
|
│
|
|
59
|
-
├── Migration # Auto-migration system (
|
|
76
|
+
├── Migration # Auto-migration system (97 numbered Sequel DSL migrations)
|
|
60
77
|
│
|
|
61
78
|
├── Model # Sequel model autoloader
|
|
62
79
|
│ └── Models: Extension, Function, Runner, Node, Task, TaskLog, Setting,
|
|
63
80
|
│ DigitalWorker, Relationship, AuditLog, AuditRecord, Chain,
|
|
64
81
|
│ RbacRoleAssignment, RbacRunnerGrant, RbacCrossTeamGrant,
|
|
65
82
|
│ IdentityProvider, Principal, Identity, IdentityGroup,
|
|
66
|
-
│ IdentityGroupMembership, IdentityAuditLog,
|
|
67
|
-
│ ApolloEntry, ApolloRelation, ApolloExpertise, ApolloAccessLog (PG only)
|
|
83
|
+
│ IdentityGroupMembership, IdentityAuditLog, ExtractStepTiming,
|
|
84
|
+
│ ApolloEntry, ApolloRelation, ApolloExpertise, ApolloAccessLog (PG only),
|
|
85
|
+
│ LLM::Conversation, LLM::Message, LLM::MessageInferenceRequest,
|
|
86
|
+
│ LLM::MessageInferenceResponse, LLM::RouteAttempt,
|
|
87
|
+
│ LLM::MessageInferenceMetric, LLM::ToolCall, LLM::ToolCallAttempt,
|
|
88
|
+
│ LLM::ConversationCompaction, LLM::PolicyEvaluation,
|
|
89
|
+
│ LLM::SecurityEvent, LLM::RegistryEvent
|
|
68
90
|
│
|
|
69
91
|
├── Local # Parallel local SQLite for agentic cognitive state
|
|
70
92
|
│ ├── .setup # Lazy init — creates legionio_local.db on first access
|
|
@@ -127,6 +149,34 @@ Legion::Data::Connection.connection_info
|
|
|
127
149
|
Legion::Data.shutdown
|
|
128
150
|
```
|
|
129
151
|
|
|
152
|
+
### Model Associations
|
|
153
|
+
|
|
154
|
+
Models use Sequel associations as the public object graph. Prefer association methods and association datasets over hand-written foreign-key lookups when the relationship is part of the schema contract.
|
|
155
|
+
|
|
156
|
+
```ruby
|
|
157
|
+
task = Legion::Data::Model::Task.first(id: 42)
|
|
158
|
+
task.function # many_to_one :function
|
|
159
|
+
task.relationship # many_to_one :relationship
|
|
160
|
+
task.task_logs_dataset # further filter/order without losing the relationship
|
|
161
|
+
|
|
162
|
+
conversation = Legion::Data::Models::LLM::Conversation.first(uuid: conversation_uuid)
|
|
163
|
+
conversation.messages_dataset.order(:seq).all
|
|
164
|
+
conversation.security_incident_lineage
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Official LLM lifecycle data lives under `Legion::Data::Models::LLM`. `legion-llm` and `lex-llm-ledger` should use these models and the `llm_*` migration tables for conversations, model-visible messages, inference requests, responses, route attempts, metrics, tool calls, policy decisions, security events, and registry events. Legacy ledger-only tables are not the canonical schema.
|
|
168
|
+
|
|
169
|
+
Association rules used in this repo follow Sequel's own association model:
|
|
170
|
+
|
|
171
|
+
| Relationship | Use this Sequel association |
|
|
172
|
+
|--------------|-----------------------------|
|
|
173
|
+
| Current table has the foreign key | `many_to_one` |
|
|
174
|
+
| Associated table has the foreign key | `one_to_many` or `one_to_one` |
|
|
175
|
+
| Join table connects both sides | `many_to_many` |
|
|
176
|
+
| One associated record through a join table | `one_through_one` |
|
|
177
|
+
|
|
178
|
+
When Sequel cannot infer names from the schema, models must be explicit with `:class`, `:key`, `:primary_key`, `:join_table`, `:left_key`, and `:right_key`. Association names must not collide with real column names because Sequel creates methods with the association name.
|
|
179
|
+
|
|
130
180
|
### Local Database (Agentic Cognitive State)
|
|
131
181
|
|
|
132
182
|
Extensions register their own migration directories and create models bound to the local connection:
|
|
@@ -385,6 +435,37 @@ Legion::Data.reload_static_cache
|
|
|
385
435
|
|
|
386
436
|
Apollo models require PostgreSQL with the `pgvector` extension. They are skipped silently on SQLite and MySQL.
|
|
387
437
|
|
|
438
|
+
The `Legion::Data::Model::Identity::*`, `Apollo::*`, and `RBAC::*` namespaces provide cleaner Sequel model names for API-facing code while preserving the legacy flat model classes. Official LLM lifecycle models live under `Legion::Data::Models::LLM`.
|
|
439
|
+
|
|
440
|
+
### Identity Namespace Models
|
|
441
|
+
|
|
442
|
+
| Model | Table | Description |
|
|
443
|
+
|-------|-------|-------------|
|
|
444
|
+
| `Identity::Provider` | `portable_identity_providers` | Portable provider records with integer primary keys and public UUIDs |
|
|
445
|
+
| `Identity::ProviderCapability` | `portable_identity_provider_capabilities` | Normalized provider capability declarations |
|
|
446
|
+
| `Identity::Principal` | `portable_identity_principals` | Human, service, worker, or system principals |
|
|
447
|
+
| `Identity::Identity` | `portable_identities` | Provider-bound identities for principals |
|
|
448
|
+
| `Identity::Group` | `portable_identity_groups` | Identity groups |
|
|
449
|
+
| `Identity::GroupMembership` | `portable_identity_group_memberships` | Principal and identity group membership rows |
|
|
450
|
+
| `Identity::AuditLog` | `portable_identity_audit_log` | Identity lifecycle and lookup audit events |
|
|
451
|
+
|
|
452
|
+
### LLM Lifecycle Models
|
|
453
|
+
|
|
454
|
+
| Model | Table | Description |
|
|
455
|
+
|-------|-------|-------------|
|
|
456
|
+
| `LLM::Conversation` | `llm_conversations` | Conversation container tied to the base user identity |
|
|
457
|
+
| `LLM::Message` | `llm_messages` | Model-visible conversation transcript messages |
|
|
458
|
+
| `LLM::MessageInferenceRequest` | `llm_message_inference_requests` | Provider request assembled from message, context, tools, policy, and routing inputs |
|
|
459
|
+
| `LLM::MessageInferenceResponse` | `llm_message_inference_responses` | Provider/runtime response for one inference request |
|
|
460
|
+
| `LLM::RouteAttempt` | `llm_route_attempts` | Provider/model/runner routing attempts, including failures and escalations |
|
|
461
|
+
| `LLM::MessageInferenceMetric` | `llm_message_inference_metrics` | Token, latency, cost, and finance usage metrics for an inference pair |
|
|
462
|
+
| `LLM::ToolCall` | `llm_tool_calls` | Tool calls requested by an LLM provider response |
|
|
463
|
+
| `LLM::ToolCallAttempt` | `llm_tool_call_attempts` | Execution attempts, retries, failures, and results for provider-requested tool calls |
|
|
464
|
+
| `LLM::ConversationCompaction` | `llm_conversation_compactions` | Conversation-scoped compaction events |
|
|
465
|
+
| `LLM::PolicyEvaluation` | `llm_policy_evaluations` | Policy, classification, RBAC, and enforcement decisions for inference requests |
|
|
466
|
+
| `LLM::SecurityEvent` | `llm_security_events` | Security-relevant events tied to conversation, inference, response, or tool attempts |
|
|
467
|
+
| `LLM::RegistryEvent` | `llm_registry_events` | Provider/model registry availability and health events |
|
|
468
|
+
|
|
388
469
|
---
|
|
389
470
|
|
|
390
471
|
## Dependencies
|
|
@@ -404,7 +485,7 @@ Apollo models require PostgreSQL with the `pgvector` extension. They are skipped
|
|
|
404
485
|
|
|
405
486
|
## Migrations
|
|
406
487
|
|
|
407
|
-
|
|
488
|
+
97 numbered Sequel DSL migrations run automatically on startup (`auto_migrate: true`). Key milestones:
|
|
408
489
|
|
|
409
490
|
| Range | What was added |
|
|
410
491
|
|-------|---------------|
|
|
@@ -422,6 +503,9 @@ Apollo models require PostgreSQL with the `pgvector` extension. They are skipped
|
|
|
422
503
|
| 068–071 | Entity type on audit records, principal on nodes, approval queue resume, engine on relationships |
|
|
423
504
|
| 072–073 | Identity audit log and multi-instance identity columns |
|
|
424
505
|
| 074–076 | Apollo field width fixes, task idempotency columns, and Extract step timing rows |
|
|
506
|
+
| 077–090 | Portable LLM lifecycle schema: conversations, messages, inference requests/responses, route attempts, inference metrics, provider-requested tool calls, compactions, policy/security, and registry events |
|
|
507
|
+
| 091–096 | Portable identity companion schema with integer primary keys, public UUIDs, provider capabilities, principals, identities, groups, memberships, and audit log |
|
|
508
|
+
| 097 | LLM dispatch identifiers for fleet operation, correlation, idempotency, provider instance, and dispatch path |
|
|
425
509
|
|
|
426
510
|
Run migrations standalone:
|
|
427
511
|
|
|
@@ -429,6 +513,15 @@ Run migrations standalone:
|
|
|
429
513
|
bundle exec legionio_migrate
|
|
430
514
|
```
|
|
431
515
|
|
|
516
|
+
Migration rules:
|
|
517
|
+
|
|
518
|
+
- Do not edit published migrations.
|
|
519
|
+
- Do not guard migrations with `create_table?`, `table_exists?`, `if_not_exists`, or similar conditional schema logic.
|
|
520
|
+
- Add new migrations in the next available number and keep domains split by dependency and rollback risk.
|
|
521
|
+
- Use portable Sequel DSL unless a feature truly requires adapter-specific behavior.
|
|
522
|
+
- Prefer integer `id` primary keys for joins plus public `uuid` columns for APIs, logs, and external references.
|
|
523
|
+
- Avoid JSON columns unless the shape is genuinely provider-specific or dynamic evidence.
|
|
524
|
+
|
|
432
525
|
---
|
|
433
526
|
|
|
434
527
|
## CLI Executable
|
|
@@ -458,6 +551,7 @@ bundle exec legionio_migrate
|
|
|
458
551
|
11. Financial logging for UAIS cost recovery
|
|
459
552
|
12. Global tool embedding cache (L4 tier for `Legion::Tools::EmbeddingCache`)
|
|
460
553
|
13. Unified identity system (providers, principals, identities, groups)
|
|
554
|
+
14. LLM lifecycle ledger for audit, finance metrics, routing reconstruction, tool calls, and security incident lineage
|
|
461
555
|
|
|
462
556
|
---
|
|
463
557
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
change do
|
|
5
|
+
create_table(:llm_conversations) do
|
|
6
|
+
primary_key :id
|
|
7
|
+
String :uuid, size: 36, null: false, unique: true
|
|
8
|
+
Integer :principal_id
|
|
9
|
+
Integer :identity_id
|
|
10
|
+
String :title, size: 255
|
|
11
|
+
String :status, size: 32, null: false, default: 'active'
|
|
12
|
+
String :system_prompt_key, size: 255
|
|
13
|
+
String :system_prompt_hash, size: 128
|
|
14
|
+
String :classification_level, size: 64
|
|
15
|
+
TrueClass :contains_phi, null: false, default: false
|
|
16
|
+
TrueClass :contains_pii, null: false, default: false
|
|
17
|
+
String :retention_policy, size: 64, null: false, default: 'default'
|
|
18
|
+
DateTime :expires_at
|
|
19
|
+
DateTime :recorded_at
|
|
20
|
+
DateTime :inserted_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
21
|
+
DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
22
|
+
DateTime :updated_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
23
|
+
|
|
24
|
+
index :uuid
|
|
25
|
+
index :principal_id
|
|
26
|
+
index :identity_id
|
|
27
|
+
index :status
|
|
28
|
+
index :retention_policy
|
|
29
|
+
index :expires_at
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
change do
|
|
5
|
+
create_table(:llm_messages) do
|
|
6
|
+
primary_key :id
|
|
7
|
+
String :uuid, size: 36, null: false, unique: true
|
|
8
|
+
foreign_key :conversation_id, :llm_conversations, null: false, on_delete: :cascade
|
|
9
|
+
foreign_key :parent_message_id, :llm_messages, null: true, on_delete: :set_null
|
|
10
|
+
Integer :message_inference_request_id
|
|
11
|
+
Integer :message_inference_response_id
|
|
12
|
+
Integer :tool_call_id
|
|
13
|
+
Integer :seq, null: false
|
|
14
|
+
String :role, size: 32, null: false
|
|
15
|
+
String :content_type, size: 64, null: false, default: 'text'
|
|
16
|
+
String :content, text: true
|
|
17
|
+
Integer :input_tokens, null: false, default: 0
|
|
18
|
+
Integer :output_tokens, null: false, default: 0
|
|
19
|
+
DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
20
|
+
DateTime :inserted_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
21
|
+
|
|
22
|
+
unique %i[conversation_id seq]
|
|
23
|
+
index :uuid
|
|
24
|
+
index :conversation_id
|
|
25
|
+
index :parent_message_id
|
|
26
|
+
index :message_inference_request_id
|
|
27
|
+
index :message_inference_response_id
|
|
28
|
+
index :tool_call_id
|
|
29
|
+
index %i[conversation_id role]
|
|
30
|
+
index :created_at
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
change do
|
|
5
|
+
create_table(:llm_message_inference_requests) do
|
|
6
|
+
primary_key :id
|
|
7
|
+
String :uuid, size: 36, null: false, unique: true
|
|
8
|
+
foreign_key :conversation_id, :llm_conversations, null: false, on_delete: :cascade
|
|
9
|
+
foreign_key :latest_message_id, :llm_messages, null: true, on_delete: :set_null
|
|
10
|
+
Integer :caller_principal_id
|
|
11
|
+
Integer :caller_identity_id
|
|
12
|
+
String :runtime_caller_type, size: 64
|
|
13
|
+
String :request_ref, size: 128
|
|
14
|
+
String :correlation_ref, size: 128
|
|
15
|
+
String :exchange_ref, size: 128
|
|
16
|
+
String :request_type, size: 64, null: false, default: 'chat'
|
|
17
|
+
String :status, size: 64, null: false, default: 'created'
|
|
18
|
+
Integer :context_message_count, null: false, default: 0
|
|
19
|
+
Integer :context_tokens, null: false, default: 0
|
|
20
|
+
Integer :token_budget, null: false, default: 0
|
|
21
|
+
String :curation_strategy, size: 128
|
|
22
|
+
Integer :injected_tool_count, null: false, default: 0
|
|
23
|
+
String :tool_policy, size: 128
|
|
24
|
+
String :request_capture_mode, size: 64, null: false, default: 'metadata_only'
|
|
25
|
+
String :request_content_hash, size: 128
|
|
26
|
+
String :request_json, text: true
|
|
27
|
+
String :classification_level, size: 64
|
|
28
|
+
String :rbac_decision, size: 64
|
|
29
|
+
String :cost_center, size: 128
|
|
30
|
+
String :budget_key, size: 128
|
|
31
|
+
DateTime :requested_at
|
|
32
|
+
DateTime :inserted_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
33
|
+
|
|
34
|
+
index :uuid
|
|
35
|
+
index :conversation_id
|
|
36
|
+
index :latest_message_id
|
|
37
|
+
index :caller_principal_id
|
|
38
|
+
index :caller_identity_id
|
|
39
|
+
index :request_ref
|
|
40
|
+
index :correlation_ref
|
|
41
|
+
index :exchange_ref
|
|
42
|
+
index :status
|
|
43
|
+
index %i[cost_center requested_at]
|
|
44
|
+
index :requested_at
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
change do
|
|
5
|
+
create_table(:llm_message_inference_responses) do
|
|
6
|
+
primary_key :id
|
|
7
|
+
String :uuid, size: 36, null: false, unique: true
|
|
8
|
+
foreign_key :message_inference_request_id, :llm_message_inference_requests, null: false, on_delete: :cascade
|
|
9
|
+
foreign_key :response_message_id, :llm_messages, null: true, on_delete: :set_null
|
|
10
|
+
String :provider, size: 128
|
|
11
|
+
String :model_key, size: 255
|
|
12
|
+
String :tier, size: 64
|
|
13
|
+
String :runner_ref, size: 128
|
|
14
|
+
String :provider_response_ref, size: 255
|
|
15
|
+
String :status, size: 64, null: false, default: 'created'
|
|
16
|
+
String :finish_reason, size: 128
|
|
17
|
+
String :error_category, size: 128
|
|
18
|
+
String :error_code, size: 128
|
|
19
|
+
String :error_message, text: true
|
|
20
|
+
Integer :latency_ms, null: false, default: 0
|
|
21
|
+
Integer :wall_clock_ms, null: false, default: 0
|
|
22
|
+
String :response_capture_mode, size: 64, null: false, default: 'metadata_only'
|
|
23
|
+
String :response_content_hash, size: 128
|
|
24
|
+
String :response_json, text: true
|
|
25
|
+
String :response_thinking_json, text: true
|
|
26
|
+
DateTime :responded_at
|
|
27
|
+
DateTime :inserted_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
28
|
+
|
|
29
|
+
index :uuid
|
|
30
|
+
index :message_inference_request_id
|
|
31
|
+
index :response_message_id
|
|
32
|
+
index %i[provider model_key]
|
|
33
|
+
index :runner_ref
|
|
34
|
+
index :provider_response_ref
|
|
35
|
+
index :status
|
|
36
|
+
index :responded_at
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
up do
|
|
5
|
+
alter_table(:llm_messages) do
|
|
6
|
+
add_foreign_key [:message_inference_request_id], :llm_message_inference_requests, key: :id, on_delete: :set_null
|
|
7
|
+
add_foreign_key [:message_inference_response_id], :llm_message_inference_responses, key: :id, on_delete: :set_null
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
down do
|
|
12
|
+
alter_table(:llm_messages) do
|
|
13
|
+
drop_foreign_key [:message_inference_response_id]
|
|
14
|
+
drop_foreign_key [:message_inference_request_id]
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
change do
|
|
5
|
+
create_table(:llm_route_attempts) do
|
|
6
|
+
primary_key :id
|
|
7
|
+
String :uuid, size: 36, null: false, unique: true
|
|
8
|
+
foreign_key :message_inference_request_id, :llm_message_inference_requests, null: false, on_delete: :cascade
|
|
9
|
+
foreign_key :message_inference_response_id, :llm_message_inference_responses, null: true, on_delete: :set_null
|
|
10
|
+
Integer :attempt_no, null: false
|
|
11
|
+
String :provider, size: 128
|
|
12
|
+
String :model_key, size: 255
|
|
13
|
+
String :tier, size: 64
|
|
14
|
+
String :route_target, size: 255
|
|
15
|
+
String :status, size: 64, null: false
|
|
16
|
+
String :failure_reason, text: true
|
|
17
|
+
Integer :latency_ms, null: false, default: 0
|
|
18
|
+
DateTime :started_at
|
|
19
|
+
DateTime :ended_at
|
|
20
|
+
DateTime :inserted_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
21
|
+
|
|
22
|
+
unique %i[message_inference_request_id attempt_no]
|
|
23
|
+
index :uuid
|
|
24
|
+
index :message_inference_request_id
|
|
25
|
+
index :message_inference_response_id
|
|
26
|
+
index %i[provider model_key]
|
|
27
|
+
index :status
|
|
28
|
+
index :started_at
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
change do
|
|
5
|
+
create_table(:llm_message_inference_metrics) do
|
|
6
|
+
primary_key :id
|
|
7
|
+
String :uuid, size: 36, null: false, unique: true
|
|
8
|
+
foreign_key :message_inference_request_id, :llm_message_inference_requests, null: false, on_delete: :cascade
|
|
9
|
+
foreign_key :message_inference_response_id, :llm_message_inference_responses, null: true, on_delete: :set_null
|
|
10
|
+
String :provider, size: 128
|
|
11
|
+
String :model_key, size: 255
|
|
12
|
+
String :tier, size: 64
|
|
13
|
+
Integer :input_tokens, null: false, default: 0
|
|
14
|
+
Integer :output_tokens, null: false, default: 0
|
|
15
|
+
Integer :thinking_tokens, null: false, default: 0
|
|
16
|
+
Integer :total_tokens, null: false, default: 0
|
|
17
|
+
Integer :latency_ms, null: false, default: 0
|
|
18
|
+
Integer :wall_clock_ms, null: false, default: 0
|
|
19
|
+
BigDecimal :cost_usd, size: [20, 8], null: false, default: 0
|
|
20
|
+
String :currency, size: 3, null: false, default: 'USD'
|
|
21
|
+
String :cost_center, size: 128
|
|
22
|
+
String :budget_key, size: 128
|
|
23
|
+
DateTime :recorded_at
|
|
24
|
+
DateTime :inserted_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
25
|
+
|
|
26
|
+
index :uuid
|
|
27
|
+
index :message_inference_request_id
|
|
28
|
+
index :message_inference_response_id
|
|
29
|
+
index %i[provider model_key]
|
|
30
|
+
index :cost_center
|
|
31
|
+
index :budget_key
|
|
32
|
+
index :recorded_at
|
|
33
|
+
index %i[cost_center recorded_at]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
change do
|
|
5
|
+
create_table(:llm_tool_calls) do
|
|
6
|
+
primary_key :id
|
|
7
|
+
String :uuid, size: 36, null: false, unique: true
|
|
8
|
+
foreign_key :message_inference_response_id, :llm_message_inference_responses, null: false, on_delete: :cascade
|
|
9
|
+
foreign_key :requested_by_message_id, :llm_messages, null: true, on_delete: :set_null
|
|
10
|
+
foreign_key :result_message_id, :llm_messages, null: true, on_delete: :set_null
|
|
11
|
+
Integer :tool_call_index, null: false, default: 0
|
|
12
|
+
String :provider_tool_call_ref, size: 255
|
|
13
|
+
String :tool_name, size: 255, null: false
|
|
14
|
+
String :tool_source_type, size: 128
|
|
15
|
+
String :tool_source_server, size: 255
|
|
16
|
+
String :status, size: 64, null: false, default: 'requested'
|
|
17
|
+
DateTime :requested_at
|
|
18
|
+
DateTime :completed_at
|
|
19
|
+
DateTime :inserted_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
20
|
+
|
|
21
|
+
unique %i[message_inference_response_id tool_call_index]
|
|
22
|
+
index :uuid
|
|
23
|
+
index :message_inference_response_id
|
|
24
|
+
index :requested_by_message_id
|
|
25
|
+
index :result_message_id
|
|
26
|
+
index :provider_tool_call_ref
|
|
27
|
+
index :tool_name
|
|
28
|
+
index :status
|
|
29
|
+
index :requested_at
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
up do
|
|
5
|
+
alter_table(:llm_messages) do
|
|
6
|
+
add_foreign_key [:tool_call_id], :llm_tool_calls, key: :id, on_delete: :set_null
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
down do
|
|
11
|
+
alter_table(:llm_messages) do
|
|
12
|
+
drop_foreign_key [:tool_call_id]
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
change do
|
|
5
|
+
create_table(:llm_tool_call_attempts) do
|
|
6
|
+
primary_key :id
|
|
7
|
+
String :uuid, size: 36, null: false, unique: true
|
|
8
|
+
foreign_key :tool_call_id, :llm_tool_calls, null: false, on_delete: :cascade
|
|
9
|
+
Integer :attempt_no, null: false
|
|
10
|
+
String :runner_ref, size: 128
|
|
11
|
+
String :status, size: 64, null: false
|
|
12
|
+
String :error_category, size: 128
|
|
13
|
+
String :error_code, size: 128
|
|
14
|
+
String :error_message, text: true
|
|
15
|
+
Integer :duration_ms, null: false, default: 0
|
|
16
|
+
String :arguments_ref, size: 255
|
|
17
|
+
String :result_ref, size: 255
|
|
18
|
+
DateTime :started_at
|
|
19
|
+
DateTime :ended_at
|
|
20
|
+
DateTime :inserted_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
21
|
+
|
|
22
|
+
unique %i[tool_call_id attempt_no]
|
|
23
|
+
index :uuid
|
|
24
|
+
index :tool_call_id
|
|
25
|
+
index :runner_ref
|
|
26
|
+
index :status
|
|
27
|
+
index :started_at
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
change do
|
|
5
|
+
create_table(:llm_conversation_compactions) do
|
|
6
|
+
primary_key :id
|
|
7
|
+
String :uuid, size: 36, null: false, unique: true
|
|
8
|
+
foreign_key :conversation_id, :llm_conversations, null: false, on_delete: :cascade
|
|
9
|
+
foreign_key :triggered_by_message_inference_request_id, :llm_message_inference_requests, null: true,
|
|
10
|
+
on_delete: :set_null
|
|
11
|
+
foreign_key :replaces_message_from_id, :llm_messages, null: true, on_delete: :set_null
|
|
12
|
+
foreign_key :replaces_message_to_id, :llm_messages, null: true, on_delete: :set_null
|
|
13
|
+
String :strategy, size: 128
|
|
14
|
+
String :status, size: 64, null: false, default: 'created'
|
|
15
|
+
Integer :source_message_count, null: false, default: 0
|
|
16
|
+
Integer :source_token_count, null: false, default: 0
|
|
17
|
+
Integer :compacted_token_count, null: false, default: 0
|
|
18
|
+
String :content_hash, size: 128
|
|
19
|
+
String :summary, text: true
|
|
20
|
+
String :error_message, text: true
|
|
21
|
+
DateTime :compacted_at
|
|
22
|
+
DateTime :inserted_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
23
|
+
|
|
24
|
+
index :uuid
|
|
25
|
+
index :conversation_id
|
|
26
|
+
index :triggered_by_message_inference_request_id
|
|
27
|
+
index :status
|
|
28
|
+
index :compacted_at
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
change do
|
|
5
|
+
create_table(:llm_policy_evaluations) do
|
|
6
|
+
primary_key :id
|
|
7
|
+
String :uuid, size: 36, null: false, unique: true
|
|
8
|
+
foreign_key :conversation_id, :llm_conversations, null: true, on_delete: :set_null
|
|
9
|
+
foreign_key :message_inference_request_id, :llm_message_inference_requests, null: true, on_delete: :set_null
|
|
10
|
+
foreign_key :message_inference_response_id, :llm_message_inference_responses, null: true, on_delete: :set_null
|
|
11
|
+
String :policy_key, size: 128, null: false
|
|
12
|
+
String :policy_version, size: 64
|
|
13
|
+
String :evaluation_type, size: 64, null: false
|
|
14
|
+
String :decision, size: 64, null: false
|
|
15
|
+
String :enforcement_action, size: 64
|
|
16
|
+
String :classification_level, size: 64
|
|
17
|
+
TrueClass :contains_phi, null: false, default: false
|
|
18
|
+
TrueClass :contains_pii, null: false, default: false
|
|
19
|
+
String :reason_code, size: 128
|
|
20
|
+
String :reason, text: true
|
|
21
|
+
DateTime :evaluated_at
|
|
22
|
+
DateTime :inserted_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
23
|
+
|
|
24
|
+
index :uuid
|
|
25
|
+
index :conversation_id
|
|
26
|
+
index :message_inference_request_id
|
|
27
|
+
index :message_inference_response_id
|
|
28
|
+
index :policy_key
|
|
29
|
+
index :decision
|
|
30
|
+
index :evaluated_at
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
change do
|
|
5
|
+
create_table(:llm_security_events) do
|
|
6
|
+
primary_key :id
|
|
7
|
+
String :uuid, size: 36, null: false, unique: true
|
|
8
|
+
foreign_key :conversation_id, :llm_conversations, null: true, on_delete: :set_null
|
|
9
|
+
foreign_key :message_inference_request_id, :llm_message_inference_requests, null: true, on_delete: :set_null
|
|
10
|
+
foreign_key :message_inference_response_id, :llm_message_inference_responses, null: true, on_delete: :set_null
|
|
11
|
+
foreign_key :tool_call_id, :llm_tool_calls, null: true, on_delete: :set_null
|
|
12
|
+
foreign_key :tool_call_attempt_id, :llm_tool_call_attempts, null: true, on_delete: :set_null
|
|
13
|
+
foreign_key :policy_evaluation_id, :llm_policy_evaluations, null: true, on_delete: :set_null
|
|
14
|
+
String :event_type, size: 128, null: false
|
|
15
|
+
String :severity, size: 32, null: false, default: 'info'
|
|
16
|
+
String :status, size: 64, null: false, default: 'open'
|
|
17
|
+
String :description, text: true
|
|
18
|
+
DateTime :detected_at
|
|
19
|
+
DateTime :inserted_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
20
|
+
|
|
21
|
+
index :uuid
|
|
22
|
+
index :conversation_id
|
|
23
|
+
index :message_inference_request_id
|
|
24
|
+
index :message_inference_response_id
|
|
25
|
+
index :tool_call_id
|
|
26
|
+
index :tool_call_attempt_id
|
|
27
|
+
index :policy_evaluation_id
|
|
28
|
+
index :event_type
|
|
29
|
+
index :severity
|
|
30
|
+
index :detected_at
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
change do
|
|
5
|
+
create_table(:llm_registry_events) do
|
|
6
|
+
primary_key :id
|
|
7
|
+
String :uuid, size: 36, null: false, unique: true
|
|
8
|
+
String :provider, size: 128
|
|
9
|
+
String :model_key, size: 255
|
|
10
|
+
String :event_type, size: 128, null: false
|
|
11
|
+
String :status, size: 64, null: false
|
|
12
|
+
String :reason, text: true
|
|
13
|
+
DateTime :recorded_at
|
|
14
|
+
DateTime :inserted_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
15
|
+
|
|
16
|
+
index :uuid
|
|
17
|
+
index %i[provider model_key]
|
|
18
|
+
index :event_type
|
|
19
|
+
index :status
|
|
20
|
+
index :recorded_at
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sequel.migration do
|
|
4
|
+
change do
|
|
5
|
+
create_table(:portable_identity_providers) do
|
|
6
|
+
primary_key :id
|
|
7
|
+
String :uuid, size: 36, null: false, unique: true
|
|
8
|
+
String :name, size: 255, null: false, unique: true
|
|
9
|
+
String :provider_type, size: 64, null: false
|
|
10
|
+
String :facing, size: 32, null: false
|
|
11
|
+
Integer :priority, null: false, default: 100
|
|
12
|
+
Integer :trust_weight, null: false, default: 50
|
|
13
|
+
String :source, size: 64, null: false, default: 'gem'
|
|
14
|
+
TrueClass :enabled, null: false, default: true
|
|
15
|
+
DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
16
|
+
DateTime :updated_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
17
|
+
|
|
18
|
+
index :uuid
|
|
19
|
+
index :name
|
|
20
|
+
index :provider_type
|
|
21
|
+
index :enabled
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
create_table(:portable_identity_provider_capabilities) do
|
|
25
|
+
primary_key :id
|
|
26
|
+
foreign_key :provider_id, :portable_identity_providers, null: false, on_delete: :cascade
|
|
27
|
+
String :capability_key, size: 128, null: false
|
|
28
|
+
DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
|
|
29
|
+
|
|
30
|
+
unique %i[provider_id capability_key]
|
|
31
|
+
index :provider_id
|
|
32
|
+
index :capability_key
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|