@a5c-ai/krate 5.0.1-staging.04a3db697

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 (246) hide show
  1. package/Dockerfile +31 -0
  2. package/README.md +183 -0
  3. package/bin/krate-demo.mjs +23 -0
  4. package/bin/krate-server.mjs +14 -0
  5. package/dist/krate-controller-ui.json +3067 -0
  6. package/dist/krate-lifecycle.json +201 -0
  7. package/dist/krate-runtime-snapshot.json +2955 -0
  8. package/dist/krate-summary.json +722 -0
  9. package/docs/README.md +61 -0
  10. package/docs/agents/README.md +83 -0
  11. package/docs/agents/acceptance-test-matrix.md +193 -0
  12. package/docs/agents/agent-mux-adapter-contract.md +167 -0
  13. package/docs/agents/agent-mux-source-map.md +310 -0
  14. package/docs/agents/agent-run-memory-import-spec.md +256 -0
  15. package/docs/agents/agent-stack-management-spec.md +421 -0
  16. package/docs/agents/api-contract-spec.md +309 -0
  17. package/docs/agents/artifacts-writeback-spec.md +145 -0
  18. package/docs/agents/chart-packaging-spec.md +128 -0
  19. package/docs/agents/ci-orchestration-spec.md +140 -0
  20. package/docs/agents/context-assembly-spec.md +219 -0
  21. package/docs/agents/controller-reconciliation-spec.md +255 -0
  22. package/docs/agents/crd-schema-spec.md +315 -0
  23. package/docs/agents/decision-log-open-questions.md +169 -0
  24. package/docs/agents/developer-implementation-checklist.md +329 -0
  25. package/docs/agents/dispatching-design.md +262 -0
  26. package/docs/agents/gaps-agent-mux-to-krate-crds.md +298 -0
  27. package/docs/agents/glossary.md +66 -0
  28. package/docs/agents/implementation-blueprint.md +324 -0
  29. package/docs/agents/implementation-rollout-slices.md +251 -0
  30. package/docs/agents/memory-context-integration-spec.md +194 -0
  31. package/docs/agents/memory-ontology-schema-spec.md +253 -0
  32. package/docs/agents/memory-operations-runbook.md +121 -0
  33. package/docs/agents/mvp-vertical-slice-spec.md +146 -0
  34. package/docs/agents/observability-audit-spec.md +265 -0
  35. package/docs/agents/operator-runbook.md +174 -0
  36. package/docs/agents/org-memory-api-payload-examples.md +333 -0
  37. package/docs/agents/org-memory-controller-sequence-spec.md +181 -0
  38. package/docs/agents/org-memory-e2e-fixture-plan.md +161 -0
  39. package/docs/agents/org-memory-ui-implementation-map.md +114 -0
  40. package/docs/agents/org-memory-vertical-slice-spec.md +168 -0
  41. package/docs/agents/org-resource-model-delta-spec.md +111 -0
  42. package/docs/agents/org-route-resource-model-spec.md +183 -0
  43. package/docs/agents/org-scoping-namespace-spec.md +114 -0
  44. package/docs/agents/rbac-secrets-management-spec.md +406 -0
  45. package/docs/agents/repository-page-integration-spec.md +255 -0
  46. package/docs/agents/resource-contract-examples.md +808 -0
  47. package/docs/agents/resource-relationship-map.md +190 -0
  48. package/docs/agents/security-threat-model.md +188 -0
  49. package/docs/agents/shared-memory-company-brain-spec.md +358 -0
  50. package/docs/agents/storage-migration-spec.md +168 -0
  51. package/docs/agents/subagent-orchestration-spec.md +152 -0
  52. package/docs/agents/system-overview.md +88 -0
  53. package/docs/agents/tools-mcp-skills-spec.md +189 -0
  54. package/docs/agents/traceability-matrix.md +79 -0
  55. package/docs/agents/ui-flow-spec.md +211 -0
  56. package/docs/agents/ui-ux-system-spec.md +426 -0
  57. package/docs/agents/workspace-lifecycle-spec.md +166 -0
  58. package/docs/architecture-spec.md +78 -0
  59. package/docs/components/control-plane.md +78 -0
  60. package/docs/components/data-plane.md +69 -0
  61. package/docs/components/hooks-events.md +67 -0
  62. package/docs/components/identity-rbac-policy.md +73 -0
  63. package/docs/components/kubevela-oam.md +70 -0
  64. package/docs/components/operations-publishing.md +81 -0
  65. package/docs/components/runners-ci.md +66 -0
  66. package/docs/components/web-ui.md +94 -0
  67. package/docs/external/README.md +47 -0
  68. package/docs/external/bidirectional-sync-design.md +134 -0
  69. package/docs/external/cicd-interface.md +64 -0
  70. package/docs/external/external-backend-controllers.md +170 -0
  71. package/docs/external/external-backend-crds.md +234 -0
  72. package/docs/external/external-backend-ui-spec.md +151 -0
  73. package/docs/external/external-backend-ux-flows.md +115 -0
  74. package/docs/external/external-object-mapping.md +125 -0
  75. package/docs/external/git-forge-interface.md +68 -0
  76. package/docs/external/github-integration-design.md +151 -0
  77. package/docs/external/issue-tracking-interface.md +66 -0
  78. package/docs/external/provider-capability-manifests.md +204 -0
  79. package/docs/external/provider-catalog.md +139 -0
  80. package/docs/external/provider-rollout-testing.md +78 -0
  81. package/docs/external/research-results.md +48 -0
  82. package/docs/external/security-auth-permissions.md +81 -0
  83. package/docs/external/sync-state-machines.md +108 -0
  84. package/docs/external/unified-external-backend-model.md +107 -0
  85. package/docs/external/user-facing-changes.md +67 -0
  86. package/docs/gaps.md +161 -0
  87. package/docs/install.md +94 -0
  88. package/docs/krate-design.md +334 -0
  89. package/docs/local-minikube.md +55 -0
  90. package/docs/ontology/README.md +32 -0
  91. package/docs/ontology/bounded-contexts.md +29 -0
  92. package/docs/ontology/events-and-hooks.md +32 -0
  93. package/docs/ontology/oam-kubevela.md +32 -0
  94. package/docs/ontology/operations-and-release.md +25 -0
  95. package/docs/ontology/personas-and-actors.md +32 -0
  96. package/docs/ontology/policies-and-invariants.md +33 -0
  97. package/docs/ontology/problem-space.md +30 -0
  98. package/docs/ontology/resource-contracts.md +40 -0
  99. package/docs/ontology/resource-taxonomy.md +42 -0
  100. package/docs/ontology/runners-and-ci.md +29 -0
  101. package/docs/ontology/solution-space.md +24 -0
  102. package/docs/ontology/storage-and-data-boundaries.md +29 -0
  103. package/docs/ontology/validation-matrix.md +24 -0
  104. package/docs/ontology/web-ui-excellent-flows.md +32 -0
  105. package/docs/ontology/workflows.md +39 -0
  106. package/docs/ontology/world.md +35 -0
  107. package/docs/product-requirements.md +62 -0
  108. package/docs/roadmap-mvp.md +87 -0
  109. package/docs/system-requirements.md +90 -0
  110. package/docs/tests/README.md +53 -0
  111. package/docs/tests/agent-qa-plan.md +63 -0
  112. package/docs/tests/browser-ui-tests.md +62 -0
  113. package/docs/tests/ci-quality-gates.md +48 -0
  114. package/docs/tests/coverage-model.md +64 -0
  115. package/docs/tests/e2e-scenario-tests.md +53 -0
  116. package/docs/tests/fixtures-test-data.md +63 -0
  117. package/docs/tests/observability-reliability-tests.md +54 -0
  118. package/docs/tests/product-test-matrix.md +145 -0
  119. package/docs/tests/qa-adoption-roadmap.md +130 -0
  120. package/docs/tests/qa-automation-plan.md +101 -0
  121. package/docs/tests/security-compliance-tests.md +57 -0
  122. package/docs/tests/test-framework-tools.md +88 -0
  123. package/docs/tests/test-suite-layout.md +121 -0
  124. package/docs/tests/unit-integration-tests.md +48 -0
  125. package/docs/todo-kyverno +714 -0
  126. package/docs/todos.md +4 -0
  127. package/docs/user-stories.md +78 -0
  128. package/examples/minikube-demo.yaml +190 -0
  129. package/examples/oam-application.yaml +23 -0
  130. package/examples/policy-kyverno-pr-title.yaml +18 -0
  131. package/package.json +63 -0
  132. package/scripts/build.mjs +29 -0
  133. package/scripts/setup-minikube.mjs +65 -0
  134. package/scripts/smoke.mjs +37 -0
  135. package/scripts/validate-doc-coverage.mjs +152 -0
  136. package/scripts/validate-package.mjs +93 -0
  137. package/scripts/validate-ui.mjs +236 -0
  138. package/src/agent-adapter-controller.js +169 -0
  139. package/src/agent-approval-controller.js +170 -0
  140. package/src/agent-context-bundles.js +242 -0
  141. package/src/agent-dispatch-controller.js +209 -0
  142. package/src/agent-gateway-config-controller.js +147 -0
  143. package/src/agent-memory-controller.js +357 -0
  144. package/src/agent-memory-import.js +327 -0
  145. package/src/agent-memory-query.js +292 -0
  146. package/src/agent-memory-repository-source-controller.js +255 -0
  147. package/src/agent-mux-client.js +280 -0
  148. package/src/agent-permission-review.js +250 -0
  149. package/src/agent-project-controller.js +117 -0
  150. package/src/agent-provider-config-controller.js +150 -0
  151. package/src/agent-secret-config-grant-controller.js +282 -0
  152. package/src/agent-session-transcript-controller.js +189 -0
  153. package/src/agent-stack-controller.js +347 -0
  154. package/src/agent-subagent-controller.js +160 -0
  155. package/src/agent-transport-binding-controller.js +121 -0
  156. package/src/agent-trigger-controller.js +321 -0
  157. package/src/agent-workspace-controller.js +447 -0
  158. package/src/agent-writeback-controller.js +302 -0
  159. package/src/api-controller.js +541 -0
  160. package/src/argocd-gitops.js +43 -0
  161. package/src/async-controller.js +207 -0
  162. package/src/audit-controller.js +191 -0
  163. package/src/auth.js +307 -0
  164. package/src/component-catalog.js +41 -0
  165. package/src/control-plane.js +136 -0
  166. package/src/controller-client.js +50 -0
  167. package/src/controller-ui.js +551 -0
  168. package/src/data-plane.js +178 -0
  169. package/src/event-bus.js +61 -0
  170. package/src/external/conflict-controller.js +225 -0
  171. package/src/external/github/auth.js +96 -0
  172. package/src/external/github/cicd.js +180 -0
  173. package/src/external/github/git-forge.js +240 -0
  174. package/src/external/github/index.js +144 -0
  175. package/src/external/github/issue-tracking.js +163 -0
  176. package/src/external/provider-adapter.js +161 -0
  177. package/src/external/provider-resource-factory.js +161 -0
  178. package/src/external/sync-controller.js +235 -0
  179. package/src/external/webhook-controller.js +144 -0
  180. package/src/external/write-controller.js +283 -0
  181. package/src/gitea-backend.js +95 -0
  182. package/src/gitea-service.js +173 -0
  183. package/src/handoff.js +98 -0
  184. package/src/hooks-events.js +63 -0
  185. package/src/http-server.js +377 -0
  186. package/src/identity-policy.js +86 -0
  187. package/src/index.js +55 -0
  188. package/src/kubernetes-controller-async.js +511 -0
  189. package/src/kubernetes-controller.js +878 -0
  190. package/src/kubernetes-resource-gateway.js +48 -0
  191. package/src/operations.js +112 -0
  192. package/src/org-scoping.js +5 -0
  193. package/src/resource-model.js +221 -0
  194. package/src/runners-ci.js +48 -0
  195. package/src/runtime.js +196 -0
  196. package/src/snapshot-cache.js +157 -0
  197. package/src/web-ui.js +40 -0
  198. package/tests/agent-adapter-controller.test.js +361 -0
  199. package/tests/agent-approval-controller.test.js +173 -0
  200. package/tests/agent-context-bundles.test.js +278 -0
  201. package/tests/agent-dispatch-controller.test.js +315 -0
  202. package/tests/agent-gateway-config-controller.test.js +386 -0
  203. package/tests/agent-memory-controller.test.js +308 -0
  204. package/tests/agent-memory-import-snapshot.test.js +477 -0
  205. package/tests/agent-memory-query.test.js +404 -0
  206. package/tests/agent-memory-repository-source.test.js +514 -0
  207. package/tests/agent-mux-client.test.js +204 -0
  208. package/tests/agent-permission-review-v2.test.js +317 -0
  209. package/tests/agent-permission-review.test.js +209 -0
  210. package/tests/agent-project-controller.test.js +302 -0
  211. package/tests/agent-provider-config-controller.test.js +376 -0
  212. package/tests/agent-resources.test.js +228 -0
  213. package/tests/agent-secret-config-grant.test.js +231 -0
  214. package/tests/agent-session-transcript-controller.test.js +499 -0
  215. package/tests/agent-stack-controller.test.js +221 -0
  216. package/tests/agent-subagent-controller.test.js +201 -0
  217. package/tests/agent-transport-binding-controller.test.js +294 -0
  218. package/tests/agent-trigger-controller.test.js +211 -0
  219. package/tests/agent-trigger-routes.test.js +190 -0
  220. package/tests/agent-trigger-sources.test.js +245 -0
  221. package/tests/agent-workspace-controller.test.js +181 -0
  222. package/tests/agent-writeback.test.js +292 -0
  223. package/tests/approval-persistence.test.js +171 -0
  224. package/tests/async-controller.test.js +252 -0
  225. package/tests/audit-controller.test.js +227 -0
  226. package/tests/deployment.test.js +396 -0
  227. package/tests/e2e/lifecycle.test.js +117 -0
  228. package/tests/external-github-forge.test.js +560 -0
  229. package/tests/external-github-issues-cicd.test.js +520 -0
  230. package/tests/external-integration.test.js +470 -0
  231. package/tests/external-persistence.test.js +340 -0
  232. package/tests/external-provider-adapter.test.js +365 -0
  233. package/tests/external-resource-model.test.js +215 -0
  234. package/tests/external-webhook-sync.test.js +287 -0
  235. package/tests/external-write-conflict.test.js +353 -0
  236. package/tests/gitea-service.test.js +253 -0
  237. package/tests/health-check-real.test.js +165 -0
  238. package/tests/integration/full-flow.test.js +266 -0
  239. package/tests/krate.test.js +727 -0
  240. package/tests/memory-search-wiring.test.js +270 -0
  241. package/tests/org-scoping.test.js +687 -0
  242. package/tests/session-cookie-hmac.test.js +151 -0
  243. package/tests/snapshot-performance.test.js +247 -0
  244. package/tests/sse-events.test.js +107 -0
  245. package/tests/workspace-volumes.test.js +312 -0
  246. 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
+ });