@a5c-ai/krate 5.0.1-staging.660d2b90f → 5.0.1-staging.69cb593ea

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 (118) hide show
  1. package/Dockerfile +31 -29
  2. package/bin/krate-demo.mjs +0 -0
  3. package/bin/krate-server.mjs +0 -0
  4. package/dist/krate-controller-ui.json +808 -10
  5. package/dist/krate-lifecycle.json +1 -1
  6. package/dist/krate-runtime-snapshot.json +223 -53
  7. package/dist/krate-summary.json +40 -3
  8. package/docs/agents/gaps-agent-mux-to-krate-crds.md +298 -0
  9. package/docs/architecture-v2.md +431 -0
  10. package/docs/openapi.yaml +1275 -0
  11. package/docs/requirements-v2.md +238 -0
  12. package/docs/sdk-api-reference.md +782 -0
  13. package/docs/system-spec-v2.md +352 -0
  14. package/docs/todos.md +4 -0
  15. package/docs/web-console-spec.md +433 -0
  16. package/package.json +1 -1
  17. package/scripts/validate-ui.mjs +305 -207
  18. package/src/agent-adapter-controller.js +169 -0
  19. package/src/agent-approval-controller.js +47 -0
  20. package/src/agent-dispatch-controller.js +130 -7
  21. package/src/agent-gateway-config-controller.js +147 -0
  22. package/src/agent-memory-controller.js +357 -0
  23. package/src/agent-memory-import.js +327 -0
  24. package/src/agent-memory-query.js +292 -0
  25. package/src/agent-memory-repository-source-controller.js +255 -0
  26. package/src/agent-mux-client.js +1 -1
  27. package/src/agent-permission-review.js +102 -14
  28. package/src/agent-project-controller.js +117 -0
  29. package/src/agent-provider-config-controller.js +150 -0
  30. package/src/agent-secret-config-grant-controller.js +282 -0
  31. package/src/agent-session-transcript-controller.js +189 -0
  32. package/src/agent-stack-controller.js +52 -1
  33. package/src/agent-subagent-controller.js +160 -0
  34. package/src/agent-transport-binding-controller.js +121 -0
  35. package/src/agent-trigger-controller.js +273 -0
  36. package/src/agent-workspace-controller.js +702 -0
  37. package/src/agent-writeback-controller.js +302 -0
  38. package/src/api-controller.js +338 -3
  39. package/src/async-controller.js +207 -0
  40. package/src/audit-controller.js +191 -0
  41. package/src/auth.js +48 -6
  42. package/src/controller-client.js +112 -38
  43. package/src/controller-ui.js +96 -16
  44. package/src/data-plane.js +3 -2
  45. package/src/event-bus.js +61 -0
  46. package/src/external/conflict-controller.js +225 -0
  47. package/src/external/github/auth.js +96 -0
  48. package/src/external/github/cicd.js +180 -0
  49. package/src/external/github/git-forge.js +240 -0
  50. package/src/external/github/index.js +144 -0
  51. package/src/external/github/issue-tracking.js +163 -0
  52. package/src/external/provider-adapter.js +161 -0
  53. package/src/external/provider-resource-factory.js +161 -0
  54. package/src/external/sync-controller.js +235 -0
  55. package/src/external/webhook-controller.js +144 -0
  56. package/src/external/write-controller.js +283 -0
  57. package/src/gitea-backend.js +36 -0
  58. package/src/gitea-service.js +173 -0
  59. package/src/http-server.js +226 -0
  60. package/src/index.js +27 -0
  61. package/src/kubernetes-controller-async.js +531 -0
  62. package/src/kubernetes-controller.js +156 -84
  63. package/src/notification-controller.js +178 -0
  64. package/src/org-scoping.js +5 -0
  65. package/src/resource-model.js +26 -8
  66. package/src/runner-controller.js +272 -0
  67. package/src/snapshot-cache.js +157 -0
  68. package/tests/agent-adapter-controller.test.js +361 -0
  69. package/tests/agent-dispatch-controller.test.js +139 -0
  70. package/tests/agent-gateway-config-controller.test.js +386 -0
  71. package/tests/agent-memory-controller.test.js +308 -0
  72. package/tests/agent-memory-import-snapshot.test.js +477 -0
  73. package/tests/agent-memory-query.test.js +404 -0
  74. package/tests/agent-memory-repository-source.test.js +514 -0
  75. package/tests/agent-permission-review-v2.test.js +317 -0
  76. package/tests/agent-project-controller.test.js +302 -0
  77. package/tests/agent-provider-config-controller.test.js +376 -0
  78. package/tests/agent-resources.test.js +35 -19
  79. package/tests/agent-secret-config-grant.test.js +231 -0
  80. package/tests/agent-session-transcript-controller.test.js +499 -0
  81. package/tests/agent-subagent-controller.test.js +201 -0
  82. package/tests/agent-transport-binding-controller.test.js +294 -0
  83. package/tests/agent-trigger-routes.test.js +190 -0
  84. package/tests/agent-trigger-sources.test.js +245 -0
  85. package/tests/agent-workspace-controller.test.js +181 -0
  86. package/tests/agent-writeback.test.js +292 -0
  87. package/tests/approval-persistence.test.js +171 -0
  88. package/tests/async-controller.test.js +252 -0
  89. package/tests/audit-controller.test.js +227 -0
  90. package/tests/codespace-controller.test.js +318 -0
  91. package/tests/controller-client.test.js +133 -0
  92. package/tests/deployment.test.js +43 -29
  93. package/tests/e2e/lifecycle.test.js +5 -2
  94. package/tests/event-bus-integration.test.js +190 -0
  95. package/tests/external-github-forge.test.js +560 -0
  96. package/tests/external-github-issues-cicd.test.js +520 -0
  97. package/tests/external-integration.test.js +470 -0
  98. package/tests/external-persistence.test.js +340 -0
  99. package/tests/external-provider-adapter.test.js +365 -0
  100. package/tests/external-resource-model.test.js +215 -0
  101. package/tests/external-webhook-sync.test.js +287 -0
  102. package/tests/external-write-conflict.test.js +353 -0
  103. package/tests/gitea-service.test.js +253 -0
  104. package/tests/health-check-real.test.js +165 -0
  105. package/tests/integration/full-flow.test.js +266 -0
  106. package/tests/krate.test.js +58 -6
  107. package/tests/memory-search-wiring.test.js +270 -0
  108. package/tests/notification-controller.test.js +196 -0
  109. package/tests/notification-integration.test.js +179 -0
  110. package/tests/org-scoping.test.js +687 -0
  111. package/tests/runner-controller.test.js +327 -0
  112. package/tests/runner-integration.test.js +231 -0
  113. package/tests/session-cookie-hmac.test.js +151 -0
  114. package/tests/snapshot-performance.test.js +315 -0
  115. package/tests/sse-events.test.js +107 -0
  116. package/tests/webhook-trigger.test.js +198 -0
  117. package/tests/workspace-volumes.test.js +312 -0
  118. package/tests/writeback-persistence.test.js +207 -0
@@ -0,0 +1,231 @@
1
+ import assert from 'node:assert/strict';
2
+ import test from 'node:test';
3
+ import {
4
+ createAgentSecretGrantController,
5
+ createAgentConfigGrantController,
6
+ validateAgentSecretGrant,
7
+ validateAgentConfigGrant,
8
+ listGrantsForAgent,
9
+ revokeGrant
10
+ } from '../src/agent-secret-config-grant-controller.js';
11
+
12
+ // ---------------------------------------------------------------------------
13
+ // validateAgentSecretGrant
14
+ // ---------------------------------------------------------------------------
15
+
16
+ test('validateAgentSecretGrant returns valid for complete input', () => {
17
+ const result = validateAgentSecretGrant({
18
+ name: 'grant-db-password',
19
+ orgRef: 'acme',
20
+ secretName: 'db-password',
21
+ grantedTo: 'agent-stack-1',
22
+ permissions: ['read']
23
+ });
24
+ assert.equal(result.valid, true);
25
+ assert.equal(result.errors.length, 0);
26
+ });
27
+
28
+ test('validateAgentSecretGrant rejects missing name', () => {
29
+ const result = validateAgentSecretGrant({
30
+ orgRef: 'acme',
31
+ secretName: 'db-password',
32
+ grantedTo: 'agent-stack-1',
33
+ permissions: ['read']
34
+ });
35
+ assert.equal(result.valid, false);
36
+ assert.ok(result.errors.some((e) => e.includes('name')));
37
+ });
38
+
39
+ test('validateAgentSecretGrant rejects invalid permissions', () => {
40
+ const result = validateAgentSecretGrant({
41
+ name: 'grant-1',
42
+ orgRef: 'acme',
43
+ secretName: 'db-password',
44
+ grantedTo: 'agent-stack-1',
45
+ permissions: ['delete']
46
+ });
47
+ assert.equal(result.valid, false);
48
+ assert.ok(result.errors.some((e) => e.includes('invalid permissions')));
49
+ });
50
+
51
+ test('validateAgentSecretGrant rejects empty permissions array', () => {
52
+ const result = validateAgentSecretGrant({
53
+ name: 'grant-1',
54
+ orgRef: 'acme',
55
+ secretName: 'db-password',
56
+ grantedTo: 'agent-stack-1',
57
+ permissions: []
58
+ });
59
+ assert.equal(result.valid, false);
60
+ });
61
+
62
+ // ---------------------------------------------------------------------------
63
+ // validateAgentConfigGrant
64
+ // ---------------------------------------------------------------------------
65
+
66
+ test('validateAgentConfigGrant returns valid for complete input', () => {
67
+ const result = validateAgentConfigGrant({
68
+ name: 'grant-app-config',
69
+ orgRef: 'acme',
70
+ configMapName: 'app-config',
71
+ grantedTo: 'agent-stack-2'
72
+ });
73
+ assert.equal(result.valid, true);
74
+ });
75
+
76
+ test('validateAgentConfigGrant rejects missing configMapName', () => {
77
+ const result = validateAgentConfigGrant({
78
+ name: 'grant-1',
79
+ orgRef: 'acme',
80
+ grantedTo: 'agent-stack-2'
81
+ });
82
+ assert.equal(result.valid, false);
83
+ assert.ok(result.errors.some((e) => e.includes('configMapName')));
84
+ });
85
+
86
+ // ---------------------------------------------------------------------------
87
+ // createAgentSecretGrantController
88
+ // ---------------------------------------------------------------------------
89
+
90
+ test('createSecretGrant creates AgentSecretGrant resource with Active status', () => {
91
+ const controller = createAgentSecretGrantController();
92
+ const result = controller.createSecretGrant({
93
+ name: 'grant-api-key',
94
+ orgRef: 'acme',
95
+ secretName: 'api-key',
96
+ grantedTo: 'agent-stack-1',
97
+ permissions: ['read', 'mount']
98
+ });
99
+
100
+ assert.ok(!result.error, 'Should succeed');
101
+ assert.ok(result.grant, 'Should return a grant resource');
102
+ assert.equal(result.grant.kind, 'AgentSecretGrant');
103
+ assert.equal(result.grant.status.phase, 'Active');
104
+ assert.equal(result.grant.spec.secretName, 'api-key');
105
+ assert.equal(result.grant.spec.grantedTo, 'agent-stack-1');
106
+ assert.deepEqual(result.grant.spec.permissions, ['read', 'mount']);
107
+ });
108
+
109
+ test('createSecretGrant returns error for invalid input', () => {
110
+ const controller = createAgentSecretGrantController();
111
+ const result = controller.createSecretGrant({
112
+ name: '',
113
+ orgRef: 'acme',
114
+ secretName: 'key',
115
+ grantedTo: 'agent-1',
116
+ permissions: ['read']
117
+ });
118
+ assert.ok(result.error, 'Should return an error');
119
+ assert.ok(result.message);
120
+ });
121
+
122
+ test('createSecretGrant calls persistFn', async () => {
123
+ const persisted = [];
124
+ const controller = createAgentSecretGrantController({ persistFn: (r) => persisted.push(r) });
125
+ controller.createSecretGrant({
126
+ name: 'grant-persist-test',
127
+ orgRef: 'acme',
128
+ secretName: 'my-secret',
129
+ grantedTo: 'agent-stack-1',
130
+ permissions: ['read']
131
+ });
132
+ await new Promise((r) => setTimeout(r, 10));
133
+ assert.equal(persisted.length, 1);
134
+ assert.equal(persisted[0].kind, 'AgentSecretGrant');
135
+ });
136
+
137
+ // ---------------------------------------------------------------------------
138
+ // createAgentConfigGrantController
139
+ // ---------------------------------------------------------------------------
140
+
141
+ test('createConfigGrant creates AgentConfigGrant resource with Active status', () => {
142
+ const controller = createAgentConfigGrantController();
143
+ const result = controller.createConfigGrant({
144
+ name: 'grant-app-cfg',
145
+ orgRef: 'acme',
146
+ configMapName: 'app-config',
147
+ grantedTo: 'agent-stack-2'
148
+ });
149
+
150
+ assert.ok(!result.error, 'Should succeed');
151
+ assert.ok(result.grant, 'Should return a grant resource');
152
+ assert.equal(result.grant.kind, 'AgentConfigGrant');
153
+ assert.equal(result.grant.status.phase, 'Active');
154
+ assert.equal(result.grant.spec.configMapName, 'app-config');
155
+ assert.equal(result.grant.spec.grantedTo, 'agent-stack-2');
156
+ });
157
+
158
+ test('createConfigGrant returns error for invalid input', () => {
159
+ const controller = createAgentConfigGrantController();
160
+ const result = controller.createConfigGrant({
161
+ name: 'grant-bad',
162
+ orgRef: 'acme',
163
+ configMapName: '',
164
+ grantedTo: 'agent-1'
165
+ });
166
+ assert.ok(result.error, 'Should return an error');
167
+ });
168
+
169
+ // ---------------------------------------------------------------------------
170
+ // listGrantsForAgent
171
+ // ---------------------------------------------------------------------------
172
+
173
+ test('listGrantsForAgent filters by grantedTo field', () => {
174
+ const grants = [
175
+ { metadata: { name: 'g1' }, spec: { grantedTo: 'agent-1' } },
176
+ { metadata: { name: 'g2' }, spec: { grantedTo: 'agent-2' } },
177
+ { metadata: { name: 'g3' }, spec: { grantedTo: 'agent-1' } }
178
+ ];
179
+ const result = listGrantsForAgent(grants, 'agent-1');
180
+ assert.equal(result.length, 2);
181
+ assert.ok(result.every((g) => g.spec.grantedTo === 'agent-1'));
182
+ });
183
+
184
+ test('listGrantsForAgent returns empty array for unknown agent', () => {
185
+ const grants = [{ metadata: { name: 'g1' }, spec: { grantedTo: 'agent-1' } }];
186
+ const result = listGrantsForAgent(grants, 'agent-unknown');
187
+ assert.equal(result.length, 0);
188
+ });
189
+
190
+ // ---------------------------------------------------------------------------
191
+ // revokeGrant
192
+ // ---------------------------------------------------------------------------
193
+
194
+ test('revokeGrant transitions grant phase to Revoked', () => {
195
+ const grants = [
196
+ { metadata: { name: 'grant-1' }, spec: { secretName: 'key' }, status: { phase: 'Active' } }
197
+ ];
198
+ const result = revokeGrant(grants, 'grant-1');
199
+ assert.ok(!result.error, 'Should succeed');
200
+ assert.equal(result.grant.status.phase, 'Revoked');
201
+ assert.ok(result.grant.status.revokedAt, 'Should set revokedAt timestamp');
202
+ });
203
+
204
+ test('revokeGrant returns error for unknown grant name', () => {
205
+ const result = revokeGrant([], 'nonexistent-grant');
206
+ assert.ok(result.error, 'Should return an error');
207
+ assert.equal(result.reason, 'not-found');
208
+ });
209
+
210
+ test('revokeGrant returns error for already-revoked grant', () => {
211
+ const grants = [
212
+ { metadata: { name: 'grant-already' }, spec: {}, status: { phase: 'Revoked', revokedAt: new Date().toISOString() } }
213
+ ];
214
+ const result = revokeGrant(grants, 'grant-already');
215
+ assert.ok(result.error, 'Should return an error');
216
+ assert.equal(result.reason, 'already-revoked');
217
+ });
218
+
219
+ test('controller.revokeGrant works end-to-end via secret grant controller', () => {
220
+ const controller = createAgentSecretGrantController();
221
+ const { grant } = controller.createSecretGrant({
222
+ name: 'grant-to-revoke',
223
+ orgRef: 'acme',
224
+ secretName: 'my-key',
225
+ grantedTo: 'agent-stack-1',
226
+ permissions: ['read']
227
+ });
228
+ const result = controller.revokeGrant('grant-to-revoke', [grant]);
229
+ assert.ok(!result.error, 'Should succeed');
230
+ assert.equal(result.grant.status.phase, 'Revoked');
231
+ });