@open-everywhere/provider-teams 0.1.4 → 0.1.5

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.
package/NOTICE CHANGED
@@ -8,10 +8,40 @@ This product is licensed under the Apache License, Version 2.0 (see LICENSE).
8
8
  Built on Vercel Eve (https://github.com/vercel/eve), licensed under the
9
9
  Apache License, Version 2.0.
10
10
 
11
- @open-everywhere/core also ships a patch that modifies Vercel Eve (the file in
12
- its patches/ directory), with the oe-eve-patch command that applies it to a
13
- consumer's own installed copy. The patch is licensed under the Apache License,
14
- Version 2.0. No modified Vercel Eve files are distributed.
11
+ ---
12
+
13
+ Modifications to eve
14
+
15
+ The @open-everywhere/core package distributes patches/eve+0.54.3.patch. That
16
+ patch file is a modification of eve 0.54.3. Vercel licenses eve 0.54.3 under the
17
+ Apache License, Version 2.0. The copyright notice of eve 0.54.3 reads
18
+ "Copyright 2026 Vercel, Inc. and contributors". The Open Everywhere authors made
19
+ the changes in the patch file.
20
+
21
+ The patch modifies six files of eve 0.54.3:
22
+
23
+ dist/src/context/dynamic-tool-lifecycle.js
24
+ dist/src/execution/web-fetch/request.js
25
+ dist/src/harness/tool-loop.js
26
+ dist/src/internal/authored-package-boundary.js
27
+ dist/src/protocol/message.d.ts
28
+ dist/src/tasks/session-index.js
29
+
30
+ Open Everywhere does not ship the eve package. eve is a peer dependency, so the
31
+ consumer installs eve 0.54.3 from the registry. The patch file carries the
32
+ modified portions of eve. The oe-eve-patch command, which
33
+ @open-everywhere/core ships, applies them to the eve that the consumer
34
+ installed. The command writes no file outside the consumer's own project.
35
+
36
+ The attribution notice of eve 0.54.3 follows, as section 4(d) of the Apache
37
+ License, Version 2.0 requires. The notices for eve's bundled code-mode runtime
38
+ are not reproduced, because the patch modifies no part of that runtime.
39
+
40
+ eve
41
+ Copyright 2026 Vercel, Inc. and contributors
42
+
43
+ This product includes software developed at Vercel, Inc.
44
+ (https://vercel.com/).
15
45
 
16
46
  ---
17
47
 
@@ -46,7 +46,8 @@
46
46
  // 🔴 KNOWN LIMIT, STATED RATHER THAN HIDDEN: a denylist reports "per-team" for any FUTURE
47
47
  // tenant-wide role Microsoft adds to those endpoints. An allowlist is not available (point 1 —
48
48
  // there is nothing positive to match). Re-check the two API pages when Graph changes; the list
49
- // below is the whole of the claim, and TEAMS_READ_BOUNDARY_SOURCES records where it came from.
49
+ // in teams-graph-roles.ts (TENANT_WIDE_CHANNEL_READ_ROLES) is the whole of the claim, and
50
+ // TEAMS_READ_BOUNDARY_SOURCES below records where it came from.
50
51
  //
51
52
  // NO SIGNATURE VERIFICATION, ON PURPOSE. We decode a token WE minted, over TLS, from
52
53
  // login.microsoftonline.com, seconds earlier. It is not attacker-supplied, and the decoded value
@@ -55,16 +56,18 @@
55
56
  // of the token itself.
56
57
 
57
58
  import { appendAudit, deploymentOrg } from "@open-everywhere/core/agent/adapter-api.js";
59
+ import { boundaryFromRoles, decodeJwtRoles, tenantWideRolesIn, type TeamsReadBoundary } from "./teams-graph-roles.js";
58
60
 
59
- /** Which boundary governs this deployment's Teams channel reads.
60
- * - `per-team` — Microsoft enforces the team boundary (the RSC path, shipped default).
61
- * - `tenant-wide` — Microsoft enforces NO team boundary; only OE's domain allowlist remains.
62
- * - `unknown` — not determined yet, or the minted token did not parse. */
63
- export type TeamsReadBoundary = "per-team" | "tenant-wide" | "unknown";
64
-
65
- /** The Graph APPLICATION permissions that read Teams channel messages TENANT-WIDE. See the header
66
- * for why this is a denylist and what it can miss. */
67
- export const TENANT_WIDE_CHANNEL_READ_ROLES: readonly string[] = ["ChannelMessage.Read.All", "Group.Read.All", "Group.ReadWrite.All"];
61
+ // The pure predicate lives in teams-graph-roles.ts, which imports nothing from core (OPE-2219). The
62
+ // ops arm needs only the predicate, and this file's audit row needs the main core barrel, which
63
+ // costs about 1.9 s to load. Re-exported here so this file's public names stay the same.
64
+ export {
65
+ boundaryFromRoles,
66
+ boundaryOfGraphToken,
67
+ decodeJwtRoles,
68
+ TENANT_WIDE_CHANNEL_READ_ROLES,
69
+ type TeamsReadBoundary,
70
+ } from "./teams-graph-roles.js";
68
71
 
69
72
  /** Where the denylist came from — quoted in the runbook so a future reader can re-verify it. */
70
73
  export const TEAMS_READ_BOUNDARY_SOURCES: readonly string[] = [
@@ -76,50 +79,6 @@ export const TEAMS_READ_BOUNDARY_SOURCES: readonly string[] = [
76
79
  /** The audit action that records a boundary determination. */
77
80
  const TEAMS_READ_BOUNDARY_ACTION = "teams.read_boundary";
78
81
 
79
- /**
80
- * The `roles` claim of a JWT's payload, or `undefined` when the token does not parse as one.
81
- *
82
- * Returns an EMPTY array — not `undefined` — for a token that parses but carries no `roles` claim:
83
- * that is a real, meaningful state (an app registration with no consented Graph application
84
- * permissions), and it is exactly the per-team case. Only a genuine parse failure is `undefined`,
85
- * which is what keeps "malformed" from being reported as "per-team". Pure.
86
- */
87
- export function decodeJwtRoles(token: string): readonly string[] | undefined {
88
- const parts = token.split(".");
89
- if (parts.length !== 3 || parts[1].length === 0) return undefined;
90
- let payload: unknown;
91
- try {
92
- payload = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf-8"));
93
- } catch {
94
- return undefined;
95
- }
96
- // An ARRAY passes `typeof === "object"`, so it needs its own rejection: a JWT payload is a JSON
97
- // object, and letting an array through would read its absent `roles` as [] — reporting "per-team"
98
- // for a token that never parsed as a claims set at all.
99
- if (typeof payload !== "object" || payload === null || Array.isArray(payload)) return undefined;
100
- const roles = (payload as { roles?: unknown }).roles;
101
- if (roles === undefined) return [];
102
- if (!Array.isArray(roles)) return undefined;
103
- return roles.filter((r): r is string => typeof r === "string");
104
- }
105
-
106
- /** Every tenant-wide role the token actually carries (empty on the per-team path). Pure. */
107
- function tenantWideRolesIn(roles: readonly string[]): readonly string[] {
108
- return TENANT_WIDE_CHANNEL_READ_ROLES.filter((r) => roles.includes(r));
109
- }
110
-
111
- /** The boundary a decoded `roles` claim implies — see the header for the one-sided reasoning.
112
- * `undefined` roles (a token that did not parse) yield `"unknown"`, never a guess. Pure. */
113
- export function boundaryFromRoles(roles: readonly string[] | undefined): TeamsReadBoundary {
114
- if (roles === undefined) return "unknown";
115
- return tenantWideRolesIn(roles).length > 0 ? "tenant-wide" : "per-team";
116
- }
117
-
118
- /** The boundary a minted Graph token implies. Pure; never logs or returns any part of the token. */
119
- export function boundaryOfGraphToken(token: string): TeamsReadBoundary {
120
- return boundaryFromRoles(decodeJwtRoles(token));
121
- }
122
-
123
82
  // --- the process-held determination + its audit row -------------------------------------------
124
83
 
125
84
  let held: TeamsReadBoundary = "unknown";
@@ -0,0 +1,62 @@
1
+ // THE PURE HALF of the Teams channel-read boundary predicate (OPE-428): decode a Graph token's
2
+ // `roles` claim and map it to a boundary. teams-graph-boundary.ts holds the reasoning (why a
3
+ // denylist, what it can miss) and the process-held determination with its audit row.
4
+ //
5
+ // 🔴 NO CORE IMPORT, ON PURPOSE (OPE-2219). The ops arm (agent/ops.ts) runs this predicate in the
6
+ // standalone ops MCP server. teams-graph-boundary.ts imports the main core barrel for its audit row,
7
+ // and that barrel loads most of core: about 1.9 s on a warm Windows machine. Boundary rule 4d
8
+ // (packages/core/scripts/boundary-test.ts) refuses an ops arm that reaches the main barrel.
9
+
10
+ /** Which boundary governs this deployment's Teams channel reads.
11
+ * - `per-team` — Microsoft enforces the team boundary (the RSC path, shipped default).
12
+ * - `tenant-wide` — Microsoft enforces NO team boundary; only OE's domain allowlist remains.
13
+ * - `unknown` — not determined yet, or the minted token did not parse. */
14
+ export type TeamsReadBoundary = "per-team" | "tenant-wide" | "unknown";
15
+
16
+ /** The Graph APPLICATION permissions that read Teams channel messages TENANT-WIDE. See
17
+ * teams-graph-boundary.ts's header for why this is a denylist and what it can miss. */
18
+ export const TENANT_WIDE_CHANNEL_READ_ROLES: readonly string[] = ["ChannelMessage.Read.All", "Group.Read.All", "Group.ReadWrite.All"];
19
+
20
+ /**
21
+ * The `roles` claim of a JWT's payload, or `undefined` when the token does not parse as one.
22
+ *
23
+ * Returns an EMPTY array — not `undefined` — for a token that parses but carries no `roles` claim:
24
+ * that is a real, meaningful state (an app registration with no consented Graph application
25
+ * permissions), and it is exactly the per-team case. Only a genuine parse failure is `undefined`,
26
+ * which is what keeps "malformed" from being reported as "per-team". Pure.
27
+ */
28
+ export function decodeJwtRoles(token: string): readonly string[] | undefined {
29
+ const parts = token.split(".");
30
+ if (parts.length !== 3 || parts[1].length === 0) return undefined;
31
+ let payload: unknown;
32
+ try {
33
+ payload = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf-8"));
34
+ } catch {
35
+ return undefined;
36
+ }
37
+ // An ARRAY passes `typeof === "object"`, so it needs its own rejection: a JWT payload is a JSON
38
+ // object, and letting an array through would read its absent `roles` as [] — reporting "per-team"
39
+ // for a token that never parsed as a claims set at all.
40
+ if (typeof payload !== "object" || payload === null || Array.isArray(payload)) return undefined;
41
+ const roles = (payload as { roles?: unknown }).roles;
42
+ if (roles === undefined) return [];
43
+ if (!Array.isArray(roles)) return undefined;
44
+ return roles.filter((r): r is string => typeof r === "string");
45
+ }
46
+
47
+ /** Every tenant-wide role the token actually carries (empty on the per-team path). Pure. */
48
+ export function tenantWideRolesIn(roles: readonly string[]): readonly string[] {
49
+ return TENANT_WIDE_CHANNEL_READ_ROLES.filter((r) => roles.includes(r));
50
+ }
51
+
52
+ /** The boundary a decoded `roles` claim implies — see teams-graph-boundary.ts's header for the one-sided reasoning.
53
+ * `undefined` roles (a token that did not parse) yield `"unknown"`, never a guess. Pure. */
54
+ export function boundaryFromRoles(roles: readonly string[] | undefined): TeamsReadBoundary {
55
+ if (roles === undefined) return "unknown";
56
+ return tenantWideRolesIn(roles).length > 0 ? "tenant-wide" : "per-team";
57
+ }
58
+
59
+ /** The boundary a minted Graph token implies. Pure; never logs or returns any part of the token. */
60
+ export function boundaryOfGraphToken(token: string): TeamsReadBoundary {
61
+ return boundaryFromRoles(decodeJwtRoles(token));
62
+ }
package/agent/ops.ts CHANGED
@@ -5,7 +5,11 @@
5
5
  // WHY THIS CANNOT BE AN ENV CHECK. Both boundaries use the SAME three env vars and the SAME token
6
6
  // mint. The difference is which Graph permission the tenant consented, which lives in the token's
7
7
  // `roles` claim — so the probe mints a token and decodes it. teams-graph-boundary.ts owns the
8
- // predicate and the reasoning; this file is only the ops skin over it.
8
+ // reasoning and teams-graph-roles.ts the pure predicate; this file is only the ops skin over it.
9
+ //
10
+ // It imports core through the LIGHT door (`adapter-api-ops.js`), and the predicate from
11
+ // teams-graph-roles.ts, which imports no core (OPE-2219). The main barrel loads most of core, so one
12
+ // import of it here added about 1.9 s to the ops MCP server's start. Boundary rule 4d pins this.
9
13
  //
10
14
  // This file (not core) owns the Teams env-key knowledge — MICROSOFT_APP_ID / _PASSWORD /
11
15
  // _TENANT_ID and their TEAMS_* fallbacks are the bundle's vendor fingerprints (boundary rule 6).
@@ -18,8 +22,8 @@
18
22
  // path is a documented, supported configuration, and `missing` would make `ready` false and stop
19
23
  // an operator who has made an informed choice. It is advice, exactly like the two-role DB nudge.
20
24
 
21
- import { registerPreflightProbe, registerSurfaceCredentialProbe, type Check } from "@open-everywhere/core/agent/adapter-api.js";
22
- import { boundaryOfGraphToken, TENANT_WIDE_CHANNEL_READ_ROLES, type TeamsReadBoundary } from "./channels/teams-graph-boundary.js";
25
+ import { registerPreflightProbe, registerSurfaceCredentialProbe, type Check } from "@open-everywhere/core/agent/adapter-api-ops.js";
26
+ import { boundaryOfGraphToken, TENANT_WIDE_CHANNEL_READ_ROLES, type TeamsReadBoundary } from "./channels/teams-graph-roles.js";
23
27
 
24
28
  const TOKEN_LOGIN_BASE = "https://login.microsoftonline.com";
25
29
  const GRAPH_TOKEN_SCOPE = "https://graph.microsoft.com/.default";
@@ -1,27 +1,7 @@
1
- /** Which boundary governs this deployment's Teams channel reads.
2
- * - `per-team` — Microsoft enforces the team boundary (the RSC path, shipped default).
3
- * - `tenant-wide` — Microsoft enforces NO team boundary; only OE's domain allowlist remains.
4
- * - `unknown` — not determined yet, or the minted token did not parse. */
5
- export type TeamsReadBoundary = "per-team" | "tenant-wide" | "unknown";
6
- /** The Graph APPLICATION permissions that read Teams channel messages TENANT-WIDE. See the header
7
- * for why this is a denylist and what it can miss. */
8
- export declare const TENANT_WIDE_CHANNEL_READ_ROLES: readonly string[];
1
+ import { type TeamsReadBoundary } from "./teams-graph-roles.js";
2
+ export { boundaryFromRoles, boundaryOfGraphToken, decodeJwtRoles, TENANT_WIDE_CHANNEL_READ_ROLES, type TeamsReadBoundary, } from "./teams-graph-roles.js";
9
3
  /** Where the denylist came from — quoted in the runbook so a future reader can re-verify it. */
10
4
  export declare const TEAMS_READ_BOUNDARY_SOURCES: readonly string[];
11
- /**
12
- * The `roles` claim of a JWT's payload, or `undefined` when the token does not parse as one.
13
- *
14
- * Returns an EMPTY array — not `undefined` — for a token that parses but carries no `roles` claim:
15
- * that is a real, meaningful state (an app registration with no consented Graph application
16
- * permissions), and it is exactly the per-team case. Only a genuine parse failure is `undefined`,
17
- * which is what keeps "malformed" from being reported as "per-team". Pure.
18
- */
19
- export declare function decodeJwtRoles(token: string): readonly string[] | undefined;
20
- /** The boundary a decoded `roles` claim implies — see the header for the one-sided reasoning.
21
- * `undefined` roles (a token that did not parse) yield `"unknown"`, never a guess. Pure. */
22
- export declare function boundaryFromRoles(roles: readonly string[] | undefined): TeamsReadBoundary;
23
- /** The boundary a minted Graph token implies. Pure; never logs or returns any part of the token. */
24
- export declare function boundaryOfGraphToken(token: string): TeamsReadBoundary;
25
5
  /**
26
6
  * The boundary last determined in THIS process, `"unknown"` before the first Graph token mint.
27
7
  *
@@ -1 +1 @@
1
- {"version":3,"file":"teams-graph-boundary.d.ts","sourceRoot":"","sources":["../../../agent/channels/teams-graph-boundary.ts"],"names":[],"mappings":"AA0DA;;;+EAG+E;AAC/E,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,aAAa,GAAG,SAAS,CAAC;AAEvE;uDACuD;AACvD,eAAO,MAAM,8BAA8B,EAAE,SAAS,MAAM,EAAyE,CAAC;AAEtI,gGAAgG;AAChG,eAAO,MAAM,2BAA2B,EAAE,SAAS,MAAM,EAIxD,CAAC;AAKF;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CAiB3E;AAOD;6FAC6F;AAC7F,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,iBAAiB,CAGzF;AAED,oGAAoG;AACpG,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,CAErE;AAOD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,IAAI,iBAAiB,CAErD;AAED,sDAAsD;AACtD,wBAAgB,8BAA8B,IAAI,IAAI,CAGrD;AAED;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAwBrF"}
1
+ {"version":3,"file":"teams-graph-boundary.d.ts","sourceRoot":"","sources":["../../../agent/channels/teams-graph-boundary.ts"],"names":[],"mappings":"AA0DA,OAAO,EAAwD,KAAK,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAKtH,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,EACd,8BAA8B,EAC9B,KAAK,iBAAiB,GACvB,MAAM,wBAAwB,CAAC;AAEhC,gGAAgG;AAChG,eAAO,MAAM,2BAA2B,EAAE,SAAS,MAAM,EAIxD,CAAC;AAUF;;;;;;GAMG;AACH,wBAAgB,iBAAiB,IAAI,iBAAiB,CAErD;AAED,sDAAsD;AACtD,wBAAgB,8BAA8B,IAAI,IAAI,CAGrD;AAED;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAwBrF"}
@@ -46,7 +46,8 @@
46
46
  // 🔴 KNOWN LIMIT, STATED RATHER THAN HIDDEN: a denylist reports "per-team" for any FUTURE
47
47
  // tenant-wide role Microsoft adds to those endpoints. An allowlist is not available (point 1 —
48
48
  // there is nothing positive to match). Re-check the two API pages when Graph changes; the list
49
- // below is the whole of the claim, and TEAMS_READ_BOUNDARY_SOURCES records where it came from.
49
+ // in teams-graph-roles.ts (TENANT_WIDE_CHANNEL_READ_ROLES) is the whole of the claim, and
50
+ // TEAMS_READ_BOUNDARY_SOURCES below records where it came from.
50
51
  //
51
52
  // NO SIGNATURE VERIFICATION, ON PURPOSE. We decode a token WE minted, over TLS, from
52
53
  // login.microsoftonline.com, seconds earlier. It is not attacker-supplied, and the decoded value
@@ -54,9 +55,11 @@
54
55
  // need its JWKS and would buy nothing here. Nothing in this module logs, audits or returns any part
55
56
  // of the token itself.
56
57
  import { appendAudit, deploymentOrg } from "@open-everywhere/core/agent/adapter-api.js";
57
- /** The Graph APPLICATION permissions that read Teams channel messages TENANT-WIDE. See the header
58
- * for why this is a denylist and what it can miss. */
59
- export const TENANT_WIDE_CHANNEL_READ_ROLES = ["ChannelMessage.Read.All", "Group.Read.All", "Group.ReadWrite.All"];
58
+ import { boundaryFromRoles, decodeJwtRoles, tenantWideRolesIn } from "./teams-graph-roles.js";
59
+ // The pure predicate lives in teams-graph-roles.ts, which imports nothing from core (OPE-2219). The
60
+ // ops arm needs only the predicate, and this file's audit row needs the main core barrel, which
61
+ // costs about 1.9 s to load. Re-exported here so this file's public names stay the same.
62
+ export { boundaryFromRoles, boundaryOfGraphToken, decodeJwtRoles, TENANT_WIDE_CHANNEL_READ_ROLES, } from "./teams-graph-roles.js";
60
63
  /** Where the denylist came from — quoted in the runbook so a future reader can re-verify it. */
61
64
  export const TEAMS_READ_BOUNDARY_SOURCES = [
62
65
  "https://learn.microsoft.com/en-us/graph/api/channel-list-messages",
@@ -65,52 +68,6 @@ export const TEAMS_READ_BOUNDARY_SOURCES = [
65
68
  ];
66
69
  /** The audit action that records a boundary determination. */
67
70
  const TEAMS_READ_BOUNDARY_ACTION = "teams.read_boundary";
68
- /**
69
- * The `roles` claim of a JWT's payload, or `undefined` when the token does not parse as one.
70
- *
71
- * Returns an EMPTY array — not `undefined` — for a token that parses but carries no `roles` claim:
72
- * that is a real, meaningful state (an app registration with no consented Graph application
73
- * permissions), and it is exactly the per-team case. Only a genuine parse failure is `undefined`,
74
- * which is what keeps "malformed" from being reported as "per-team". Pure.
75
- */
76
- export function decodeJwtRoles(token) {
77
- const parts = token.split(".");
78
- if (parts.length !== 3 || parts[1].length === 0)
79
- return undefined;
80
- let payload;
81
- try {
82
- payload = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf-8"));
83
- }
84
- catch {
85
- return undefined;
86
- }
87
- // An ARRAY passes `typeof === "object"`, so it needs its own rejection: a JWT payload is a JSON
88
- // object, and letting an array through would read its absent `roles` as [] — reporting "per-team"
89
- // for a token that never parsed as a claims set at all.
90
- if (typeof payload !== "object" || payload === null || Array.isArray(payload))
91
- return undefined;
92
- const roles = payload.roles;
93
- if (roles === undefined)
94
- return [];
95
- if (!Array.isArray(roles))
96
- return undefined;
97
- return roles.filter((r) => typeof r === "string");
98
- }
99
- /** Every tenant-wide role the token actually carries (empty on the per-team path). Pure. */
100
- function tenantWideRolesIn(roles) {
101
- return TENANT_WIDE_CHANNEL_READ_ROLES.filter((r) => roles.includes(r));
102
- }
103
- /** The boundary a decoded `roles` claim implies — see the header for the one-sided reasoning.
104
- * `undefined` roles (a token that did not parse) yield `"unknown"`, never a guess. Pure. */
105
- export function boundaryFromRoles(roles) {
106
- if (roles === undefined)
107
- return "unknown";
108
- return tenantWideRolesIn(roles).length > 0 ? "tenant-wide" : "per-team";
109
- }
110
- /** The boundary a minted Graph token implies. Pure; never logs or returns any part of the token. */
111
- export function boundaryOfGraphToken(token) {
112
- return boundaryFromRoles(decodeJwtRoles(token));
113
- }
114
71
  // --- the process-held determination + its audit row -------------------------------------------
115
72
  let held = "unknown";
116
73
  let heldRoles = [];
@@ -1 +1 @@
1
- {"version":3,"file":"teams-graph-boundary.js","sourceRoot":"","sources":["../../../agent/channels/teams-graph-boundary.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,EAAE;AACF,iGAAiG;AACjG,gGAAgG;AAChG,EAAE;AACF,mGAAmG;AACnG,4FAA4F;AAC5F,mGAAmG;AACnG,yEAAyE;AACzE,iGAAiG;AACjG,kGAAkG;AAClG,iFAAiF;AACjF,6EAA6E;AAC7E,EAAE;AACF,+FAA+F;AAC/F,iGAAiG;AACjG,EAAE;AACF,wFAAwF;AACxF,EAAE;AACF,kGAAkG;AAClG,iGAAiG;AACjG,mGAAmG;AACnG,8FAA8F;AAC9F,gGAAgG;AAChG,8FAA8F;AAC9F,8FAA8F;AAC9F,sDAAsD;AACtD,EAAE;AACF,iFAAiF;AACjF,EAAE;AACF,mGAAmG;AACnG,+FAA+F;AAC/F,oGAAoG;AACpG,0FAA0F;AAC1F,6FAA6F;AAC7F,2EAA2E;AAC3E,EAAE;AACF,mGAAmG;AACnG,gGAAgG;AAChG,qGAAqG;AACrG,iGAAiG;AACjG,+FAA+F;AAC/F,mGAAmG;AACnG,iGAAiG;AACjG,EAAE;AACF,0FAA0F;AAC1F,+FAA+F;AAC/F,+FAA+F;AAC/F,+FAA+F;AAC/F,EAAE;AACF,qFAAqF;AACrF,iGAAiG;AACjG,iGAAiG;AACjG,oGAAoG;AACpG,uBAAuB;AAEvB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,4CAA4C,CAAC;AAQxF;uDACuD;AACvD,MAAM,CAAC,MAAM,8BAA8B,GAAsB,CAAC,yBAAyB,EAAE,gBAAgB,EAAE,qBAAqB,CAAC,CAAC;AAEtI,gGAAgG;AAChG,MAAM,CAAC,MAAM,2BAA2B,GAAsB;IAC5D,mEAAmE;IACnE,sEAAsE;IACtE,mGAAmG;CACpG,CAAC;AAEF,8DAA8D;AAC9D,MAAM,0BAA0B,GAAG,qBAAqB,CAAC;AAEzD;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAClE,IAAI,OAAgB,CAAC;IACrB,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,gGAAgG;IAChG,kGAAkG;IAClG,wDAAwD;IACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,SAAS,CAAC;IAChG,MAAM,KAAK,GAAI,OAA+B,CAAC,KAAK,CAAC;IACrD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACnC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5C,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;AACjE,CAAC;AAED,4FAA4F;AAC5F,SAAS,iBAAiB,CAAC,KAAwB;IACjD,OAAO,8BAA8B,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AACzE,CAAC;AAED;6FAC6F;AAC7F,MAAM,UAAU,iBAAiB,CAAC,KAAoC;IACpE,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,OAAO,iBAAiB,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC;AAC1E,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,OAAO,iBAAiB,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,iGAAiG;AAEjG,IAAI,IAAI,GAAsB,SAAS,CAAC;AACxC,IAAI,SAAS,GAAsB,EAAE,CAAC;AAEtC;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,8BAA8B;IAC5C,IAAI,GAAG,SAAS,CAAC;IACjB,SAAS,GAAG,EAAE,CAAC;AACjB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,KAAa;IACvD,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,UAAU,GAAG,iBAAiB,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IAClD,MAAM,OAAO,GAAG,QAAQ,KAAK,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClF,IAAI,GAAG,QAAQ,CAAC;IAChB,SAAS,GAAG,UAAU,CAAC;IACvB,IAAI,CAAC,OAAO;QAAE,OAAO,QAAQ,CAAC;IAC9B,IAAI,CAAC;QACH,MAAM,WAAW,CAAC;YAChB,GAAG,EAAE,aAAa,EAAE;YACpB,QAAQ,EAAE,OAAO;YACjB,SAAS,EAAE,SAAS;YACpB,MAAM,EAAE,0BAA0B;YAClC,MAAM,EAAE;gBACN,QAAQ;gBACR,eAAe,EAAE,CAAC,GAAG,UAAU,CAAC;gBAChC,UAAU,EAAE,QAAQ,KAAK,aAAa,CAAC,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAAC,wBAAwB;aACvG;SACF,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,oEAAoE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClG,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"teams-graph-boundary.js","sourceRoot":"","sources":["../../../agent/channels/teams-graph-boundary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /** Which boundary governs this deployment's Teams channel reads.
2
+ * - `per-team` — Microsoft enforces the team boundary (the RSC path, shipped default).
3
+ * - `tenant-wide` — Microsoft enforces NO team boundary; only OE's domain allowlist remains.
4
+ * - `unknown` — not determined yet, or the minted token did not parse. */
5
+ export type TeamsReadBoundary = "per-team" | "tenant-wide" | "unknown";
6
+ /** The Graph APPLICATION permissions that read Teams channel messages TENANT-WIDE. See
7
+ * teams-graph-boundary.ts's header for why this is a denylist and what it can miss. */
8
+ export declare const TENANT_WIDE_CHANNEL_READ_ROLES: readonly string[];
9
+ /**
10
+ * The `roles` claim of a JWT's payload, or `undefined` when the token does not parse as one.
11
+ *
12
+ * Returns an EMPTY array — not `undefined` — for a token that parses but carries no `roles` claim:
13
+ * that is a real, meaningful state (an app registration with no consented Graph application
14
+ * permissions), and it is exactly the per-team case. Only a genuine parse failure is `undefined`,
15
+ * which is what keeps "malformed" from being reported as "per-team". Pure.
16
+ */
17
+ export declare function decodeJwtRoles(token: string): readonly string[] | undefined;
18
+ /** Every tenant-wide role the token actually carries (empty on the per-team path). Pure. */
19
+ export declare function tenantWideRolesIn(roles: readonly string[]): readonly string[];
20
+ /** The boundary a decoded `roles` claim implies — see teams-graph-boundary.ts's header for the one-sided reasoning.
21
+ * `undefined` roles (a token that did not parse) yield `"unknown"`, never a guess. Pure. */
22
+ export declare function boundaryFromRoles(roles: readonly string[] | undefined): TeamsReadBoundary;
23
+ /** The boundary a minted Graph token implies. Pure; never logs or returns any part of the token. */
24
+ export declare function boundaryOfGraphToken(token: string): TeamsReadBoundary;
25
+ //# sourceMappingURL=teams-graph-roles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"teams-graph-roles.d.ts","sourceRoot":"","sources":["../../../agent/channels/teams-graph-roles.ts"],"names":[],"mappings":"AASA;;;+EAG+E;AAC/E,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,aAAa,GAAG,SAAS,CAAC;AAEvE;wFACwF;AACxF,eAAO,MAAM,8BAA8B,EAAE,SAAS,MAAM,EAAyE,CAAC;AAEtI;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CAiB3E;AAED,4FAA4F;AAC5F,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,MAAM,EAAE,CAE7E;AAED;6FAC6F;AAC7F,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,iBAAiB,CAGzF;AAED,oGAAoG;AACpG,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,CAErE"}
@@ -0,0 +1,58 @@
1
+ // THE PURE HALF of the Teams channel-read boundary predicate (OPE-428): decode a Graph token's
2
+ // `roles` claim and map it to a boundary. teams-graph-boundary.ts holds the reasoning (why a
3
+ // denylist, what it can miss) and the process-held determination with its audit row.
4
+ //
5
+ // 🔴 NO CORE IMPORT, ON PURPOSE (OPE-2219). The ops arm (agent/ops.ts) runs this predicate in the
6
+ // standalone ops MCP server. teams-graph-boundary.ts imports the main core barrel for its audit row,
7
+ // and that barrel loads most of core: about 1.9 s on a warm Windows machine. Boundary rule 4d
8
+ // (packages/core/scripts/boundary-test.ts) refuses an ops arm that reaches the main barrel.
9
+ /** The Graph APPLICATION permissions that read Teams channel messages TENANT-WIDE. See
10
+ * teams-graph-boundary.ts's header for why this is a denylist and what it can miss. */
11
+ export const TENANT_WIDE_CHANNEL_READ_ROLES = ["ChannelMessage.Read.All", "Group.Read.All", "Group.ReadWrite.All"];
12
+ /**
13
+ * The `roles` claim of a JWT's payload, or `undefined` when the token does not parse as one.
14
+ *
15
+ * Returns an EMPTY array — not `undefined` — for a token that parses but carries no `roles` claim:
16
+ * that is a real, meaningful state (an app registration with no consented Graph application
17
+ * permissions), and it is exactly the per-team case. Only a genuine parse failure is `undefined`,
18
+ * which is what keeps "malformed" from being reported as "per-team". Pure.
19
+ */
20
+ export function decodeJwtRoles(token) {
21
+ const parts = token.split(".");
22
+ if (parts.length !== 3 || parts[1].length === 0)
23
+ return undefined;
24
+ let payload;
25
+ try {
26
+ payload = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf-8"));
27
+ }
28
+ catch {
29
+ return undefined;
30
+ }
31
+ // An ARRAY passes `typeof === "object"`, so it needs its own rejection: a JWT payload is a JSON
32
+ // object, and letting an array through would read its absent `roles` as [] — reporting "per-team"
33
+ // for a token that never parsed as a claims set at all.
34
+ if (typeof payload !== "object" || payload === null || Array.isArray(payload))
35
+ return undefined;
36
+ const roles = payload.roles;
37
+ if (roles === undefined)
38
+ return [];
39
+ if (!Array.isArray(roles))
40
+ return undefined;
41
+ return roles.filter((r) => typeof r === "string");
42
+ }
43
+ /** Every tenant-wide role the token actually carries (empty on the per-team path). Pure. */
44
+ export function tenantWideRolesIn(roles) {
45
+ return TENANT_WIDE_CHANNEL_READ_ROLES.filter((r) => roles.includes(r));
46
+ }
47
+ /** The boundary a decoded `roles` claim implies — see teams-graph-boundary.ts's header for the one-sided reasoning.
48
+ * `undefined` roles (a token that did not parse) yield `"unknown"`, never a guess. Pure. */
49
+ export function boundaryFromRoles(roles) {
50
+ if (roles === undefined)
51
+ return "unknown";
52
+ return tenantWideRolesIn(roles).length > 0 ? "tenant-wide" : "per-team";
53
+ }
54
+ /** The boundary a minted Graph token implies. Pure; never logs or returns any part of the token. */
55
+ export function boundaryOfGraphToken(token) {
56
+ return boundaryFromRoles(decodeJwtRoles(token));
57
+ }
58
+ //# sourceMappingURL=teams-graph-roles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"teams-graph-roles.js","sourceRoot":"","sources":["../../../agent/channels/teams-graph-roles.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,6FAA6F;AAC7F,qFAAqF;AACrF,EAAE;AACF,kGAAkG;AAClG,qGAAqG;AACrG,8FAA8F;AAC9F,4FAA4F;AAQ5F;wFACwF;AACxF,MAAM,CAAC,MAAM,8BAA8B,GAAsB,CAAC,yBAAyB,EAAE,gBAAgB,EAAE,qBAAqB,CAAC,CAAC;AAEtI;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAClE,IAAI,OAAgB,CAAC;IACrB,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,gGAAgG;IAChG,kGAAkG;IAClG,wDAAwD;IACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,SAAS,CAAC;IAChG,MAAM,KAAK,GAAI,OAA+B,CAAC,KAAK,CAAC;IACrD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACnC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5C,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;AACjE,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,iBAAiB,CAAC,KAAwB;IACxD,OAAO,8BAA8B,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AACzE,CAAC;AAED;6FAC6F;AAC7F,MAAM,UAAU,iBAAiB,CAAC,KAAoC;IACpE,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,OAAO,iBAAiB,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC;AAC1E,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,OAAO,iBAAiB,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;AAClD,CAAC"}
@@ -1,5 +1,5 @@
1
- import { type Check } from "@open-everywhere/core/agent/adapter-api.js";
2
- import { type TeamsReadBoundary } from "./channels/teams-graph-boundary.js";
1
+ import { type Check } from "@open-everywhere/core/agent/adapter-api-ops.js";
2
+ import { type TeamsReadBoundary } from "./channels/teams-graph-roles.js";
3
3
  /** The check line for a determined boundary. `ok` only on the per-team path — that is the only one
4
4
  * where Microsoft itself holds the line. */
5
5
  export declare function boundaryCheck(boundary: TeamsReadBoundary): Check;
@@ -1 +1 @@
1
- {"version":3,"file":"ops.d.ts","sourceRoot":"","sources":["../../agent/ops.ts"],"names":[],"mappings":"AAoBA,OAAO,EAA0D,KAAK,KAAK,EAAE,MAAM,4CAA4C,CAAC;AAChI,OAAO,EAAwD,KAAK,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAmClI;6CAC6C;AAC7C,wBAAgB,aAAa,CAAC,QAAQ,EAAE,iBAAiB,GAAG,KAAK,CA4BhE;AAED,wFAAwF;AACxF,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,SAAS,KAAK,EAAE,CAAC,CA6B1F;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAGvC"}
1
+ {"version":3,"file":"ops.d.ts","sourceRoot":"","sources":["../../agent/ops.ts"],"names":[],"mappings":"AAwBA,OAAO,EAA0D,KAAK,KAAK,EAAE,MAAM,gDAAgD,CAAC;AACpI,OAAO,EAAwD,KAAK,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAmC/H;6CAC6C;AAC7C,wBAAgB,aAAa,CAAC,QAAQ,EAAE,iBAAiB,GAAG,KAAK,CA4BhE;AAED,wFAAwF;AACxF,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,SAAS,KAAK,EAAE,CAAC,CA6B1F;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAGvC"}
package/dist/agent/ops.js CHANGED
@@ -5,7 +5,11 @@
5
5
  // WHY THIS CANNOT BE AN ENV CHECK. Both boundaries use the SAME three env vars and the SAME token
6
6
  // mint. The difference is which Graph permission the tenant consented, which lives in the token's
7
7
  // `roles` claim — so the probe mints a token and decodes it. teams-graph-boundary.ts owns the
8
- // predicate and the reasoning; this file is only the ops skin over it.
8
+ // reasoning and teams-graph-roles.ts the pure predicate; this file is only the ops skin over it.
9
+ //
10
+ // It imports core through the LIGHT door (`adapter-api-ops.js`), and the predicate from
11
+ // teams-graph-roles.ts, which imports no core (OPE-2219). The main barrel loads most of core, so one
12
+ // import of it here added about 1.9 s to the ops MCP server's start. Boundary rule 4d pins this.
9
13
  //
10
14
  // This file (not core) owns the Teams env-key knowledge — MICROSOFT_APP_ID / _PASSWORD /
11
15
  // _TENANT_ID and their TEAMS_* fallbacks are the bundle's vendor fingerprints (boundary rule 6).
@@ -17,8 +21,8 @@
17
21
  // Teams lines). A mint that fails ⇒ one `info` line saying so. NEVER `missing`: the tenant-wide
18
22
  // path is a documented, supported configuration, and `missing` would make `ready` false and stop
19
23
  // an operator who has made an informed choice. It is advice, exactly like the two-role DB nudge.
20
- import { registerPreflightProbe, registerSurfaceCredentialProbe } from "@open-everywhere/core/agent/adapter-api.js";
21
- import { boundaryOfGraphToken, TENANT_WIDE_CHANNEL_READ_ROLES } from "./channels/teams-graph-boundary.js";
24
+ import { registerPreflightProbe, registerSurfaceCredentialProbe } from "@open-everywhere/core/agent/adapter-api-ops.js";
25
+ import { boundaryOfGraphToken, TENANT_WIDE_CHANNEL_READ_ROLES } from "./channels/teams-graph-roles.js";
22
26
  const TOKEN_LOGIN_BASE = "https://login.microsoftonline.com";
23
27
  const GRAPH_TOKEN_SCOPE = "https://graph.microsoft.com/.default";
24
28
  /** A preflight must not hang on a slow or unreachable identity endpoint. */
@@ -1 +1 @@
1
- {"version":3,"file":"ops.js","sourceRoot":"","sources":["../../agent/ops.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ops.js","sourceRoot":"","sources":["../../agent/ops.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-everywhere/provider-teams",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Open Everywhere Microsoft Teams provider — Teams channel and chat surfaces via Microsoft Graph.",
5
5
  "keywords": [
6
6
  "agent",
@@ -73,6 +73,10 @@
73
73
  "types": "./dist/agent/channels/teams-graph-boundary.d.ts",
74
74
  "default": "./dist/agent/channels/teams-graph-boundary.js"
75
75
  },
76
+ "./agent/channels/teams-graph-roles.js": {
77
+ "types": "./dist/agent/channels/teams-graph-roles.d.ts",
78
+ "default": "./dist/agent/channels/teams-graph-roles.js"
79
+ },
76
80
  "./agent/channels/teams-graph-team-id.js": {
77
81
  "types": "./dist/agent/channels/teams-graph-team-id.d.ts",
78
82
  "default": "./dist/agent/channels/teams-graph-team-id.js"
@@ -155,7 +159,7 @@
155
159
  "prepack": "npm run build",
156
160
  "typecheck": "tsc --noEmit -p tsconfig.json",
157
161
  "test": "npm run test:chain",
158
- "test:chain": "npm run test:teams && npm run test:teams-connector && npm run test:teams-connector-seam && npm run test:teams-read && npm run test:teams-graph-team-id && npm run test:teams-fire-eligibility && npm run test:teams-input-response && npm run test:teams-bot-name && npm run test:teams-stop && npm run test:teams-reaction-feedback && npm run test:teams-engagement && npm run test:teams-message-ops && npm run test:teams-id-restore && npm run test:teams-spend-attribution",
162
+ "test:chain": "tsx ../../../scripts/chain/run-chain.ts",
159
163
  "test:teams": "NODE_NO_WARNINGS=1 tsx scripts/teams-test.ts",
160
164
  "test:teams-connector": "NODE_NO_WARNINGS=1 tsx scripts/teams-connector-test.ts",
161
165
  "test:teams-connector-seam": "NODE_NO_WARNINGS=1 tsx scripts/teams-connector-seam-test.ts",
@@ -172,7 +176,7 @@
172
176
  "test:teams-spend-attribution": "NODE_NO_WARNINGS=1 tsx scripts/teams-spend-attribution-test.ts"
173
177
  },
174
178
  "dependencies": {
175
- "@open-everywhere/core": "0.1.4",
179
+ "@open-everywhere/core": "0.1.5",
176
180
  "zod": "4.5.4"
177
181
  },
178
182
  "peerDependencies": {