@agent-native/dispatch 0.7.0 → 0.8.1

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 (235) hide show
  1. package/README.md +56 -3
  2. package/dist/actions/apply-dream-proposal.d.ts +3 -0
  3. package/dist/actions/apply-dream-proposal.d.ts.map +1 -0
  4. package/dist/actions/apply-dream-proposal.js +11 -0
  5. package/dist/actions/apply-dream-proposal.js.map +1 -0
  6. package/dist/actions/create-dream-report.d.ts +3 -0
  7. package/dist/actions/create-dream-report.d.ts.map +1 -0
  8. package/dist/actions/create-dream-report.js +67 -0
  9. package/dist/actions/create-dream-report.js.map +1 -0
  10. package/dist/actions/create-workspace-resource.js +3 -3
  11. package/dist/actions/create-workspace-resource.js.map +1 -1
  12. package/dist/actions/delete-workspace-resource.js +1 -1
  13. package/dist/actions/delete-workspace-resource.js.map +1 -1
  14. package/dist/actions/ensure-dream-job.d.ts +3 -0
  15. package/dist/actions/ensure-dream-job.d.ts.map +1 -0
  16. package/dist/actions/ensure-dream-job.js +73 -0
  17. package/dist/actions/ensure-dream-job.js.map +1 -0
  18. package/dist/actions/get-dream-settings.d.ts +3 -0
  19. package/dist/actions/get-dream-settings.d.ts.map +1 -0
  20. package/dist/actions/get-dream-settings.js +11 -0
  21. package/dist/actions/get-dream-settings.js.map +1 -0
  22. package/dist/actions/get-dream.d.ts +3 -0
  23. package/dist/actions/get-dream.d.ts.map +1 -0
  24. package/dist/actions/get-dream.js +13 -0
  25. package/dist/actions/get-dream.js.map +1 -0
  26. package/dist/actions/get-workspace-resource-effective-context.d.ts +3 -0
  27. package/dist/actions/get-workspace-resource-effective-context.d.ts.map +1 -0
  28. package/dist/actions/get-workspace-resource-effective-context.js +27 -0
  29. package/dist/actions/get-workspace-resource-effective-context.js.map +1 -0
  30. package/dist/actions/index.d.ts.map +1 -1
  31. package/dist/actions/index.js +30 -4
  32. package/dist/actions/index.js.map +1 -1
  33. package/dist/actions/list-dream-candidates.d.ts +3 -0
  34. package/dist/actions/list-dream-candidates.d.ts.map +1 -0
  35. package/dist/actions/list-dream-candidates.js +68 -0
  36. package/dist/actions/list-dream-candidates.js.map +1 -0
  37. package/dist/actions/list-dreams.d.ts +3 -0
  38. package/dist/actions/list-dreams.d.ts.map +1 -0
  39. package/dist/actions/list-dreams.js +17 -0
  40. package/dist/actions/list-dreams.js.map +1 -0
  41. package/dist/actions/list-workspace-resources-for-app.d.ts +3 -0
  42. package/dist/actions/list-workspace-resources-for-app.d.ts.map +1 -0
  43. package/dist/actions/list-workspace-resources-for-app.js +12 -0
  44. package/dist/actions/list-workspace-resources-for-app.js.map +1 -0
  45. package/dist/actions/list-workspace-resources.js +1 -1
  46. package/dist/actions/list-workspace-resources.js.map +1 -1
  47. package/dist/actions/navigate.d.ts +1 -0
  48. package/dist/actions/navigate.d.ts.map +1 -1
  49. package/dist/actions/navigate.js +2 -1
  50. package/dist/actions/navigate.js.map +1 -1
  51. package/dist/actions/preview-dream-proposal.d.ts +3 -0
  52. package/dist/actions/preview-dream-proposal.d.ts.map +1 -0
  53. package/dist/actions/preview-dream-proposal.js +13 -0
  54. package/dist/actions/preview-dream-proposal.js.map +1 -0
  55. package/dist/actions/preview-workspace-resource-change.d.ts +3 -0
  56. package/dist/actions/preview-workspace-resource-change.d.ts.map +1 -0
  57. package/dist/actions/preview-workspace-resource-change.js +24 -0
  58. package/dist/actions/preview-workspace-resource-change.js.map +1 -0
  59. package/dist/actions/reject-dream-proposal.d.ts +3 -0
  60. package/dist/actions/reject-dream-proposal.d.ts.map +1 -0
  61. package/dist/actions/reject-dream-proposal.js +12 -0
  62. package/dist/actions/reject-dream-proposal.js.map +1 -0
  63. package/dist/actions/restore-starter-workspace-resources.d.ts +3 -0
  64. package/dist/actions/restore-starter-workspace-resources.d.ts.map +1 -0
  65. package/dist/actions/restore-starter-workspace-resources.js +14 -0
  66. package/dist/actions/restore-starter-workspace-resources.js.map +1 -0
  67. package/dist/actions/send-code-agent-remote-command.d.ts +3 -0
  68. package/dist/actions/send-code-agent-remote-command.d.ts.map +1 -0
  69. package/dist/actions/send-code-agent-remote-command.js +53 -0
  70. package/dist/actions/send-code-agent-remote-command.js.map +1 -0
  71. package/dist/actions/set-dream-settings.d.ts +3 -0
  72. package/dist/actions/set-dream-settings.d.ts.map +1 -0
  73. package/dist/actions/set-dream-settings.js +41 -0
  74. package/dist/actions/set-dream-settings.js.map +1 -0
  75. package/dist/actions/start-workspace-app-creation.js +1 -1
  76. package/dist/actions/start-workspace-app-creation.js.map +1 -1
  77. package/dist/actions/update-workspace-resource.js +1 -1
  78. package/dist/actions/update-workspace-resource.js.map +1 -1
  79. package/dist/actions/view-screen.d.ts.map +1 -1
  80. package/dist/actions/view-screen.js +73 -2
  81. package/dist/actions/view-screen.js.map +1 -1
  82. package/dist/components/approval-value-block.d.ts +7 -0
  83. package/dist/components/approval-value-block.d.ts.map +1 -0
  84. package/dist/components/approval-value-block.js +22 -0
  85. package/dist/components/approval-value-block.js.map +1 -0
  86. package/dist/components/create-app-popover.d.ts.map +1 -1
  87. package/dist/components/create-app-popover.js +6 -5
  88. package/dist/components/create-app-popover.js.map +1 -1
  89. package/dist/components/layout/Layout.d.ts.map +1 -1
  90. package/dist/components/layout/Layout.js +8 -1
  91. package/dist/components/layout/Layout.js.map +1 -1
  92. package/dist/components/ui/chart.d.ts +1 -1
  93. package/dist/components/workspace-app-card.d.ts.map +1 -1
  94. package/dist/components/workspace-app-card.js +25 -4
  95. package/dist/components/workspace-app-card.js.map +1 -1
  96. package/dist/components/workspace-resource-effective-stack.d.ts +11 -0
  97. package/dist/components/workspace-resource-effective-stack.d.ts.map +1 -0
  98. package/dist/components/workspace-resource-effective-stack.js +59 -0
  99. package/dist/components/workspace-resource-effective-stack.js.map +1 -0
  100. package/dist/components/workspace-resource-impact-preview.d.ts +9 -0
  101. package/dist/components/workspace-resource-impact-preview.d.ts.map +1 -0
  102. package/dist/components/workspace-resource-impact-preview.js +39 -0
  103. package/dist/components/workspace-resource-impact-preview.js.map +1 -0
  104. package/dist/db/migrations.d.ts.map +1 -1
  105. package/dist/db/migrations.js +59 -0
  106. package/dist/db/migrations.js.map +1 -1
  107. package/dist/db/schema.d.ts +714 -0
  108. package/dist/db/schema.d.ts.map +1 -1
  109. package/dist/db/schema.js +44 -2
  110. package/dist/db/schema.js.map +1 -1
  111. package/dist/hooks/use-navigation-state.d.ts +3 -0
  112. package/dist/hooks/use-navigation-state.d.ts.map +1 -1
  113. package/dist/hooks/use-navigation-state.js +23 -3
  114. package/dist/hooks/use-navigation-state.js.map +1 -1
  115. package/dist/lib/utils.d.ts +2 -1
  116. package/dist/lib/utils.d.ts.map +1 -1
  117. package/dist/lib/utils.js +5 -1
  118. package/dist/lib/utils.js.map +1 -1
  119. package/dist/routes/index.d.ts.map +1 -1
  120. package/dist/routes/index.js +1 -0
  121. package/dist/routes/index.js.map +1 -1
  122. package/dist/routes/pages/approval.d.ts.map +1 -1
  123. package/dist/routes/pages/approval.js +4 -1
  124. package/dist/routes/pages/approval.js.map +1 -1
  125. package/dist/routes/pages/approvals.js +1 -1
  126. package/dist/routes/pages/approvals.js.map +1 -1
  127. package/dist/routes/pages/dream-settings.d.ts +34 -0
  128. package/dist/routes/pages/dream-settings.d.ts.map +1 -0
  129. package/dist/routes/pages/dream-settings.js +68 -0
  130. package/dist/routes/pages/dream-settings.js.map +1 -0
  131. package/dist/routes/pages/dreams.d.ts +5 -0
  132. package/dist/routes/pages/dreams.d.ts.map +1 -0
  133. package/dist/routes/pages/dreams.js +435 -0
  134. package/dist/routes/pages/dreams.js.map +1 -0
  135. package/dist/routes/pages/workspace.d.ts.map +1 -1
  136. package/dist/routes/pages/workspace.js +187 -35
  137. package/dist/routes/pages/workspace.js.map +1 -1
  138. package/dist/server/lib/app-creation-store.d.ts.map +1 -1
  139. package/dist/server/lib/app-creation-store.js +3 -2
  140. package/dist/server/lib/app-creation-store.js.map +1 -1
  141. package/dist/server/lib/dispatch-integrations.d.ts +1 -1
  142. package/dist/server/lib/dispatch-integrations.d.ts.map +1 -1
  143. package/dist/server/lib/dispatch-integrations.js +9 -4
  144. package/dist/server/lib/dispatch-integrations.js.map +1 -1
  145. package/dist/server/lib/dispatch-remote-commands.d.ts +83 -0
  146. package/dist/server/lib/dispatch-remote-commands.d.ts.map +1 -0
  147. package/dist/server/lib/dispatch-remote-commands.js +256 -0
  148. package/dist/server/lib/dispatch-remote-commands.js.map +1 -0
  149. package/dist/server/lib/dispatch-store.d.ts +26 -0
  150. package/dist/server/lib/dispatch-store.d.ts.map +1 -1
  151. package/dist/server/lib/dispatch-store.js +17 -1
  152. package/dist/server/lib/dispatch-store.js.map +1 -1
  153. package/dist/server/lib/dreams-store.d.ts +398 -0
  154. package/dist/server/lib/dreams-store.d.ts.map +1 -0
  155. package/dist/server/lib/dreams-store.js +2330 -0
  156. package/dist/server/lib/dreams-store.js.map +1 -0
  157. package/dist/server/lib/thread-debug-store.d.ts +2 -2
  158. package/dist/server/lib/vault-store.d.ts +1 -1
  159. package/dist/server/lib/workspace-resources-store.d.ts +181 -17
  160. package/dist/server/lib/workspace-resources-store.d.ts.map +1 -1
  161. package/dist/server/lib/workspace-resources-store.js +737 -108
  162. package/dist/server/lib/workspace-resources-store.js.map +1 -1
  163. package/dist/server/plugins/agent-chat.js +1 -1
  164. package/dist/server/plugins/agent-chat.js.map +1 -1
  165. package/dist/server/plugins/integrations.js +2 -2
  166. package/dist/server/plugins/integrations.js.map +1 -1
  167. package/package.json +4 -2
  168. package/src/actions/apply-dream-proposal.ts +12 -0
  169. package/src/actions/create-dream-report.ts +76 -0
  170. package/src/actions/create-workspace-resource.ts +3 -3
  171. package/src/actions/delete-workspace-resource.ts +1 -1
  172. package/src/actions/ensure-dream-job.ts +76 -0
  173. package/src/actions/get-dream-settings.ts +12 -0
  174. package/src/actions/get-dream.ts +14 -0
  175. package/src/actions/get-workspace-resource-effective-context.ts +34 -0
  176. package/src/actions/index.spec.ts +26 -0
  177. package/src/actions/index.ts +31 -4
  178. package/src/actions/list-dream-candidates.ts +77 -0
  179. package/src/actions/list-dreams.ts +17 -0
  180. package/src/actions/list-workspace-resources-for-app.ts +13 -0
  181. package/src/actions/list-workspace-resources.ts +1 -1
  182. package/src/actions/navigate.ts +2 -1
  183. package/src/actions/preview-dream-proposal.ts +14 -0
  184. package/src/actions/preview-workspace-resource-change.ts +25 -0
  185. package/src/actions/reject-dream-proposal.ts +12 -0
  186. package/src/actions/restore-starter-workspace-resources.ts +17 -0
  187. package/src/actions/send-code-agent-remote-command.ts +59 -0
  188. package/src/actions/set-dream-settings.spec.ts +81 -0
  189. package/src/actions/set-dream-settings.ts +44 -0
  190. package/src/actions/start-workspace-app-creation.ts +1 -1
  191. package/src/actions/update-workspace-resource.ts +1 -1
  192. package/src/actions/view-screen.ts +90 -2
  193. package/src/components/approval-value-block.spec.tsx +59 -0
  194. package/src/components/approval-value-block.tsx +33 -0
  195. package/src/components/create-app-popover.tsx +6 -5
  196. package/src/components/layout/Layout.tsx +8 -0
  197. package/src/components/workspace-app-card.tsx +166 -1
  198. package/src/components/workspace-resource-effective-stack.spec.tsx +125 -0
  199. package/src/components/workspace-resource-effective-stack.tsx +141 -0
  200. package/src/components/workspace-resource-impact-preview.spec.tsx +147 -0
  201. package/src/components/workspace-resource-impact-preview.tsx +116 -0
  202. package/src/db/migrations.spec.ts +79 -0
  203. package/src/db/migrations.ts +59 -0
  204. package/src/db/schema.ts +46 -2
  205. package/src/hooks/use-navigation-state.ts +24 -5
  206. package/src/lib/utils.ts +6 -1
  207. package/src/routes/index.ts +1 -0
  208. package/src/routes/pages/approval.tsx +14 -1
  209. package/src/routes/pages/approvals.tsx +1 -1
  210. package/src/routes/pages/dream-settings.spec.ts +130 -0
  211. package/src/routes/pages/dream-settings.ts +103 -0
  212. package/src/routes/pages/dreams.tsx +1828 -0
  213. package/src/routes/pages/workspace.tsx +577 -97
  214. package/src/server/lib/app-creation-store.ts +3 -2
  215. package/src/server/lib/dispatch-integrations.ts +10 -3
  216. package/src/server/lib/dispatch-remote-commands.spec.ts +167 -0
  217. package/src/server/lib/dispatch-remote-commands.ts +375 -0
  218. package/src/server/lib/dispatch-store.ts +37 -1
  219. package/src/server/lib/dreams-store.spec.ts +1492 -0
  220. package/src/server/lib/dreams-store.ts +3168 -0
  221. package/src/server/lib/workspace-resource-approval-lifecycle.spec.ts +226 -0
  222. package/src/server/lib/workspace-resources-store.spec.ts +1106 -0
  223. package/src/server/lib/workspace-resources-store.ts +1001 -134
  224. package/src/server/plugins/agent-chat.ts +1 -1
  225. package/src/server/plugins/integrations.ts +2 -2
  226. package/dist/actions/sync-workspace-resources-to-all.d.ts +0 -3
  227. package/dist/actions/sync-workspace-resources-to-all.d.ts.map +0 -1
  228. package/dist/actions/sync-workspace-resources-to-all.js +0 -9
  229. package/dist/actions/sync-workspace-resources-to-all.js.map +0 -1
  230. package/dist/actions/sync-workspace-resources-to-app.d.ts +0 -3
  231. package/dist/actions/sync-workspace-resources-to-app.d.ts.map +0 -1
  232. package/dist/actions/sync-workspace-resources-to-app.js +0 -11
  233. package/dist/actions/sync-workspace-resources-to-app.js.map +0 -1
  234. package/src/actions/sync-workspace-resources-to-all.ts +0 -10
  235. package/src/actions/sync-workspace-resources-to-app.ts +0 -12
@@ -0,0 +1,226 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
5
+
6
+ const ownerEmail = "owner+resource-lifecycle@example.test";
7
+ const approverEmail = "approver+resource-lifecycle@example.test";
8
+ const userEmail = "person+resource-lifecycle@example.test";
9
+ const orgId = "org_resource_lifecycle";
10
+ const resourcePath = "context/lifecycle-smoke.md";
11
+
12
+ const originalEnv = {
13
+ APP_NAME: process.env.APP_NAME,
14
+ DATABASE_URL: process.env.DATABASE_URL,
15
+ DATABASE_AUTH_TOKEN: process.env.DATABASE_AUTH_TOKEN,
16
+ DISPATCH_DATABASE_URL: process.env.DISPATCH_DATABASE_URL,
17
+ DISPATCH_DATABASE_AUTH_TOKEN: process.env.DISPATCH_DATABASE_AUTH_TOKEN,
18
+ };
19
+
20
+ let tempDir: string | null = null;
21
+
22
+ function restoreEnv() {
23
+ for (const [key, value] of Object.entries(originalEnv)) {
24
+ if (value === undefined) delete process.env[key];
25
+ else process.env[key] = value;
26
+ }
27
+ }
28
+
29
+ beforeEach(async () => {
30
+ tempDir = fs.mkdtempSync(
31
+ path.join(os.tmpdir(), "dispatch-resource-lifecycle-"),
32
+ );
33
+ process.env.DATABASE_URL = `file:${path.join(tempDir, "app.db")}`;
34
+ delete process.env.APP_NAME;
35
+ delete process.env.DATABASE_AUTH_TOKEN;
36
+ delete process.env.DISPATCH_DATABASE_URL;
37
+ delete process.env.DISPATCH_DATABASE_AUTH_TOKEN;
38
+ vi.resetModules();
39
+
40
+ const [{ runMigrations }, { dispatchMigrations }] = await Promise.all([
41
+ import("@agent-native/core/db"),
42
+ import("../../db/migrations.js"),
43
+ ]);
44
+ await runMigrations(dispatchMigrations, {
45
+ table: "dispatch_migrations",
46
+ })({});
47
+ });
48
+
49
+ afterEach(async () => {
50
+ try {
51
+ const { closeDbExec } = await import("@agent-native/core/db");
52
+ await closeDbExec();
53
+ } catch {}
54
+ restoreEnv();
55
+ if (tempDir) {
56
+ fs.rmSync(tempDir, { recursive: true, force: true });
57
+ tempDir = null;
58
+ }
59
+ });
60
+
61
+ describe("workspace resource approval lifecycle", () => {
62
+ it("queues, approves, materializes, and explains inherited All-app context", async () => {
63
+ const [
64
+ { getDbExec },
65
+ { runWithRequestContext },
66
+ { resourceGetByPath, resourcePut, SHARED_OWNER, WORKSPACE_OWNER },
67
+ { putOrgSetting },
68
+ {
69
+ approveRequest,
70
+ createWorkspaceResource,
71
+ getWorkspaceResourceEffectiveContext,
72
+ listWorkspaceResourcesForApp,
73
+ },
74
+ ] = await Promise.all([
75
+ import("@agent-native/core/db"),
76
+ import("@agent-native/core/server"),
77
+ import("@agent-native/core/resources/store"),
78
+ import("@agent-native/core/settings"),
79
+ import("./workspace-resources-store.js").then(async (resourcesStore) => {
80
+ const dispatchStore = await import("./dispatch-store.js");
81
+ return {
82
+ approveRequest: dispatchStore.approveRequest,
83
+ createWorkspaceResource: resourcesStore.createWorkspaceResource,
84
+ getWorkspaceResourceEffectiveContext:
85
+ resourcesStore.getWorkspaceResourceEffectiveContext,
86
+ listWorkspaceResourcesForApp:
87
+ resourcesStore.listWorkspaceResourcesForApp,
88
+ };
89
+ }),
90
+ ]);
91
+
92
+ const exec = getDbExec();
93
+
94
+ await runWithRequestContext({ userEmail: ownerEmail, orgId }, async () => {
95
+ await putOrgSetting(orgId, "dispatch-approval-policy", {
96
+ enabled: true,
97
+ approverEmails: [approverEmail],
98
+ });
99
+
100
+ const queued = await createWorkspaceResource({
101
+ kind: "knowledge",
102
+ name: "Lifecycle Smoke Context",
103
+ description: "A smoke-test resource for global inheritance.",
104
+ path: resourcePath,
105
+ content: "# Workspace lifecycle context",
106
+ scope: "all",
107
+ });
108
+
109
+ expect(queued).toEqual(
110
+ expect.objectContaining({
111
+ status: "pending",
112
+ changeType: "workspace-resource.create",
113
+ targetType: "workspace-knowledge",
114
+ }),
115
+ );
116
+
117
+ const beforeRows = await exec.execute({
118
+ sql: "SELECT * FROM workspace_resources WHERE path = ?",
119
+ args: [resourcePath],
120
+ });
121
+ expect(beforeRows.rows).toHaveLength(0);
122
+ await expect(
123
+ resourceGetByPath(WORKSPACE_OWNER, resourcePath),
124
+ ).resolves.toBeNull();
125
+
126
+ await approveRequest((queued as any).id);
127
+
128
+ const approvalRows = await exec.execute({
129
+ sql: "SELECT status, reviewed_by FROM dispatch_approval_requests WHERE id = ?",
130
+ args: [(queued as any).id],
131
+ });
132
+ expect(approvalRows.rows[0]).toMatchObject({
133
+ status: "approved",
134
+ reviewed_by: ownerEmail,
135
+ });
136
+
137
+ const afterRows = await exec.execute({
138
+ sql: "SELECT path, scope, content FROM workspace_resources WHERE path = ?",
139
+ args: [resourcePath],
140
+ });
141
+ expect(afterRows.rows).toEqual([
142
+ expect.objectContaining({
143
+ path: resourcePath,
144
+ scope: "all",
145
+ content: "# Workspace lifecycle context",
146
+ }),
147
+ ]);
148
+
149
+ const materialized = await resourceGetByPath(
150
+ WORKSPACE_OWNER,
151
+ resourcePath,
152
+ );
153
+ expect(materialized).toEqual(
154
+ expect.objectContaining({
155
+ owner: WORKSPACE_OWNER,
156
+ path: resourcePath,
157
+ content: "# Workspace lifecycle context",
158
+ }),
159
+ );
160
+
161
+ const appResources = await listWorkspaceResourcesForApp("analytics");
162
+ expect(appResources.resources).toEqual(
163
+ expect.arrayContaining([
164
+ expect.objectContaining({
165
+ path: resourcePath,
166
+ source: "workspace",
167
+ scope: "all",
168
+ grantId: null,
169
+ }),
170
+ ]),
171
+ );
172
+
173
+ const inherited = await getWorkspaceResourceEffectiveContext({
174
+ path: resourcePath,
175
+ appId: "analytics",
176
+ userEmail,
177
+ });
178
+ expect(inherited).toMatchObject({
179
+ availability: "all-apps",
180
+ availableToApp: true,
181
+ effectiveScope: "workspace",
182
+ });
183
+ expect(inherited.layers.map((layer) => layer.scope)).toEqual([
184
+ "workspace",
185
+ "shared",
186
+ "personal",
187
+ ]);
188
+
189
+ await resourcePut(SHARED_OWNER, resourcePath, "# Organization override");
190
+
191
+ const sharedOverride = await getWorkspaceResourceEffectiveContext({
192
+ path: resourcePath,
193
+ appId: "analytics",
194
+ userEmail,
195
+ });
196
+ expect(sharedOverride.effectiveScope).toBe("shared");
197
+ expect(
198
+ sharedOverride.layers.find((layer) => layer.scope === "workspace"),
199
+ ).toMatchObject({ exists: true, overridden: true });
200
+ expect(
201
+ sharedOverride.layers.find((layer) => layer.scope === "shared"),
202
+ ).toMatchObject({ exists: true, effective: true });
203
+
204
+ await resourcePut(userEmail, resourcePath, "# Personal override");
205
+
206
+ const personalOverride = await getWorkspaceResourceEffectiveContext({
207
+ path: resourcePath,
208
+ appId: "analytics",
209
+ userEmail,
210
+ });
211
+ expect(personalOverride.effectiveScope).toBe("personal");
212
+ expect(personalOverride.effectiveResource).toEqual(
213
+ expect.objectContaining({
214
+ owner: userEmail,
215
+ path: resourcePath,
216
+ }),
217
+ );
218
+ expect(
219
+ personalOverride.layers.find((layer) => layer.scope === "shared"),
220
+ ).toMatchObject({ exists: true, overridden: true });
221
+ expect(
222
+ personalOverride.layers.find((layer) => layer.scope === "personal"),
223
+ ).toMatchObject({ exists: true, effective: true });
224
+ });
225
+ });
226
+ });