@fulcrum_io/sdk 0.1.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.
@@ -0,0 +1,555 @@
1
+ syntax = "proto3";
2
+
3
+ package fulcrum.policy.v1;
4
+
5
+ option go_package = "github.com/fulcrum-io/fulcrum/pkg/policy/v1";
6
+
7
+ import "google/api/annotations.proto";
8
+ import "google/protobuf/timestamp.proto";
9
+ import "google/protobuf/struct.proto";
10
+
11
+ // PolicyService provides policy management and evaluation capabilities.
12
+ // Supports creating policies, evaluating rules, and enforcing governance.
13
+ service PolicyService {
14
+ // Policy CRUD operations
15
+ rpc CreatePolicy(CreatePolicyRequest) returns (CreatePolicyResponse) {
16
+ option (google.api.http) = {
17
+ post: "/v1/policies"
18
+ body: "policy"
19
+ };
20
+ }
21
+
22
+ rpc GetPolicy(GetPolicyRequest) returns (GetPolicyResponse) {
23
+ option (google.api.http) = {
24
+ get: "/v1/policies/{policy_id}"
25
+ };
26
+ }
27
+
28
+ rpc UpdatePolicy(UpdatePolicyRequest) returns (UpdatePolicyResponse) {
29
+ option (google.api.http) = {
30
+ patch: "/v1/policies/{policy.policy_id}"
31
+ body: "policy"
32
+ };
33
+ }
34
+
35
+ rpc DeletePolicy(DeletePolicyRequest) returns (DeletePolicyResponse) {
36
+ option (google.api.http) = {
37
+ delete: "/v1/policies/{policy_id}"
38
+ };
39
+ }
40
+
41
+ rpc ListPolicies(ListPoliciesRequest) returns (ListPoliciesResponse) {
42
+ option (google.api.http) = {
43
+ get: "/v1/policies"
44
+ };
45
+ }
46
+
47
+ // Policy evaluation
48
+ rpc EvaluatePolicy(EvaluatePolicyRequest) returns (EvaluatePolicyResponse) {
49
+ option (google.api.http) = {
50
+ post: "/v1/policies/evaluate"
51
+ body: "*"
52
+ };
53
+ }
54
+
55
+ // Batch evaluation for multiple policies
56
+ rpc EvaluatePolicies(EvaluatePoliciesRequest) returns (EvaluatePoliciesResponse) {
57
+ option (google.api.http) = {
58
+ post: "/v1/policies/batch-evaluate"
59
+ body: "*"
60
+ };
61
+ }
62
+
63
+ rpc GetEvaluationHistory(GetEvaluationHistoryRequest) returns (GetEvaluationHistoryResponse) {
64
+ option (google.api.http) = {
65
+ get: "/v1/policies/{policy_id}/evaluations"
66
+ };
67
+ }
68
+
69
+ // Approval Workflow
70
+ rpc ListApprovals(ListApprovalsRequest) returns (ListApprovalsResponse) {
71
+ option (google.api.http) = {
72
+ get: "/v1/approvals"
73
+ };
74
+ }
75
+
76
+ rpc UpdateApproval(UpdateApprovalRequest) returns (UpdateApprovalResponse) {
77
+ option (google.api.http) = {
78
+ patch: "/v1/approvals/{approval_id}"
79
+ body: "*"
80
+ };
81
+ }
82
+ }
83
+
84
+ // Policy defines governance rules for agent execution.
85
+ message Policy {
86
+ // Unique policy identifier
87
+ string policy_id = 1;
88
+
89
+ // Tenant this policy applies to
90
+ string tenant_id = 2;
91
+
92
+ // Policy metadata
93
+ string name = 3;
94
+ string description = 4;
95
+ map<string, string> tags = 5;
96
+
97
+ // Policy rules
98
+ repeated PolicyRule rules = 6;
99
+
100
+ // Policy scope
101
+ PolicyScope scope = 7;
102
+
103
+ // Policy status
104
+ PolicyStatus status = 8;
105
+
106
+ // Enforcement level
107
+ EnforcementLevel enforcement = 9;
108
+
109
+ // Priority (higher = evaluated first)
110
+ int32 priority = 10;
111
+
112
+ // Timestamps
113
+ google.protobuf.Timestamp created_at = 11;
114
+ google.protobuf.Timestamp updated_at = 12;
115
+ google.protobuf.Timestamp effective_at = 13; // When policy becomes active
116
+ google.protobuf.Timestamp expires_at = 14; // Optional expiration
117
+
118
+ // Created by
119
+ string created_by = 15;
120
+ }
121
+
122
+ // PolicyRule represents a single rule within a policy.
123
+ message PolicyRule {
124
+ // Rule identifier (unique within policy)
125
+ string rule_id = 1;
126
+
127
+ // Rule name and description
128
+ string name = 2;
129
+ string description = 3;
130
+
131
+ // Rule conditions (all must match for rule to trigger)
132
+ repeated PolicyCondition conditions = 4;
133
+
134
+ // Actions to take when rule matches
135
+ repeated PolicyAction actions = 5;
136
+
137
+ // Rule type
138
+ RuleType rule_type = 6;
139
+
140
+ // Rule enabled/disabled
141
+ bool enabled = 7;
142
+
143
+ // Priority within policy (higher = evaluated first)
144
+ int32 priority = 8;
145
+ }
146
+
147
+ // PolicyCondition defines when a rule should trigger.
148
+ message PolicyCondition {
149
+ // Condition type determines which fields are used
150
+ ConditionType condition_type = 1;
151
+
152
+ // Field to evaluate (e.g., "user.role", "model.id", "tool.name")
153
+ string field = 2;
154
+
155
+ // Operator for comparison
156
+ ConditionOperator operator = 3;
157
+
158
+ // Value to compare against
159
+ oneof value {
160
+ string string_value = 4;
161
+ int64 int_value = 5;
162
+ double float_value = 6;
163
+ bool bool_value = 7;
164
+ google.protobuf.ListValue list_value = 8;
165
+ }
166
+
167
+ // Additional values for multi-value operators
168
+ repeated string values = 9;
169
+
170
+ // Nested conditions for complex logic (AND/OR)
171
+ repeated PolicyCondition nested_conditions = 10;
172
+
173
+ // Logical operator for nested conditions
174
+ LogicalOperator logical_operator = 11;
175
+
176
+ // Negate the condition
177
+ bool negate = 12;
178
+
179
+ // Semantic evaluation fields
180
+ string semantic_intent = 20; // Human-readable intent description
181
+ string semantic_model = 21; // LLM model to use (e.g., "llama3.2")
182
+ float semantic_confidence_threshold = 22; // Minimum confidence to match
183
+ }
184
+
185
+ // PolicyAction defines what to do when a rule matches.
186
+ message PolicyAction {
187
+ // Action type
188
+ ActionType action_type = 1;
189
+
190
+ // Action parameters (flexible structure)
191
+ map<string, string> parameters = 2;
192
+
193
+ // Message to return to user
194
+ string message = 3;
195
+
196
+ // Severity level
197
+ SeverityLevel severity = 4;
198
+
199
+ // Stop evaluation after this action
200
+ bool terminal = 5;
201
+ }
202
+
203
+ // PolicyScope defines where a policy applies.
204
+ message PolicyScope {
205
+ // Workflows this policy applies to
206
+ repeated string workflow_ids = 1;
207
+
208
+ // Execution phases where policy is evaluated
209
+ repeated ExecutionPhase phases = 2;
210
+
211
+ // User roles this policy applies to
212
+ repeated string roles = 3;
213
+
214
+ // Model restrictions
215
+ repeated string model_ids = 4;
216
+
217
+ // Tool restrictions
218
+ repeated string tool_names = 5;
219
+
220
+ // Apply to all workflows (if true, workflow_ids ignored)
221
+ bool apply_to_all = 6;
222
+ }
223
+
224
+ // EvaluationResult represents the outcome of policy evaluation.
225
+ message EvaluationResult {
226
+ // Policy evaluated
227
+ string policy_id = 1;
228
+
229
+ // Evaluation outcome
230
+ EvaluationDecision decision = 2;
231
+
232
+ // Rules that matched
233
+ repeated RuleMatch matched_rules = 3;
234
+
235
+ // Actions to execute
236
+ repeated PolicyAction actions = 4;
237
+
238
+ // Evaluation metadata
239
+ string message = 5;
240
+ map<string, string> metadata = 6;
241
+
242
+ // Evaluation timing
243
+ google.protobuf.Timestamp evaluated_at = 7;
244
+ int64 evaluation_duration_ms = 8;
245
+
246
+ // Context that was evaluated
247
+ EvaluationContext context = 9;
248
+ }
249
+
250
+ // RuleMatch represents a rule that matched during evaluation.
251
+ message RuleMatch {
252
+ string rule_id = 1;
253
+ string rule_name = 2;
254
+ repeated string matched_conditions = 3;
255
+ int32 priority = 4;
256
+ }
257
+
258
+ // EvaluationContext provides data for policy evaluation.
259
+ message EvaluationContext {
260
+ // Tenant and workflow
261
+ string tenant_id = 1;
262
+ string workflow_id = 2;
263
+ string envelope_id = 3;
264
+
265
+ // User context
266
+ string user_id = 4;
267
+ repeated string user_roles = 5;
268
+
269
+ // Execution context
270
+ ExecutionPhase phase = 6;
271
+ string model_id = 7;
272
+ repeated string tool_names = 8;
273
+
274
+ // Content to evaluate
275
+ string input_text = 9;
276
+ string output_text = 10;
277
+
278
+ // Additional context (flexible)
279
+ map<string, string> attributes = 11;
280
+
281
+ // Timestamp
282
+ google.protobuf.Timestamp timestamp = 12;
283
+ }
284
+
285
+ // Enums
286
+
287
+ // PolicyStatus indicates policy state
288
+ enum PolicyStatus {
289
+ POLICY_STATUS_UNSPECIFIED = 0;
290
+ POLICY_STATUS_DRAFT = 1;
291
+ POLICY_STATUS_ACTIVE = 2;
292
+ POLICY_STATUS_INACTIVE = 3;
293
+ POLICY_STATUS_ARCHIVED = 4;
294
+ }
295
+
296
+ // EnforcementLevel defines how strictly policy is enforced
297
+ enum EnforcementLevel {
298
+ ENFORCEMENT_LEVEL_UNSPECIFIED = 0;
299
+ ENFORCEMENT_LEVEL_AUDIT = 1; // Log only, don't block
300
+ ENFORCEMENT_LEVEL_WARN = 2; // Warn but allow
301
+ ENFORCEMENT_LEVEL_BLOCK = 3; // Block execution
302
+ ENFORCEMENT_LEVEL_TERMINATE = 4; // Terminate execution immediately
303
+ }
304
+
305
+ // RuleType categorizes policy rules
306
+ enum RuleType {
307
+ RULE_TYPE_UNSPECIFIED = 0;
308
+ RULE_TYPE_RBAC = 1; // Role-based access control
309
+ RULE_TYPE_CONTENT_FILTER = 2; // Content filtering
310
+ RULE_TYPE_TOOL_ALLOWLIST = 3; // Tool access control
311
+ RULE_TYPE_MODEL_RESTRICTION = 4; // Model usage restrictions
312
+ RULE_TYPE_RATE_LIMIT = 5; // Rate limiting
313
+ RULE_TYPE_COST_CONTROL = 6; // Cost-based controls
314
+ RULE_TYPE_CUSTOM = 7; // Custom rule type
315
+ }
316
+
317
+ // ConditionType defines the type of condition
318
+ enum ConditionType {
319
+ CONDITION_TYPE_UNSPECIFIED = 0;
320
+ CONDITION_TYPE_FIELD_MATCH = 1; // Simple field comparison
321
+ CONDITION_TYPE_REGEX = 2; // Regex pattern matching
322
+ CONDITION_TYPE_RANGE = 3; // Numeric range
323
+ CONDITION_TYPE_IN_LIST = 4; // Value in list
324
+ CONDITION_TYPE_CONTAINS = 5; // String contains
325
+ CONDITION_TYPE_STARTS_WITH = 6; // String starts with
326
+ CONDITION_TYPE_ENDS_WITH = 7; // String ends with
327
+ CONDITION_TYPE_LOGICAL = 8; // AND/OR of nested conditions
328
+ CONDITION_TYPE_STATISTICAL_SPIKE = 9; // Deviation from historical baseline
329
+ CONDITION_TYPE_EXTERNAL_CALL = 10; // Fetch data from external API/DB
330
+ CONDITION_TYPE_SEMANTIC = 11; // LLM-based intent evaluation
331
+ }
332
+
333
+ // ConditionOperator defines comparison operators
334
+ enum ConditionOperator {
335
+ CONDITION_OPERATOR_UNSPECIFIED = 0;
336
+ CONDITION_OPERATOR_EQUALS = 1;
337
+ CONDITION_OPERATOR_NOT_EQUALS = 2;
338
+ CONDITION_OPERATOR_GREATER_THAN = 3;
339
+ CONDITION_OPERATOR_LESS_THAN = 4;
340
+ CONDITION_OPERATOR_GREATER_EQUAL = 5;
341
+ CONDITION_OPERATOR_LESS_EQUAL = 6;
342
+ CONDITION_OPERATOR_MATCHES = 7; // Regex match
343
+ CONDITION_OPERATOR_CONTAINS = 8; // String/list contains
344
+ CONDITION_OPERATOR_IN = 9; // Value in list
345
+ CONDITION_OPERATOR_NOT_IN = 10; // Value not in list
346
+ }
347
+
348
+ // LogicalOperator combines multiple conditions
349
+ enum LogicalOperator {
350
+ LOGICAL_OPERATOR_UNSPECIFIED = 0;
351
+ LOGICAL_OPERATOR_AND = 1;
352
+ LOGICAL_OPERATOR_OR = 2;
353
+ LOGICAL_OPERATOR_NOT = 3;
354
+ }
355
+
356
+ // ActionType defines what action to take
357
+ enum ActionType {
358
+ ACTION_TYPE_UNSPECIFIED = 0;
359
+ ACTION_TYPE_ALLOW = 1; // Allow execution
360
+ ACTION_TYPE_DENY = 2; // Block execution
361
+ ACTION_TYPE_WARN = 3; // Warn but allow
362
+ ACTION_TYPE_MODIFY = 4; // Modify request
363
+ ACTION_TYPE_REDIRECT = 5; // Redirect to different model/tool
364
+ ACTION_TYPE_AUDIT = 6; // Log for audit
365
+ ACTION_TYPE_THROTTLE = 7; // Rate limit
366
+ ACTION_TYPE_REQUIRE_APPROVAL = 8; // Require human approval
367
+ ACTION_TYPE_NOTIFY = 9; // Notify external service (Slack/Teams)
368
+ }
369
+
370
+ // SeverityLevel indicates action severity
371
+ enum SeverityLevel {
372
+ SEVERITY_LEVEL_UNSPECIFIED = 0;
373
+ SEVERITY_LEVEL_INFO = 1;
374
+ SEVERITY_LEVEL_LOW = 2;
375
+ SEVERITY_LEVEL_MEDIUM = 3;
376
+ SEVERITY_LEVEL_HIGH = 4;
377
+ SEVERITY_LEVEL_CRITICAL = 5;
378
+ }
379
+
380
+ // ExecutionPhase defines when policy is evaluated
381
+ enum ExecutionPhase {
382
+ EXECUTION_PHASE_UNSPECIFIED = 0;
383
+ EXECUTION_PHASE_PRE_EXECUTION = 1; // Before execution starts
384
+ EXECUTION_PHASE_PRE_LLM_CALL = 2; // Before each LLM call
385
+ EXECUTION_PHASE_POST_LLM_CALL = 3; // After each LLM call
386
+ EXECUTION_PHASE_PRE_TOOL_CALL = 4; // Before each tool call
387
+ EXECUTION_PHASE_POST_TOOL_CALL = 5; // After each tool call
388
+ EXECUTION_PHASE_POST_EXECUTION = 6; // After execution completes
389
+ }
390
+
391
+ // EvaluationDecision is the final policy decision
392
+ enum EvaluationDecision {
393
+ EVALUATION_DECISION_UNSPECIFIED = 0;
394
+ EVALUATION_DECISION_ALLOW = 1; // Execution allowed
395
+ EVALUATION_DECISION_DENY = 2; // Execution blocked
396
+ EVALUATION_DECISION_WARN = 3; // Warning issued
397
+ EVALUATION_DECISION_REQUIRE_APPROVAL = 4; // Needs approval
398
+ }
399
+
400
+ // Request/Response messages
401
+
402
+ message CreatePolicyRequest {
403
+ Policy policy = 1;
404
+ }
405
+
406
+ message CreatePolicyResponse {
407
+ Policy policy = 1;
408
+ }
409
+
410
+ message GetPolicyRequest {
411
+ string policy_id = 1;
412
+ }
413
+
414
+ message GetPolicyResponse {
415
+ Policy policy = 1;
416
+ }
417
+
418
+ message UpdatePolicyRequest {
419
+ Policy policy = 1;
420
+ repeated string update_mask = 2;
421
+ }
422
+
423
+ message UpdatePolicyResponse {
424
+ Policy policy = 1;
425
+ }
426
+
427
+ message DeletePolicyRequest {
428
+ string policy_id = 1;
429
+ }
430
+
431
+ message DeletePolicyResponse {
432
+ bool success = 1;
433
+ }
434
+
435
+ message ListPoliciesRequest {
436
+ // Filter by tenant
437
+ string tenant_id = 1;
438
+
439
+ // Filter by status
440
+ PolicyStatus status = 2;
441
+
442
+ // Filter by rule type
443
+ RuleType rule_type = 3;
444
+
445
+ // Pagination
446
+ int32 page_size = 4;
447
+ string page_token = 5;
448
+ }
449
+
450
+ message ListPoliciesResponse {
451
+ repeated Policy policies = 1;
452
+ string next_page_token = 2;
453
+ int32 total_count = 3;
454
+ }
455
+
456
+ message EvaluatePolicyRequest {
457
+ // Policy to evaluate
458
+ string policy_id = 1;
459
+
460
+ // Context for evaluation
461
+ EvaluationContext context = 2;
462
+
463
+ // Dry run (don't execute actions)
464
+ bool dry_run = 3;
465
+ }
466
+
467
+ message EvaluatePolicyResponse {
468
+ EvaluationResult result = 1;
469
+ }
470
+
471
+ message EvaluatePoliciesRequest {
472
+ // Policies to evaluate (in priority order if empty, all active policies)
473
+ repeated string policy_ids = 1;
474
+
475
+ // Context for evaluation
476
+ EvaluationContext context = 2;
477
+
478
+ // Stop on first deny
479
+ bool stop_on_deny = 3;
480
+
481
+ // Dry run
482
+ bool dry_run = 4;
483
+ }
484
+
485
+ message EvaluatePoliciesResponse {
486
+ // All evaluation results
487
+ repeated EvaluationResult results = 1;
488
+
489
+ // Final decision (aggregate)
490
+ EvaluationDecision final_decision = 2;
491
+
492
+ // All actions to execute
493
+ repeated PolicyAction actions = 3;
494
+ }
495
+
496
+ message GetEvaluationHistoryRequest {
497
+ // Policy to get history for
498
+ string policy_id = 1;
499
+
500
+ // Time range
501
+ google.protobuf.Timestamp start_time = 2;
502
+ google.protobuf.Timestamp end_time = 3;
503
+
504
+ // Filter by decision
505
+ EvaluationDecision decision = 4;
506
+
507
+ // Pagination
508
+ int32 page_size = 5;
509
+ string page_token = 6;
510
+ }
511
+
512
+ message GetEvaluationHistoryResponse {
513
+ repeated EvaluationResult evaluations = 1;
514
+ string next_page_token = 2;
515
+ int32 total_count = 3;
516
+ }
517
+
518
+ // Approval messages
519
+ message Approval {
520
+ string approval_id = 1;
521
+ string evaluation_id = 2;
522
+ string policy_id = 3;
523
+ string envelope_id = 4;
524
+ string status = 5; // PENDING, APPROVED, REJECTED
525
+ string reviewer_id = 6;
526
+ string review_note = 7;
527
+ google.protobuf.Timestamp created_at = 8;
528
+ map<string, string> metadata = 9;
529
+ string policy_name = 10; // Joined field convenience
530
+ }
531
+
532
+ message ListApprovalsRequest {
533
+ string tenant_id = 1;
534
+ string status = 2; // e.g., "PENDING"
535
+ }
536
+
537
+ message ListApprovalsResponse {
538
+ repeated Approval approvals = 1;
539
+ }
540
+
541
+ message UpdateApprovalRequest {
542
+ string approval_id = 1;
543
+ string status = 2; // APPROVED, REJECTED
544
+ string review_note = 3;
545
+ string reviewer_id = 4;
546
+ }
547
+
548
+ message UpdateApprovalResponse {
549
+ Approval approval = 1;
550
+ }
551
+
552
+ // PolicyList is a wrapper for a list of policies, used primarily for caching.
553
+ message PolicyList {
554
+ repeated Policy policies = 1;
555
+ }
@@ -0,0 +1,57 @@
1
+ syntax = "proto3";
2
+
3
+ package fulcrum.tenant.v1;
4
+
5
+ import "google/protobuf/timestamp.proto";
6
+
7
+ option go_package = "github.com/fulcrum-io/fulcrum/pkg/tenant/v1;tenantv1";
8
+
9
+ service TenantService {
10
+ // CreateApiKey creates a new API key for the authenticated tenant.
11
+ rpc CreateApiKey(CreateApiKeyRequest) returns (CreateApiKeyResponse);
12
+
13
+ // ListApiKeys lists all API keys for the authenticated tenant.
14
+ rpc ListApiKeys(ListApiKeysRequest) returns (ListApiKeysResponse);
15
+
16
+ // RevokeApiKey revokes (deletes) an API key by ID.
17
+ rpc RevokeApiKey(RevokeApiKeyRequest) returns (RevokeApiKeyResponse);
18
+ }
19
+
20
+ message ApiKey {
21
+ string id = 1;
22
+ string name = 2;
23
+ string key_hint = 3; // e.g. "abcd...1234"
24
+ repeated string scopes = 4;
25
+ google.protobuf.Timestamp expires_at = 5;
26
+ google.protobuf.Timestamp created_at = 6;
27
+ google.protobuf.Timestamp last_used_at = 7;
28
+ }
29
+
30
+ message CreateApiKeyRequest {
31
+ string name = 1;
32
+ repeated string scopes = 2;
33
+ int64 expires_in_seconds = 3; // Optional: TTL. If 0, never expires.
34
+ }
35
+
36
+ message CreateApiKeyResponse {
37
+ ApiKey key = 1;
38
+ string key_secret = 2; // The raw key secret. ONLY returned here.
39
+ }
40
+
41
+ message ListApiKeysRequest {
42
+ int32 page_size = 1;
43
+ string page_token = 2;
44
+ }
45
+
46
+ message ListApiKeysResponse {
47
+ repeated ApiKey keys = 1;
48
+ string next_page_token = 2;
49
+ }
50
+
51
+ message RevokeApiKeyRequest {
52
+ string key_id = 1;
53
+ }
54
+
55
+ message RevokeApiKeyResponse {
56
+ bool success = 1;
57
+ }
@@ -0,0 +1,31 @@
1
+ // Copyright 2025 Google LLC
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ syntax = "proto3";
16
+
17
+ package google.api;
18
+
19
+ import "google/api/http.proto";
20
+ import "google/protobuf/descriptor.proto";
21
+
22
+ option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations";
23
+ option java_multiple_files = true;
24
+ option java_outer_classname = "AnnotationsProto";
25
+ option java_package = "com.google.api";
26
+ option objc_class_prefix = "GAPI";
27
+
28
+ extend google.protobuf.MethodOptions {
29
+ // See `HttpRule`.
30
+ HttpRule http = 72295728;
31
+ }