Skip to content

Commit ecdf3b2

Browse files
docs: describe ai gateway auditing context
1 parent ffe42c0 commit ecdf3b2

File tree

6 files changed

+34
-3
lines changed

6 files changed

+34
-3
lines changed

OPERATIONS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ sequenceDiagram
137137
- [ ] Tools (`sendEmail`, `getEmails`, etc.) succeed via AI Gateway
138138
- [ ] AI Gateway dashboards contain traffic with metadata (`userId`, `mcpTool`, `userEmail`)
139139
- [ ] Access and Workers logs show consistent request IDs/correlation IDs
140+
- [ ] Durable Object logs include `aiGatewayLogId` entries that match AI Gateway analytics for each tool call
140141
- [ ] Durable Object state persists across tool calls
141142

142143
## 4. Maintenance Procedures

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ clear ingress controls, governed egress, and auditable operations.
2828
3. **Egress Governance** – Route all outbound API calls (Microsoft Graph, LLMs, webhooks)
2929
through Cloudflare AI Gateway with metadata for logging and policy enforcement.
3030
4. **Operational Guardrails** – Maintain reproducible deployment, observability, and
31-
incident response checklists suitable for regulated environments.
31+
incident response checklists suitable for regulated environments.
32+
5. **Auditable Graph Egress** – All Microsoft Graph calls run through Cloudflare AI
33+
Gateway with enriched metadata (`userId`, `userEmail`, `mcpTool`, `requestId`) and
34+
expose the gateway log identifier so investigations can pivot between Workers logs
35+
and gateway analytics.
3236

3337
## Repository Map
3438

TECHNICAL.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ This data can be injected into the AI Gateway metadata payload for end-to-end tr
137137

138138
- **AI Gateway**: Primary location for monitoring outbound traffic, rate limiting, and DLP violations.
139139
- Dynamic routes expose provider/model decisions and quotas ([docs](https://developers.cloudflare.com/ai-gateway/features/dynamic-routing/)).
140+
- **Gateway Log Correlation**: Every Graph request attaches metadata (`userId`, `userEmail`, `mcpTool`, `requestId`) and records the resulting `env.AI.aiGatewayLogId`. Durable Object logs emit this identifier so operators can jump directly to the corresponding entry inside the AI Gateway dashboard.
140141
- **Workers Tail**: Use `wrangler tail --metadata` to surface request IDs and Access identity info.
141142
- **Access Audit Logs**: Provide authentication history, device posture evaluation, and policy results.
142143
- **Microsoft Entra ID**: Audit application sign-ins to confirm OAuth flows remain compliant.

src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ export interface Env {
5353
*/
5454
OAUTH_KV: KVNamespace;
5555

56-
/** Cloudflare AI Gateway binding used for Microsoft Graph egress. */
56+
/** Cloudflare AI Gateway binding used to route Microsoft Graph traffic through governed egress. */
5757
AI: Ai;
5858

59-
/** Optional Cloudflare Access headers for audit metadata. */
59+
/** Optional Cloudflare Access headers surfaced when perimeter policies are enforced (best-effort). */
6060
CF_Access_Jwt_Assertion?: string;
6161
CF_Access_Authenticated_User_Email?: string;
6262
CF_Access_Authenticated_User_Id?: string;

src/microsoft-graph.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ export interface GatewayMetadata {
7272
userId: string;
7373
mcpTool: string;
7474
requestId: string;
75+
/**
76+
* Optional identity fields enrich gateway logs so downstream analytics can correlate
77+
* Access identities with Microsoft principals without exposing raw tokens.
78+
*/
7579
userEmail?: string;
7680
microsoftUserPrincipalName?: string;
7781
microsoftDisplayName?: string;
@@ -584,6 +588,10 @@ export class MicrosoftGraphClient {
584588
metadata?: GatewayMetadata,
585589
): Promise<any> {
586590
const graphUrl = new URL(url);
591+
/**
592+
* AI Gateway expects an origin-relative path so that routing rules decide the upstream.
593+
* Persist the original query string to avoid losing pagination or filter parameters.
594+
*/
587595
const requestPayload: {
588596
method: string;
589597
path: string;
@@ -602,6 +610,10 @@ export class MicrosoftGraphClient {
602610
requestPayload.headers["Content-Type"] = "application/json";
603611
}
604612

613+
/**
614+
* Metadata drives AI Gateway analytics (user, tool invoked, correlation IDs).
615+
* Only attach when upstream code supplies context to keep requests lightweight.
616+
*/
605617
const gatewayOptions = metadata
606618
? {
607619
gateway: {
@@ -616,6 +628,10 @@ export class MicrosoftGraphClient {
616628
gatewayOptions,
617629
);
618630

631+
/**
632+
* Cloudflare exposes the latest log ID via env.AI.aiGatewayLogId so operators can
633+
* correlate Worker logs with Gateway dashboards. Cache it for the Durable Object.
634+
*/
619635
this.lastGatewayLogId = this.env.AI.aiGatewayLogId || undefined;
620636

621637
if (!response.ok) {

src/microsoft-mcp-agent.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ export class MicrosoftMCPAgent extends McpAgent<Env, State, Props> {
112112
? crypto.randomUUID()
113113
: `req-${Date.now().toString(36)}`;
114114

115+
/**
116+
* Gateway metadata forms the audit envelope that travels with every Graph call.
117+
* Prefer stable identifiers (Access headers, Microsoft props) so operations teams
118+
* can reconstruct who triggered a tool and how it propagated.
119+
*/
115120
const metadata: GatewayMetadata = {
116121
userId:
117122
this.props?.id ??
@@ -142,6 +147,10 @@ export class MicrosoftMCPAgent extends McpAgent<Env, State, Props> {
142147
toolName: string,
143148
metadata: GatewayMetadata,
144149
): void {
150+
/**
151+
* Persist the AI Gateway log ID alongside the tool invocation. This enables
152+
* real-time troubleshooting by pivoting from Durable Object logs to Gateway analytics.
153+
*/
145154
const logId = this.graphClient.getLastGatewayLogId();
146155
if (!logId) {
147156
return;

0 commit comments

Comments
 (0)