@kya-os/mcp-i-cloudflare 1.7.13 → 1.7.16

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 (34) hide show
  1. package/dist/agent.d.ts.map +1 -1
  2. package/dist/agent.js +16 -4
  3. package/dist/agent.js.map +1 -1
  4. package/dist/runtime/oauth-handler.d.ts.map +1 -1
  5. package/dist/runtime/oauth-handler.js +110 -4
  6. package/dist/runtime/oauth-handler.js.map +1 -1
  7. package/dist/services/consent-audit.service.d.ts +55 -0
  8. package/dist/services/consent-audit.service.d.ts.map +1 -1
  9. package/dist/services/consent-audit.service.js +116 -0
  10. package/dist/services/consent-audit.service.js.map +1 -1
  11. package/dist/services/consent-templates/base/base-template.d.ts.map +1 -1
  12. package/dist/services/consent-templates/base/base-template.js +10 -1
  13. package/dist/services/consent-templates/base/base-template.js.map +1 -1
  14. package/dist/services/consent-templates/modes/credentials.template.d.ts.map +1 -1
  15. package/dist/services/consent-templates/modes/credentials.template.js +4 -1
  16. package/dist/services/consent-templates/modes/credentials.template.js.map +1 -1
  17. package/dist/services/consent-templates/registry.d.ts +6 -0
  18. package/dist/services/consent-templates/registry.d.ts.map +1 -1
  19. package/dist/services/consent-templates/registry.js +11 -17
  20. package/dist/services/consent-templates/registry.js.map +1 -1
  21. package/dist/services/consent-templates/template-renderer.d.ts +3 -0
  22. package/dist/services/consent-templates/template-renderer.d.ts.map +1 -1
  23. package/dist/services/consent-templates/template-renderer.js +9 -2
  24. package/dist/services/consent-templates/template-renderer.js.map +1 -1
  25. package/dist/services/consent-templates/types.d.ts +8 -0
  26. package/dist/services/consent-templates/types.d.ts.map +1 -1
  27. package/dist/services/consent.service.d.ts +29 -0
  28. package/dist/services/consent.service.d.ts.map +1 -1
  29. package/dist/services/consent.service.js +477 -256
  30. package/dist/services/consent.service.js.map +1 -1
  31. package/dist/services/credential-auth.handler.d.ts.map +1 -1
  32. package/dist/services/credential-auth.handler.js +55 -2
  33. package/dist/services/credential-auth.handler.js.map +1 -1
  34. package/package.json +6 -5
@@ -13,7 +13,7 @@ import { STORAGE_KEYS } from "../constants/storage-keys";
13
13
  import { loadDay0Config, getDelegationFieldName } from "../utils/day0-config";
14
14
  import { validateConsentApprovalRequest, } from "@kya-os/contracts/consent";
15
15
  import { AGENTSHIELD_ENDPOINTS, createDelegationAPIResponseSchema, createDelegationResponseSchema, } from "@kya-os/contracts/agentshield-api";
16
- import { fetchRemoteConfig, createUnsignedVCJWT, completeVCJWT, parseVCJWT, base64urlEncodeFromBytes, base64urlDecodeToBytes, bytesToBase64, generateDidKeyFromBase64, createDelegationVerifier, createDidKeyResolver, } from "@kya-os/mcp-i-core";
16
+ import { fetchRemoteConfig, createUnsignedVCJWT, completeVCJWT, parseVCJWT, base64urlEncodeFromBytes, base64urlDecodeToBytes, bytesToBase64, generateDidKeyFromBase64, createDelegationVerifier, createDidKeyResolver, logger, } from "@kya-os/mcp-i-core";
17
17
  import { wrapDelegationAsVC } from "@kya-os/contracts";
18
18
  import { WebCryptoProvider } from "../providers/crypto";
19
19
  import { ConsentAuditService } from "./consent-audit.service";
@@ -76,11 +76,31 @@ export class ConsentService {
76
76
  await this.auditInitPromise;
77
77
  }
78
78
  catch (error) {
79
- console.warn("[ConsentService] Audit service initialization failed:", error);
79
+ logger.warn("[ConsentService] Audit service initialization failed:", error);
80
80
  // Don't throw - audit failures shouldn't break consent flow
81
81
  }
82
82
  return this.auditService;
83
83
  }
84
+ /**
85
+ * Public audit helpers for OAuth callback handler
86
+ *
87
+ * The OAuth callback handler lives in `src/runtime/oauth-handler.ts` and only
88
+ * has access to a `ConsentService` instance (not the full runtime wiring needed
89
+ * to construct `ConsentAuditService`). These helpers bridge that gap and ensure
90
+ * OAuth auth events generate proofs when proofing is enabled.
91
+ */
92
+ async logOAuthAuthSuccess(event) {
93
+ const auditService = await this.getAuditService(event.projectId);
94
+ if (!auditService)
95
+ return;
96
+ await auditService.logOAuthSuccess(event);
97
+ }
98
+ async logOAuthAuthFailed(event) {
99
+ const auditService = await this.getAuditService(event.projectId);
100
+ if (!auditService)
101
+ return;
102
+ await auditService.logOAuthFailed(event);
103
+ }
84
104
  /**
85
105
  * Initialize audit service - fetches config from remote API
86
106
  *
@@ -95,7 +115,7 @@ export class ConsentService {
95
115
  // ✅ CRITICAL: Fetch config from remote API
96
116
  const config = await this.getConfigFromRemoteAPI(projectId);
97
117
  if (!config?.proofing?.enabled) {
98
- console.error("[ConsentService] Proofing not enabled in remote config");
118
+ logger.debug("[ConsentService] Proofing not enabled in remote config");
99
119
  return; // Proofing not enabled
100
120
  }
101
121
  // Get identity (async - requires runtime to be initialized)
@@ -105,16 +125,16 @@ export class ConsentService {
105
125
  // Get audit logger
106
126
  const auditLogger = this.runtime.getAuditLogger();
107
127
  if (!auditLogger) {
108
- console.warn("[ConsentService] AuditLogger not available");
128
+ logger.warn("[ConsentService] AuditLogger not available");
109
129
  return;
110
130
  }
111
131
  // Create audit service with fetched config
112
132
  this.auditService = new ConsentAuditService(new ProofService(config, this.runtime), auditLogger, proofGenerator, config, // ✅ Config fetched from remote API
113
133
  this.runtime);
114
- console.error("[ConsentService] Audit service initialized successfully");
134
+ logger.debug("[ConsentService] Audit service initialized successfully");
115
135
  }
116
136
  catch (error) {
117
- console.error("[ConsentService] Failed to initialize audit service:", error);
137
+ logger.debug("[ConsentService] Failed to initialize audit service:", error);
118
138
  // Don't throw - audit failures shouldn't break consent flow
119
139
  }
120
140
  }
@@ -131,7 +151,7 @@ export class ConsentService {
131
151
  */
132
152
  async getConfigFromRemoteAPI(projectId) {
133
153
  if (!this.env.AGENTSHIELD_API_KEY) {
134
- console.warn("[ConsentService] No API key for runtime config fetch");
154
+ logger.warn("[ConsentService] No API key for runtime config fetch");
135
155
  return undefined;
136
156
  }
137
157
  try {
@@ -166,11 +186,11 @@ export class ConsentService {
166
186
  const runtimeIdentity = await this.runtime?.getIdentity();
167
187
  if (runtimeIdentity?.did) {
168
188
  identityConfig.serverDid = runtimeIdentity.did;
169
- console.error("[ConsentService] Populated serverDid from runtime identity");
189
+ logger.debug("[ConsentService] Populated serverDid from runtime identity");
170
190
  }
171
191
  }
172
192
  catch (error) {
173
- console.warn("[ConsentService] Failed to get runtime identity for serverDid:", error);
193
+ logger.warn("[ConsentService] Failed to get runtime identity for serverDid:", error);
174
194
  }
175
195
  }
176
196
  }
@@ -179,7 +199,7 @@ export class ConsentService {
179
199
  return config;
180
200
  }
181
201
  catch (error) {
182
- console.warn("[ConsentService] Error fetching runtime config:", error);
202
+ logger.warn("[ConsentService] Error fetching runtime config:", error);
183
203
  return undefined;
184
204
  }
185
205
  }
@@ -210,7 +230,7 @@ export class ConsentService {
210
230
  const oauthKey = STORAGE_KEYS.oauthIdentity(oauthIdentity.provider, oauthIdentity.subject);
211
231
  const mappedUserDid = await this.env.DELEGATION_STORAGE.get(oauthKey, "text");
212
232
  if (mappedUserDid) {
213
- console.error("[ConsentService] Found persistent User DID from OAuth mapping:", {
233
+ logger.debug("[ConsentService] Found persistent User DID from OAuth mapping:", {
214
234
  provider: oauthIdentity.provider,
215
235
  userDid: mappedUserDid.substring(0, 20) + "...",
216
236
  });
@@ -218,7 +238,7 @@ export class ConsentService {
218
238
  }
219
239
  }
220
240
  catch (error) {
221
- console.warn("[ConsentService] Failed to check OAuth mapping:", error);
241
+ logger.warn("[ConsentService] Failed to check OAuth mapping:", error);
222
242
  }
223
243
  }
224
244
  // Priority 2: Check session storage for existing DID
@@ -231,7 +251,7 @@ export class ConsentService {
231
251
  }
232
252
  }
233
253
  catch (error) {
234
- console.warn("[ConsentService] Failed to read session cache:", error);
254
+ logger.warn("[ConsentService] Failed to read session cache:", error);
235
255
  }
236
256
  }
237
257
  // Phase 5: No ephemeral DID generation - session stays anonymous
@@ -250,7 +270,7 @@ export class ConsentService {
250
270
  */
251
271
  async updateSessionWithIdentity(sessionId, userDid, oauthIdentity) {
252
272
  if (!this.env.DELEGATION_STORAGE) {
253
- console.warn("[ConsentService] No DELEGATION_STORAGE - cannot persist session identity");
273
+ logger.warn("[ConsentService] No DELEGATION_STORAGE - cannot persist session identity");
254
274
  return;
255
275
  }
256
276
  const sessionKey = STORAGE_KEYS.session(sessionId);
@@ -270,7 +290,7 @@ export class ConsentService {
270
290
  await this.env.DELEGATION_STORAGE.put(userAgentKey, delegationToken, {
271
291
  expirationTtl: delegationTtl,
272
292
  });
273
- console.error("[ConsentService] 🔄 DELEGATION UPGRADE: Migrated consent-only delegation to user+agent scoped:", {
293
+ logger.debug("[ConsentService] 🔄 DELEGATION UPGRADE: Migrated consent-only delegation to user+agent scoped:", {
274
294
  sessionId: sessionId.substring(0, 8) + "...",
275
295
  userDid: userDid.substring(0, 20) + "...",
276
296
  agentDid: agentDid.substring(0, 20) + "...",
@@ -294,7 +314,7 @@ export class ConsentService {
294
314
  }),
295
315
  };
296
316
  await this.env.DELEGATION_STORAGE.put(sessionKey, JSON.stringify(sessionData), { expirationTtl: DEFAULT_SESSION_CACHE_TTL });
297
- console.error("[ConsentService] Session identity updated:", {
317
+ logger.debug("[ConsentService] Session identity updated:", {
298
318
  sessionId: sessionId.substring(0, 8) + "...",
299
319
  userDid: userDid.substring(0, 20) + "...",
300
320
  provider: oauthIdentity?.provider,
@@ -302,7 +322,7 @@ export class ConsentService {
302
322
  });
303
323
  }
304
324
  catch (error) {
305
- console.warn("[ConsentService] Failed to update session with identity:", error);
325
+ logger.warn("[ConsentService] Failed to update session with identity:", error);
306
326
  throw error;
307
327
  }
308
328
  // Create OAuth → DID mapping for future lookups
@@ -312,13 +332,13 @@ export class ConsentService {
312
332
  await this.env.DELEGATION_STORAGE.put(oauthKey, userDid, {
313
333
  expirationTtl: 90 * 24 * 60 * 60, // 90 days for persistent mapping
314
334
  });
315
- console.error("[ConsentService] Created OAuth → DID mapping:", {
335
+ logger.debug("[ConsentService] Created OAuth → DID mapping:", {
316
336
  provider: oauthIdentity.provider,
317
337
  userDid: userDid.substring(0, 20) + "...",
318
338
  });
319
339
  }
320
340
  catch (error) {
321
- console.warn("[ConsentService] Failed to create OAuth mapping:", error);
341
+ logger.warn("[ConsentService] Failed to create OAuth mapping:", error);
322
342
  // Non-fatal - session was updated successfully
323
343
  }
324
344
  }
@@ -343,12 +363,12 @@ export class ConsentService {
343
363
  const key = STORAGE_KEYS.userKeyPair(oauthIdentity.provider, oauthIdentity.subject);
344
364
  const stored = (await this.env.DELEGATION_STORAGE.get(key, "json"));
345
365
  if (stored) {
346
- console.error("[ConsentService] Found key pair in OAuth KV storage");
366
+ logger.debug("[ConsentService] Found key pair in OAuth KV storage");
347
367
  return stored;
348
368
  }
349
369
  }
350
370
  catch (error) {
351
- console.warn("[ConsentService] KV key pair lookup failed:", error);
371
+ logger.warn("[ConsentService] KV key pair lookup failed:", error);
352
372
  }
353
373
  }
354
374
  // Priority 2: Check session storage for ephemeral key pair (consent-only flow)
@@ -358,12 +378,12 @@ export class ConsentService {
358
378
  const sessionKey = STORAGE_KEYS.session(sessionId);
359
379
  const sessionData = (await this.env.DELEGATION_STORAGE.get(sessionKey, "json"));
360
380
  if (sessionData?.keyPair) {
361
- console.error("[ConsentService] Found ephemeral key pair in session storage (consent-only VC signing)");
381
+ logger.debug("[ConsentService] Found ephemeral key pair in session storage (consent-only VC signing)");
362
382
  return sessionData.keyPair;
363
383
  }
364
384
  }
365
385
  catch (error) {
366
- console.warn("[ConsentService] Session key pair lookup failed:", error);
386
+ logger.warn("[ConsentService] Session key pair lookup failed:", error);
367
387
  }
368
388
  }
369
389
  // Priority 3: Try UserDidManager (legacy path, may not be initialized)
@@ -378,7 +398,7 @@ export class ConsentService {
378
398
  }
379
399
  }
380
400
  // No key pair found
381
- console.warn("[ConsentService] No key pair found for session - user cannot sign VCs");
401
+ logger.warn("[ConsentService] No key pair found for session - user cannot sign VCs");
382
402
  return null;
383
403
  }
384
404
  /**
@@ -400,7 +420,7 @@ export class ConsentService {
400
420
  // 1. Try existing lookup first
401
421
  const existingKeyPair = await this.getKeyPairForSession(sessionId, oauthIdentity);
402
422
  if (existingKeyPair) {
403
- console.error("[ConsentService] Found existing key pair for OAuth identity");
423
+ logger.debug("[ConsentService] Found existing key pair for OAuth identity");
404
424
  return existingKeyPair;
405
425
  }
406
426
  // 2. Check KV storage directly by OAuth identity
@@ -411,16 +431,16 @@ export class ConsentService {
411
431
  const key = STORAGE_KEYS.userKeyPair(oauthIdentity.provider, oauthIdentity.subject);
412
432
  const stored = (await this.env.DELEGATION_STORAGE.get(key, "json"));
413
433
  if (stored) {
414
- console.error("[ConsentService] Found key pair in KV storage");
434
+ logger.debug("[ConsentService] Found key pair in KV storage");
415
435
  return stored;
416
436
  }
417
437
  }
418
438
  catch (error) {
419
- console.warn("[ConsentService] KV key pair lookup failed:", error);
439
+ logger.warn("[ConsentService] KV key pair lookup failed:", error);
420
440
  }
421
441
  }
422
442
  // 3. Generate new key pair
423
- console.error("[ConsentService] Generating new key pair for OAuth identity");
443
+ logger.debug("[ConsentService] Generating new key pair for OAuth identity");
424
444
  try {
425
445
  const crypto = new WebCryptoProvider();
426
446
  const rawKeyPair = await crypto.generateKeyPair();
@@ -443,20 +463,20 @@ export class ConsentService {
443
463
  await this.env.DELEGATION_STORAGE.put(key, JSON.stringify(keyPair), {
444
464
  expirationTtl: KEY_PAIR_TTL_SECONDS,
445
465
  });
446
- console.error("[ConsentService] Key pair persisted to KV storage");
466
+ logger.debug("[ConsentService] Key pair persisted to KV storage");
447
467
  }
448
468
  catch (persistError) {
449
- console.warn("[ConsentService] KV key pair persistence failed (non-fatal):", persistError);
469
+ logger.warn("[ConsentService] KV key pair persistence failed (non-fatal):", persistError);
450
470
  }
451
471
  }
452
- console.error("[ConsentService] Key pair generated:", {
472
+ logger.debug("[ConsentService] Key pair generated:", {
453
473
  did: did.substring(0, 30) + "...",
454
474
  keyId,
455
475
  });
456
476
  return keyPair;
457
477
  }
458
478
  catch (error) {
459
- console.error("[ConsentService] Key pair generation failed:", error);
479
+ logger.error("[ConsentService] Key pair generation failed:", error);
460
480
  return null;
461
481
  }
462
482
  }
@@ -489,7 +509,7 @@ export class ConsentService {
489
509
  const sessionKey = STORAGE_KEYS.session(sessionId);
490
510
  const existingSession = (await this.env.DELEGATION_STORAGE.get(sessionKey, "json"));
491
511
  if (existingSession?.userDid) {
492
- console.error("[ConsentService] Session already has userDid, reusing:", {
512
+ logger.debug("[ConsentService] Session already has userDid, reusing:", {
493
513
  sessionId: sessionId.substring(0, 20) + "...",
494
514
  userDid: existingSession.userDid.substring(0, 20) + "...",
495
515
  hasKeyPair: !!existingSession.keyPair,
@@ -498,11 +518,11 @@ export class ConsentService {
498
518
  }
499
519
  }
500
520
  catch (error) {
501
- console.warn("[ConsentService] Failed to check existing session userDid:", error);
521
+ logger.warn("[ConsentService] Failed to check existing session userDid:", error);
502
522
  }
503
523
  }
504
524
  // Generate new ephemeral keypair - THIS TIME WE STORE IT!
505
- console.error("[ConsentService] Generating ephemeral key pair for consent-only VC signing");
525
+ logger.debug("[ConsentService] Generating ephemeral key pair for consent-only VC signing");
506
526
  try {
507
527
  const crypto = new WebCryptoProvider();
508
528
  const rawKeyPair = await crypto.generateKeyPair();
@@ -528,13 +548,13 @@ export class ConsentService {
528
548
  keyPair, // Store the full key pair for VC signing!
529
549
  identityState: "ephemeral",
530
550
  }), { expirationTtl: DEFAULT_SESSION_CACHE_TTL });
531
- console.error("[ConsentService] ✅ Ephemeral key pair stored in session for VC signing");
551
+ logger.debug("[ConsentService] ✅ Ephemeral key pair stored in session for VC signing");
532
552
  }
533
553
  catch (storeError) {
534
- console.warn("[ConsentService] Failed to store ephemeral key pair (VC signing may fail):", storeError);
554
+ logger.warn("[ConsentService] Failed to store ephemeral key pair (VC signing may fail):", storeError);
535
555
  }
536
556
  }
537
- console.error("[ConsentService] ✅ Ephemeral key pair generated:", {
557
+ logger.info("[ConsentService] ✅ Ephemeral key pair generated:", {
538
558
  sessionId: sessionId.substring(0, 20) + "...",
539
559
  userDid: ephemeralUserDid.substring(0, 30) + "...",
540
560
  hasPrivateKey: true,
@@ -543,7 +563,7 @@ export class ConsentService {
543
563
  return ephemeralUserDid;
544
564
  }
545
565
  catch (error) {
546
- console.error("[ConsentService] Failed to generate ephemeral key pair:", error);
566
+ logger.debug("[ConsentService] Failed to generate ephemeral key pair:", error);
547
567
  return null;
548
568
  }
549
569
  }
@@ -567,7 +587,7 @@ export class ConsentService {
567
587
  const keyPair = providedKeyPair ??
568
588
  (await this.getKeyPairForSession(sessionId, oauthIdentity));
569
589
  if (!keyPair) {
570
- console.warn("[ConsentService] Cannot issue VC: no key pair available for session");
590
+ logger.warn("[ConsentService] Cannot issue VC: no key pair available for session");
571
591
  return null;
572
592
  }
573
593
  try {
@@ -592,7 +612,7 @@ export class ConsentService {
592
612
  const signature = base64urlEncodeFromBytes(signatureBytes);
593
613
  // Step 4: Complete the JWT
594
614
  const jwt = completeVCJWT(signingInput, signature);
595
- console.error("[ConsentService] VC issued successfully:", {
615
+ logger.debug("[ConsentService] VC issued successfully:", {
596
616
  issuerDid: keyPair.did.substring(0, 20) + "...",
597
617
  subjectDid: delegation.subjectDid.substring(0, 20) + "...",
598
618
  delegationId: delegation.id,
@@ -601,7 +621,7 @@ export class ConsentService {
601
621
  return jwt;
602
622
  }
603
623
  catch (error) {
604
- console.error("[ConsentService] Failed to issue VC:", error);
624
+ logger.error("[ConsentService] Failed to issue VC:", error);
605
625
  return null;
606
626
  }
607
627
  }
@@ -627,7 +647,7 @@ export class ConsentService {
627
647
  // Step 1: Parse JWT
628
648
  const parsed = parseVCJWT(vcJwt);
629
649
  if (!parsed) {
630
- console.warn("[ConsentService] verifyDelegationVC: Invalid JWT format");
650
+ logger.warn("[ConsentService] verifyDelegationVC: Invalid JWT format");
631
651
  return {
632
652
  valid: false,
633
653
  reason: "Invalid JWT format",
@@ -638,7 +658,7 @@ export class ConsentService {
638
658
  // Step 2: Extract VC from payload
639
659
  const vc = parsed.payload.vc;
640
660
  if (!vc) {
641
- console.warn("[ConsentService] verifyDelegationVC: No VC in JWT payload");
661
+ logger.warn("[ConsentService] verifyDelegationVC: No VC in JWT payload");
642
662
  return {
643
663
  valid: false,
644
664
  reason: "No VC in JWT payload",
@@ -678,7 +698,7 @@ export class ConsentService {
678
698
  const crypto = new WebCryptoProvider();
679
699
  const isValid = await crypto.verify(signingInputBytes, signatureBytes, publicKeyBase64);
680
700
  if (!isValid) {
681
- console.warn("[ConsentService] verifyDelegationVC: JWT signature verification failed");
701
+ logger.warn("[ConsentService] verifyDelegationVC: JWT signature verification failed");
682
702
  return {
683
703
  valid: false,
684
704
  reason: "JWT signature verification failed",
@@ -686,7 +706,7 @@ export class ConsentService {
686
706
  metrics: { totalMs: Date.now() - startTime },
687
707
  };
688
708
  }
689
- console.error("[ConsentService] verifyDelegationVC: JWT signature verified successfully");
709
+ logger.debug("[ConsentService] verifyDelegationVC: JWT signature verified successfully");
690
710
  }
691
711
  // Step 4: Run basic VC validation via DelegationCredentialVerifier
692
712
  // Skip signature verification since we already verified the JWT signature above
@@ -702,13 +722,13 @@ export class ConsentService {
702
722
  result.metrics.totalMs = Date.now() - startTime;
703
723
  }
704
724
  if (result.valid) {
705
- console.error("[ConsentService] verifyDelegationVC: VC verified successfully", {
725
+ logger.debug("[ConsentService] verifyDelegationVC: VC verified successfully", {
706
726
  issuer: vc.issuer,
707
727
  subject: vc.credentialSubject?.id,
708
728
  });
709
729
  }
710
730
  else {
711
- console.warn("[ConsentService] verifyDelegationVC: VC validation failed", {
731
+ logger.warn("[ConsentService] verifyDelegationVC: VC validation failed", {
712
732
  reason: result.reason,
713
733
  stage: result.stage,
714
734
  });
@@ -732,7 +752,7 @@ export class ConsentService {
732
752
  // Priority 0: Check for consent-only mode (authorization.type === 'none')
733
753
  // Consent-only means delegation is required but NO OAuth provider is needed
734
754
  if (toolProtection?.authorization?.type === "none") {
735
- console.error("[ConsentService] Tool is consent-only mode (authorization.type=none), OAuth NOT required", {
755
+ logger.debug("[ConsentService] Tool is consent-only mode (authorization.type=none), OAuth NOT required", {
736
756
  projectId,
737
757
  requiresDelegation: toolProtection.requiresDelegation,
738
758
  });
@@ -755,7 +775,7 @@ export class ConsentService {
755
775
  try {
756
776
  const resolvedProvider = await this.providerResolver.resolveProvider(toolProtection, projectId);
757
777
  if (resolvedProvider) {
758
- console.error("[ConsentService] OAuth required: ProviderResolver resolved provider", {
778
+ logger.debug("[ConsentService] OAuth required: ProviderResolver resolved provider", {
759
779
  projectId,
760
780
  provider: resolvedProvider,
761
781
  toolRequiresDelegation: toolProtection.requiresDelegation,
@@ -767,11 +787,22 @@ export class ConsentService {
767
787
  catch (error) {
768
788
  // Check if this is ConsentOnlyModeError - not a real error
769
789
  if (error instanceof Error && error.name === "ConsentOnlyModeError") {
770
- console.error("[ConsentService] Tool is consent-only mode (ConsentOnlyModeError), OAuth NOT required", { projectId });
790
+ logger.debug("[ConsentService] Tool is consent-only mode (ConsentOnlyModeError), OAuth NOT required", { projectId });
791
+ return false;
792
+ }
793
+ // Check for CredentialAuthModeError - credential auth does NOT require OAuth
794
+ // Use multiple detection methods to handle bundled code where class names may be mangled
795
+ const isCredentialAuthError = error instanceof Error &&
796
+ (error.name === "CredentialAuthModeError" ||
797
+ error.constructor?.name === "CredentialAuthModeError" ||
798
+ ("provider" in error &&
799
+ typeof error.provider === "string"));
800
+ if (isCredentialAuthError) {
801
+ logger.debug("[ConsentService] Tool uses credential auth (CredentialAuthModeError), OAuth NOT required", { projectId });
771
802
  return false;
772
803
  }
773
804
  // ProviderResolver failed - log but continue to fallback check
774
- console.warn("[ConsentService] ProviderResolver failed to resolve provider, falling back to project config check:", {
805
+ logger.warn("[ConsentService] ProviderResolver failed to resolve provider, falling back to project config check:", {
775
806
  projectId,
776
807
  error: error instanceof Error ? error.message : String(error),
777
808
  });
@@ -805,7 +836,7 @@ export class ConsentService {
805
836
  return false;
806
837
  }
807
838
  catch (error) {
808
- console.warn("[ConsentService] Failed to check OAuth requirement:", error);
839
+ logger.warn("[ConsentService] Failed to check OAuth requirement:", error);
809
840
  // On error, default to not requiring OAuth (backward compatibility)
810
841
  return false;
811
842
  }
@@ -846,7 +877,7 @@ export class ConsentService {
846
877
  codeChallenge = pkceChallenge.challenge;
847
878
  }
848
879
  catch (error) {
849
- console.warn("[ConsentService] Failed to generate PKCE challenge:", error);
880
+ logger.warn("[ConsentService] Failed to generate PKCE challenge:", error);
850
881
  }
851
882
  }
852
883
  // Build state data with required fields
@@ -881,7 +912,7 @@ export class ConsentService {
881
912
  // Store state data securely in KV (10 minute TTL for OAuth flow)
882
913
  await oauthSecurityService.storeOAuthState(stateValue, stateData, 600);
883
914
  stateParam = stateValue;
884
- console.error("[ConsentService] 🔒 SECURITY EVENT: OAuth state stored securely:", {
915
+ logger.debug("[ConsentService] 🔒 SECURITY EVENT: OAuth state stored securely:", {
885
916
  projectId,
886
917
  agentDid: agentDid.substring(0, 20) + "...",
887
918
  sessionId: sessionId.substring(0, 20) + "...",
@@ -894,7 +925,7 @@ export class ConsentService {
894
925
  else {
895
926
  // Fallback: Encode state as base64 (less secure, but backward compatible)
896
927
  if (!oauthSecurityService) {
897
- console.warn("[ConsentService] ⚠️ SECURITY WARNING: OAuthSecurityService not provided, using insecure state encoding");
928
+ logger.warn("[ConsentService] ⚠️ SECURITY WARNING: OAuthSecurityService not provided, using insecure state encoding");
898
929
  }
899
930
  stateParam = btoa(JSON.stringify(stateData));
900
931
  }
@@ -904,20 +935,20 @@ export class ConsentService {
904
935
  if (provider && this.providerRegistry) {
905
936
  // Lazy load providers if registry is empty (first request for this project)
906
937
  if (this.providerRegistry.getProviderNames().length === 0) {
907
- console.error("[ConsentService] Loading providers from AgentShield", {
938
+ logger.debug("[ConsentService] Loading providers from AgentShield", {
908
939
  projectId,
909
940
  provider,
910
941
  });
911
942
  try {
912
943
  await this.providerRegistry.loadFromAgentShield(projectId);
913
- console.error("[ConsentService] Providers loaded successfully", {
944
+ logger.debug("[ConsentService] Providers loaded successfully", {
914
945
  projectId,
915
946
  providers: this.providerRegistry.getProviderNames(),
916
947
  configuredProvider: this.providerRegistry.getConfiguredProvider(),
917
948
  });
918
949
  }
919
950
  catch (loadError) {
920
- console.warn("[ConsentService] Failed to load providers from AgentShield", {
951
+ logger.warn("[ConsentService] Failed to load providers from AgentShield", {
921
952
  projectId,
922
953
  error: loadError instanceof Error
923
954
  ? loadError.message
@@ -929,7 +960,7 @@ export class ConsentService {
929
960
  providerConfig = this.providerRegistry.getProvider(provider);
930
961
  }
931
962
  // Diagnostic logging to track race condition and OAuth mode selection
932
- console.error("[ConsentService] OAuth mode decision:", {
963
+ logger.debug("[ConsentService] OAuth mode decision:", {
933
964
  provider: provider || "none",
934
965
  hasProviderRegistry: !!this.providerRegistry,
935
966
  hasProviderConfig: !!providerConfig,
@@ -968,7 +999,7 @@ export class ConsentService {
968
999
  !providerConfig.proxyMode) {
969
1000
  // Use providerConfig.clientId from AgentShield dashboard config
970
1001
  const oauthClientId = providerConfig.clientId || projectId;
971
- console.error("[ConsentService] Using direct OAuth mode (PKCE)", {
1002
+ logger.debug("[ConsentService] Using direct OAuth mode (PKCE)", {
972
1003
  provider: provider || "unknown",
973
1004
  authorizationUrl: providerConfig.authorizationUrl,
974
1005
  supportsPKCE: providerConfig.supportsPKCE,
@@ -1119,7 +1150,7 @@ export class ConsentService {
1119
1150
  try {
1120
1151
  const existingUserDid = await this.env.DELEGATION_STORAGE.get(oauthKey, "text");
1121
1152
  if (existingUserDid) {
1122
- console.error("[ConsentService] OAuth identity already mapped:", {
1153
+ logger.debug("[ConsentService] OAuth identity already mapped:", {
1123
1154
  provider: oauthIdentity.provider,
1124
1155
  subject: oauthIdentity.subject.substring(0, 20) + "...",
1125
1156
  userDid: existingUserDid.substring(0, 20) + "...",
@@ -1128,7 +1159,7 @@ export class ConsentService {
1128
1159
  }
1129
1160
  }
1130
1161
  catch (error) {
1131
- console.warn("[ConsentService] Failed to check OAuth mapping:", error);
1162
+ logger.warn("[ConsentService] Failed to check OAuth mapping:", error);
1132
1163
  // Continue to check session
1133
1164
  }
1134
1165
  // Phase 5: Check for existing user DID in session
@@ -1147,14 +1178,14 @@ export class ConsentService {
1147
1178
  await this.env.DELEGATION_STORAGE.put(oauthIdentityKey, JSON.stringify(oauthIdentity), {
1148
1179
  expirationTtl: 90 * 24 * 60 * 60, // 90 days
1149
1180
  });
1150
- console.error("[ConsentService] OAuth identity linked to User DID:", {
1181
+ logger.debug("[ConsentService] OAuth identity linked to User DID:", {
1151
1182
  provider: oauthIdentity.provider,
1152
1183
  subject: oauthIdentity.subject.substring(0, 20) + "...",
1153
1184
  userDid: userDid.substring(0, 20) + "...",
1154
1185
  });
1155
1186
  }
1156
1187
  catch (error) {
1157
- console.error("[ConsentService] Failed to store OAuth mapping:", error);
1188
+ logger.error("[ConsentService] Failed to store OAuth mapping:", error);
1158
1189
  // Non-fatal - continue with User DID
1159
1190
  }
1160
1191
  return userDid;
@@ -1172,7 +1203,7 @@ export class ConsentService {
1172
1203
  */
1173
1204
  async cacheExternalUserDid(oauthIdentity, userDid) {
1174
1205
  if (!this.env.DELEGATION_STORAGE) {
1175
- console.warn("[ConsentService] No storage available for caching external User DID");
1206
+ logger.warn("[ConsentService] No storage available for caching external User DID");
1176
1207
  return;
1177
1208
  }
1178
1209
  const oauthKey = STORAGE_KEYS.oauthIdentity(oauthIdentity.provider, oauthIdentity.subject);
@@ -1182,7 +1213,7 @@ export class ConsentService {
1182
1213
  if (existingUserDid) {
1183
1214
  // Mapping already exists - verify it matches
1184
1215
  if (existingUserDid !== userDid) {
1185
- console.warn("[ConsentService] OAuth identity already mapped to different User DID:", {
1216
+ logger.warn("[ConsentService] OAuth identity already mapped to different User DID:", {
1186
1217
  provider: oauthIdentity.provider,
1187
1218
  subject: oauthIdentity.subject.substring(0, 20) + "...",
1188
1219
  existingUserDid: existingUserDid.substring(0, 30) + "...",
@@ -1194,7 +1225,7 @@ export class ConsentService {
1194
1225
  }
1195
1226
  }
1196
1227
  catch (error) {
1197
- console.warn("[ConsentService] Failed to check existing OAuth mapping:", error);
1228
+ logger.warn("[ConsentService] Failed to check existing OAuth mapping:", error);
1198
1229
  // Continue to store new mapping
1199
1230
  }
1200
1231
  // Store OAuth identity → userDid mapping (persistent - 90 days)
@@ -1207,7 +1238,7 @@ export class ConsentService {
1207
1238
  await this.env.DELEGATION_STORAGE.put(oauthIdentityKey, JSON.stringify(oauthIdentity), {
1208
1239
  expirationTtl: 90 * 24 * 60 * 60, // 90 days
1209
1240
  });
1210
- console.error("[ConsentService] Cached external User DID from AgentShield:", {
1241
+ logger.debug("[ConsentService] Cached external User DID from AgentShield:", {
1211
1242
  provider: oauthIdentity.provider,
1212
1243
  subject: oauthIdentity.subject.substring(0, 20) + "...",
1213
1244
  userDid: userDid.substring(0, 30) + "...",
@@ -1215,7 +1246,7 @@ export class ConsentService {
1215
1246
  });
1216
1247
  }
1217
1248
  catch (error) {
1218
- console.error("[ConsentService] Failed to cache external User DID:", error);
1249
+ logger.debug("[ConsentService] Failed to cache external User DID:", error);
1219
1250
  // Non-fatal - the persistent user_did will still be used
1220
1251
  }
1221
1252
  }
@@ -1301,6 +1332,21 @@ export class ConsentService {
1301
1332
  // ✅ Extract agent_name from URL query param (passed from buildConsentUrl)
1302
1333
  // Human-readable name for AgentShield dashboard display
1303
1334
  const agentName = params.get("agent_name");
1335
+ // ✅ Extract credential auth params for 3-screen flow (Auth → Clickwrap → Success)
1336
+ // These are set when credential auth completes and redirects to clickwrap page
1337
+ // They ensure the delegation is created with 'password' type instead of 'none'
1338
+ const credentialProviderType = params.get("credential_provider_type");
1339
+ const credentialProvider = params.get("credential_provider");
1340
+ // ✅ Extract mode param for post-credential clickwrap detection
1341
+ // When credential auth completes, user is redirected to /consent?mode=consent-only&credential_provider_type=password
1342
+ const mode = params.get("mode");
1343
+ // ✅ LOOP FIX: Detect post-credential clickwrap state to prevent re-rendering credential form
1344
+ // Both conditions must be true to identify post-credential clickwrap:
1345
+ // 1. mode === "consent-only" (indicates we're past auth phase)
1346
+ // 2. credential_provider_type === "password" (confirms this was a credential auth flow)
1347
+ // IMPORTANT: credential_provider_type is a clickwrap-only signal. It is only set by the
1348
+ // credential-auth redirect to clickwrap; it is NOT used for pure consent-only or oauth flows.
1349
+ const isPostCredentialClickwrap = mode === "consent-only" && credentialProviderType === "password";
1304
1350
  // Validate required parameters
1305
1351
  if (!tool || !agentDid || !sessionId || !projectId) {
1306
1352
  return new Response(JSON.stringify({
@@ -1372,13 +1418,13 @@ export class ConsentService {
1372
1418
  }
1373
1419
  }
1374
1420
  catch (parseError) {
1375
- console.warn("[ConsentService] Invalid OAuth cookie format:", parseError);
1421
+ logger.warn("[ConsentService] Invalid OAuth cookie format:", parseError);
1376
1422
  }
1377
1423
  }
1378
1424
  }
1379
1425
  }
1380
1426
  catch (error) {
1381
- console.warn("[ConsentService] Failed to extract OAuth cookie:", error);
1427
+ logger.warn("[ConsentService] Failed to extract OAuth cookie:", error);
1382
1428
  // Non-fatal - continue without OAuth identity
1383
1429
  }
1384
1430
  // Check if OAuth is required (after extracting OAuth identity)
@@ -1400,7 +1446,7 @@ export class ConsentService {
1400
1446
  // This is the most explicit - passed from buildConsentUrl when tool has oauthProvider configured
1401
1447
  if (urlProvider) {
1402
1448
  provider = urlProvider;
1403
- console.error("[ConsentService] Using provider from URL query param:", {
1449
+ logger.debug("[ConsentService] Using provider from URL query param:", {
1404
1450
  provider,
1405
1451
  projectId,
1406
1452
  tool,
@@ -1417,7 +1463,7 @@ export class ConsentService {
1417
1463
  if (protection) {
1418
1464
  provider = await this.providerResolver.resolveProvider(protection, projectId);
1419
1465
  if (provider) {
1420
- console.error("[ConsentService] Using provider from resolver:", {
1466
+ logger.debug("[ConsentService] Using provider from resolver:", {
1421
1467
  provider,
1422
1468
  projectId,
1423
1469
  tool,
@@ -1428,13 +1474,32 @@ export class ConsentService {
1428
1474
  }
1429
1475
  catch (error) {
1430
1476
  // Check if this is ConsentOnlyModeError - expected behavior, not an error
1431
- if (error instanceof Error && error.name === "ConsentOnlyModeError") {
1432
- console.error("[ConsentService] Tool is consent-only mode, no provider needed for consent page", { projectId, tool });
1477
+ // Use multiple detection methods to handle bundled code where class names may be mangled
1478
+ const isConsentOnlyError = error instanceof Error &&
1479
+ (error.name === "ConsentOnlyModeError" ||
1480
+ error.constructor?.name === "ConsentOnlyModeError");
1481
+ // Check for CredentialAuthModeError - expected behavior for password-based auth
1482
+ // Also check for 'provider' property as fallback detection
1483
+ const isCredentialAuthError = error instanceof Error &&
1484
+ (error.name === "CredentialAuthModeError" ||
1485
+ error.constructor?.name === "CredentialAuthModeError" ||
1486
+ // Fallback: check for provider property (unique to CredentialAuthModeError)
1487
+ ("provider" in error &&
1488
+ typeof error.provider === "string"));
1489
+ if (isConsentOnlyError) {
1490
+ logger.debug("[ConsentService] Tool is consent-only mode, no provider needed for consent page", { projectId, tool });
1433
1491
  // Continue without provider - consent-only mode just needs clickwrap
1434
1492
  }
1493
+ else if (isCredentialAuthError) {
1494
+ // CredentialAuthModeError is expected behavior for password-based auth
1495
+ // Extract provider from the error for credential form rendering
1496
+ const credError = error;
1497
+ provider = credError.provider;
1498
+ logger.debug("[ConsentService] Tool uses credential auth, setting provider for credential form", { projectId, tool, provider });
1499
+ }
1435
1500
  else {
1436
1501
  // Non-fatal - continue without provider info
1437
- console.warn("[ConsentService] Failed to resolve provider for consent page:", error);
1502
+ logger.warn("[ConsentService] Failed to resolve provider for consent page:", error);
1438
1503
  }
1439
1504
  }
1440
1505
  }
@@ -1442,7 +1507,7 @@ export class ConsentService {
1442
1507
  // This is a SEPARATE check (not else-if) to handle when providerResolver exists but returns undefined
1443
1508
  if (!provider && toolOAuthProvider) {
1444
1509
  provider = toolOAuthProvider;
1445
- console.error("[ConsentService] Using provider from tool protection (fallback):", {
1510
+ logger.debug("[ConsentService] Using provider from tool protection (fallback):", {
1446
1511
  provider,
1447
1512
  projectId,
1448
1513
  tool,
@@ -1450,10 +1515,29 @@ export class ConsentService {
1450
1515
  }
1451
1516
  let resolvedOAuthUrl;
1452
1517
  let isOAuthRequired = false;
1453
- // Skip OAuth flow for credentials provider - credentials uses form-based auth, not OAuth
1454
- const isCredentialsProvider = provider?.toLowerCase() === "credentials";
1518
+ // CONFIG-BASED CREDENTIAL DETECTION (replaces string matching)
1519
+ // Fetch credential provider config ONCE and reuse throughout the method
1520
+ // Only fetch when: provider exists AND we're not in post-credential clickwrap state
1521
+ // This avoids unnecessary network calls for pure consent-only tools and post-auth clickwrap
1522
+ let credentialProviderConfig = null;
1523
+ if (provider && projectId && !isPostCredentialClickwrap) {
1524
+ try {
1525
+ credentialProviderConfig = await this.getCredentialProviderConfig(projectId, provider);
1526
+ }
1527
+ catch (err) {
1528
+ // Non-fatal: log and continue - will fall back to OAuth flow
1529
+ logger.warn("[ConsentService] Failed to fetch credential provider config:", err);
1530
+ }
1531
+ }
1532
+ // Determine if this is a credentials provider based on config existence (not string matching)
1533
+ const isCredentialsProvider = !!credentialProviderConfig;
1455
1534
  if (isCredentialsProvider && oauthRequired) {
1456
- console.error("[ConsentService] Credentials provider detected - skipping OAuth flow, will render credential form", { provider, projectId, tool });
1535
+ logger.debug("[ConsentService] Credential provider detected via config - skipping OAuth flow, will render credential form", {
1536
+ provider,
1537
+ projectId,
1538
+ tool,
1539
+ providerType: credentialProviderConfig?.type,
1540
+ });
1457
1541
  }
1458
1542
  if (oauthRequired && !isCredentialsProvider) {
1459
1543
  // OAuth is required - redirect to OAuth provider instead of showing consent page
@@ -1468,7 +1552,7 @@ export class ConsentService {
1468
1552
  oauthSecurityService, agentName || undefined // Human-readable agent name for AgentShield dashboard
1469
1553
  );
1470
1554
  isOAuthRequired = true;
1471
- console.error("[ConsentService] 🔒 SECURITY EVENT: OAuth required, preparing consent page with redirect:", {
1555
+ logger.debug("[ConsentService] 🔒 SECURITY EVENT: OAuth required, preparing consent page with redirect:", {
1472
1556
  projectId,
1473
1557
  agentDid: agentDid.substring(0, 20) + "...",
1474
1558
  oauthUrl: resolvedOAuthUrl.substring(0, 100) + "...",
@@ -1492,7 +1576,7 @@ export class ConsentService {
1492
1576
  })
1493
1577
  .catch((err) => {
1494
1578
  // Structured error logging
1495
- console.error("[ConsentService] Audit logging failed", {
1579
+ logger.debug("[ConsentService] Audit logging failed", {
1496
1580
  eventType: "consent:page_viewed",
1497
1581
  sessionId,
1498
1582
  error: err instanceof Error ? err.message : String(err),
@@ -1515,10 +1599,12 @@ export class ConsentService {
1515
1599
  provider, // Phase 2: Include provider if resolved
1516
1600
  branding: consentConfig.branding,
1517
1601
  // ✅ Ensure terms.required has a default value (contracts requires boolean, not boolean | undefined)
1518
- terms: consentConfig.terms ? {
1519
- ...consentConfig.terms,
1520
- required: consentConfig.terms.required ?? true,
1521
- } : undefined,
1602
+ terms: consentConfig.terms
1603
+ ? {
1604
+ ...consentConfig.terms,
1605
+ required: consentConfig.terms.required ?? true,
1606
+ }
1607
+ : undefined,
1522
1608
  customFields: consentConfig.customFields,
1523
1609
  autoClose: consentConfig.ui?.autoClose ?? false,
1524
1610
  // ✅ FIX: Pass full UI config (title, description, button text, etc.)
@@ -1530,35 +1616,34 @@ export class ConsentService {
1530
1616
  // Pass OAuth details for client-side handling
1531
1617
  oauthRequired: isOAuthRequired,
1532
1618
  oauthUrl: resolvedOAuthUrl,
1619
+ // ✅ Pass credential auth params for 3-screen flow (Auth → Clickwrap → Success)
1620
+ // These are set when user is redirected from credential auth page to clickwrap
1621
+ // They ensure the delegation is created with 'password' type instead of 'none'
1622
+ credentialProviderType: credentialProviderType || undefined,
1623
+ credentialProvider: credentialProvider || undefined,
1533
1624
  };
1534
- // CRED-003: Check if this is a credential provider and render credential form
1535
- if (provider && projectId) {
1536
- try {
1537
- const credentialProviderConfig = await this.getCredentialProviderConfig(projectId, provider);
1538
- if (credentialProviderConfig) {
1539
- console.error("[ConsentService] Credential provider detected, rendering credential page", {
1540
- projectId,
1541
- provider,
1542
- providerType: credentialProviderConfig.type,
1543
- displayName: credentialProviderConfig.displayName,
1544
- });
1545
- // Generate and store CSRF token for form security
1546
- const csrfToken = await this.storeCredentialCsrfToken(sessionId);
1547
- // Render credential login page instead of OAuth consent
1548
- const html = this.renderer.renderCredentialPage(pageConfig, credentialProviderConfig, provider, csrfToken);
1549
- return new Response(html, {
1550
- status: 200,
1551
- headers: {
1552
- "Content-Type": "text/html; charset=utf-8",
1553
- "Cache-Control": "no-cache, no-store, must-revalidate",
1554
- },
1555
- });
1556
- }
1557
- }
1558
- catch (credError) {
1559
- // Non-fatal: If credential provider check fails, fall through to OAuth
1560
- console.warn("[ConsentService] Credential provider check failed, falling back to OAuth:", credError);
1561
- }
1625
+ // CRED-003: Render credential form if this is a credential provider
1626
+ // Guard conditions:
1627
+ // 1. credentialProviderConfig must exist (already fetched above)
1628
+ // 2. Must NOT be in post-credential clickwrap mode (would cause infinite loop)
1629
+ if (credentialProviderConfig && !isPostCredentialClickwrap) {
1630
+ logger.debug("[ConsentService] Credential provider detected, rendering credential page", {
1631
+ projectId,
1632
+ provider,
1633
+ providerType: credentialProviderConfig.type,
1634
+ displayName: credentialProviderConfig.displayName,
1635
+ });
1636
+ // Generate and store CSRF token for form security
1637
+ const csrfToken = await this.storeCredentialCsrfToken(sessionId);
1638
+ // Render credential login page instead of OAuth consent
1639
+ const html = this.renderer.renderCredentialPage(pageConfig, credentialProviderConfig, provider, csrfToken);
1640
+ return new Response(html, {
1641
+ status: 200,
1642
+ headers: {
1643
+ "Content-Type": "text/html; charset=utf-8",
1644
+ "Cache-Control": "no-cache, no-store, must-revalidate",
1645
+ },
1646
+ });
1562
1647
  }
1563
1648
  // Standard OAuth flow: Render page with OAuth identity (if available)
1564
1649
  const html = this.renderer.render(pageConfig, oauthIdentity);
@@ -1571,7 +1656,7 @@ export class ConsentService {
1571
1656
  });
1572
1657
  }
1573
1658
  catch (error) {
1574
- console.error("[ConsentService] Error rendering consent page:", error);
1659
+ logger.error("[ConsentService] Error rendering consent page:", error);
1575
1660
  return new Response(JSON.stringify({
1576
1661
  success: false,
1577
1662
  error: "Failed to render consent page",
@@ -1809,7 +1894,7 @@ export class ConsentService {
1809
1894
  }
1810
1895
  catch (formDataError) {
1811
1896
  // FormData parsing failed, try URL-encoded text parsing
1812
- console.warn("[ConsentService] FormData parsing failed, trying URL-encoded text:", formDataError);
1897
+ logger.warn("[ConsentService] FormData parsing failed, trying URL-encoded text:", formDataError);
1813
1898
  }
1814
1899
  // Try URL-encoded text parsing as fallback
1815
1900
  try {
@@ -1820,7 +1905,7 @@ export class ConsentService {
1820
1905
  }
1821
1906
  catch (urlEncodedError) {
1822
1907
  // Both failed, fall through to JSON parsing
1823
- console.warn("[ConsentService] URL-encoded parsing also failed:", urlEncodedError);
1908
+ logger.warn("[ConsentService] URL-encoded parsing also failed:", urlEncodedError);
1824
1909
  }
1825
1910
  }
1826
1911
  // Parse multipart FormData (multipart/form-data or when FormData object is passed with other Content-Type)
@@ -2148,7 +2233,7 @@ export class ConsentService {
2148
2233
  }
2149
2234
  }
2150
2235
  catch (formDataError) {
2151
- console.warn("[ConsentService] FormData parsing failed:", formDataError);
2236
+ logger.warn("[ConsentService] FormData parsing failed:", formDataError);
2152
2237
  // Fall through to JSON parsing
2153
2238
  }
2154
2239
  }
@@ -2665,58 +2750,115 @@ export class ConsentService {
2665
2750
  * @returns JSON response
2666
2751
  */
2667
2752
  async handleApproval(request) {
2668
- console.error("[ConsentService] Approval request received");
2753
+ logger.debug("[ConsentService] Approval request received");
2669
2754
  try {
2670
2755
  // Parse and validate request body (supports both JSON and FormData)
2671
2756
  const body = await this.parseRequestBody(request);
2672
- console.error("[ConsentService] Request body parsed:", {
2757
+ logger.debug("[ConsentService] Request body parsed:", {
2673
2758
  hasBody: !!body,
2674
2759
  bodyKeys: Object.keys(body || {}),
2675
2760
  hasOAuthIdentity: !!body?.oauth_identity,
2676
2761
  });
2677
2762
  // Handle provider_type routing:
2678
- // - 'credential': User authenticated via credential form (email/password)
2763
+ // - 'credential' or 'password': User authenticated via credential form (email/password)
2679
2764
  // - 'oauth2': User authenticated via OAuth provider (handled below)
2680
2765
  // - 'none': Consent-only mode (clickwrap) - user agrees without authentication
2681
2766
  const bodyObj = body;
2682
2767
  const providerType = bodyObj?.provider_type;
2683
2768
  // CRED-003: Check for credential provider submission
2684
- // Credential submissions include `provider_type: 'credential'` and are handled separately
2685
- if (providerType === CONSENT_PROVIDER_TYPES.CREDENTIAL) {
2686
- console.error("[ConsentService] Credential submission detected");
2769
+ // Credential submissions include `provider_type: 'credential'` or 'password' and are handled separately
2770
+ // IMPORTANT: AgentShield tool protection uses 'password' for credential-based auth validation,
2771
+ // but we also accept 'credential' for backward compatibility
2772
+ if (providerType === CONSENT_PROVIDER_TYPES.CREDENTIAL ||
2773
+ providerType === CONSENT_PROVIDER_TYPES.PASSWORD) {
2774
+ logger.debug("[ConsentService] Credential submission detected", {
2775
+ provider_type: providerType,
2776
+ });
2687
2777
  return this.handleCredentialApproval(bodyObj);
2688
2778
  }
2689
2779
  // ✅ Consent-only mode (provider_type: 'none')
2690
- // User consents without authentication - clickwrap only
2691
- // Generate an ephemeral userDid to enable reliable delegation storage & lookup
2780
+ // This can be:
2781
+ // 1. Pure consent-only: User consents without authentication (clickwrap only)
2782
+ // 2. Post-credential clickwrap: User already authenticated via credentials, this is the clickwrap step
2783
+ // 3. Post-OAuth clickwrap: User already authenticated via OAuth, this is the clickwrap step
2692
2784
  if (providerType === CONSENT_PROVIDER_TYPES.NONE) {
2693
- console.error("[ConsentService] Consent-only mode detected (clickwrap)");
2694
- // Extract session_id for ephemeral userDid generation
2695
- const sessionId = body
2696
- .session_id;
2697
- if (sessionId) {
2698
- // Generate ephemeral userDid for this consent-only session
2699
- // This enables PRIORITY 1 delegation key (user+agent scoped) for reliable lookup
2700
- const ephemeralUserDid = await this.generateEphemeralUserDidForSession(sessionId);
2701
- if (ephemeralUserDid) {
2702
- // Store ephemeral userDid in session cache
2703
- // This ensures storeDelegationToken can find it and use PRIORITY 1 key
2704
- await this.updateSessionWithIdentity(sessionId, ephemeralUserDid, null // No OAuth identity for consent-only
2705
- );
2706
- // Also inject the user_did into the request body so createDelegation receives it
2707
- body.user_did = ephemeralUserDid;
2708
- console.error("[ConsentService] Ephemeral userDid stored in session for consent-only flow:", {
2709
- sessionId: sessionId.substring(0, 20) + "...",
2710
- userDid: ephemeralUserDid.substring(0, 30) + "...",
2711
- note: "Enables reliable delegation lookup via PRIORITY 1 key",
2712
- });
2713
- }
2714
- else {
2715
- console.warn("[ConsentService] ⚠️ Failed to generate ephemeral userDid - delegation will use session-scoped storage only");
2785
+ const bodyObj = body;
2786
+ const sessionId = bodyObj.session_id;
2787
+ // Check for credential auth parameters passed from handleCredentialApproval
2788
+ // These indicate this is the clickwrap step AFTER credential authentication
2789
+ const credentialProviderType = bodyObj.credential_provider_type;
2790
+ const credentialProvider = bodyObj.credential_provider;
2791
+ if (credentialProviderType &&
2792
+ credentialProviderType === CONSENT_PROVIDER_TYPES.PASSWORD) {
2793
+ // This is the clickwrap step after credential auth
2794
+ // The session already has userDid from credential auth
2795
+ logger.debug("[ConsentService] Consent-only mode (post-credential clickwrap)");
2796
+ // Override provider_type to 'password' so delegation is created with correct authorization
2797
+ // This ensures authorization.type matches tool protection expectation
2798
+ bodyObj.provider_type = CONSENT_PROVIDER_TYPES.PASSWORD;
2799
+ if (credentialProvider) {
2800
+ bodyObj.customFields = {
2801
+ ...(bodyObj.customFields || {}),
2802
+ provider: credentialProvider,
2803
+ provider_type: CONSENT_PROVIDER_TYPES.PASSWORD,
2804
+ };
2716
2805
  }
2806
+ logger.debug("[ConsentService] ✅ Using credential auth provider_type for delegation:", {
2807
+ sessionId: sessionId?.substring(0, 20) + "...",
2808
+ providerType: CONSENT_PROVIDER_TYPES.PASSWORD,
2809
+ provider: credentialProvider,
2810
+ note: "Delegation will have authorization.type='password' to match tool protection",
2811
+ });
2812
+ // The userDid should already be in the session from credential auth
2813
+ // We don't need to generate ephemeral one
2717
2814
  }
2718
2815
  else {
2719
- console.warn("[ConsentService] ⚠️ No session_id for consent-only flow - delegation will use session-scoped storage only");
2816
+ // Pure consent-only mode - no prior authentication
2817
+ logger.debug("[ConsentService] Consent-only mode detected (pure clickwrap)");
2818
+ if (sessionId && this.env.DELEGATION_STORAGE) {
2819
+ // Check if session already has userDid (from credential auth or OAuth)
2820
+ let existingUserDid;
2821
+ try {
2822
+ const sessionKey = STORAGE_KEYS.session(sessionId);
2823
+ const existingSession = (await this.env.DELEGATION_STORAGE.get(sessionKey, "json"));
2824
+ existingUserDid = existingSession?.userDid;
2825
+ }
2826
+ catch (error) {
2827
+ logger.warn("[ConsentService] Failed to read session for userDid:", error);
2828
+ }
2829
+ if (existingUserDid) {
2830
+ // Session has userDid from prior auth step - use it
2831
+ logger.debug("[ConsentService] Session already has userDid, reusing:", {
2832
+ sessionId: sessionId.substring(0, 20) + "...",
2833
+ userDid: existingUserDid.substring(0, 30) + "...",
2834
+ });
2835
+ bodyObj.user_did = existingUserDid;
2836
+ }
2837
+ else {
2838
+ // Generate ephemeral userDid for pure consent-only
2839
+ // This enables PRIORITY 1 delegation key (user+agent scoped) for reliable lookup
2840
+ const ephemeralUserDid = await this.generateEphemeralUserDidForSession(sessionId);
2841
+ if (ephemeralUserDid) {
2842
+ // Store ephemeral userDid in session cache
2843
+ // This ensures storeDelegationToken can find it and use PRIORITY 1 key
2844
+ await this.updateSessionWithIdentity(sessionId, ephemeralUserDid, null // No OAuth identity for consent-only
2845
+ );
2846
+ // Also inject the user_did into the request body so createDelegation receives it
2847
+ bodyObj.user_did = ephemeralUserDid;
2848
+ logger.debug("[ConsentService] ✅ Ephemeral userDid stored in session for consent-only flow:", {
2849
+ sessionId: sessionId.substring(0, 20) + "...",
2850
+ userDid: ephemeralUserDid.substring(0, 30) + "...",
2851
+ note: "Enables reliable delegation lookup via PRIORITY 1 key",
2852
+ });
2853
+ }
2854
+ else {
2855
+ logger.warn("[ConsentService] ⚠️ Failed to generate ephemeral userDid - delegation will use session-scoped storage only");
2856
+ }
2857
+ }
2858
+ }
2859
+ else {
2860
+ logger.warn("[ConsentService] ⚠️ No session_id for consent-only flow - delegation will use session-scoped storage only");
2861
+ }
2720
2862
  }
2721
2863
  }
2722
2864
  // Convert null oauth_identity to undefined for proper schema validation
@@ -2733,7 +2875,7 @@ export class ConsentService {
2733
2875
  }
2734
2876
  const validation = validateConsentApprovalRequest(body);
2735
2877
  if (!validation.success) {
2736
- console.error("[ConsentService] Approval request validation failed:", {
2878
+ logger.error("[ConsentService] Approval request validation failed:", {
2737
2879
  errors: validation.error.errors,
2738
2880
  receivedBody: body,
2739
2881
  });
@@ -2748,7 +2890,7 @@ export class ConsentService {
2748
2890
  });
2749
2891
  }
2750
2892
  const approvalRequest = validation.data;
2751
- console.error("[ConsentService] Approval request validated:", {
2893
+ logger.debug("[ConsentService] Approval request validated:", {
2752
2894
  agentDid: approvalRequest.agent_did?.substring(0, 20) + "...",
2753
2895
  sessionId: approvalRequest.session_id?.substring(0, 20) + "...",
2754
2896
  scopes: approvalRequest.scopes,
@@ -2788,7 +2930,7 @@ export class ConsentService {
2788
2930
  oauthProvider: approvalRequest.oauth_identity?.provider,
2789
2931
  })
2790
2932
  .catch((err) => {
2791
- console.error("[ConsentService] Failed to log credential required", {
2933
+ logger.debug("[ConsentService] Failed to log credential required", {
2792
2934
  eventType: "consent:credential_required",
2793
2935
  sessionId: approvalRequest.session_id,
2794
2936
  error: err instanceof Error ? err.message : String(err),
@@ -2798,10 +2940,10 @@ export class ConsentService {
2798
2940
  // The credential_required event is just for audit tracking
2799
2941
  }
2800
2942
  // Create delegation via AgentShield API
2801
- console.error("[ConsentService] Creating delegation...");
2943
+ logger.debug("[ConsentService] Creating delegation...");
2802
2944
  const delegationResult = await this.createDelegation(approvalRequest);
2803
2945
  if (!delegationResult.success) {
2804
- console.error("[ConsentService] Delegation creation failed:", {
2946
+ logger.error("[ConsentService] Delegation creation failed:", {
2805
2947
  error: delegationResult.error,
2806
2948
  error_code: delegationResult.error_code,
2807
2949
  });
@@ -2814,7 +2956,7 @@ export class ConsentService {
2814
2956
  headers: { "Content-Type": "application/json" },
2815
2957
  });
2816
2958
  }
2817
- console.error("[ConsentService] ✅ Delegation created successfully:", {
2959
+ logger.info("[ConsentService] ✅ Delegation created successfully:", {
2818
2960
  delegationId: delegationResult.delegation_id?.substring(0, 20) + "...",
2819
2961
  });
2820
2962
  // Store delegation token in KV
@@ -2831,7 +2973,7 @@ export class ConsentService {
2831
2973
  (await this.getUserDidForSession(approvalRequest.session_id, approvalRequest.oauth_identity || undefined)) ?? undefined; // Phase 5: Convert null to undefined
2832
2974
  }
2833
2975
  catch (error) {
2834
- console.warn("[ConsentService] Failed to get userDid for audit logging:", error);
2976
+ logger.warn("[ConsentService] Failed to get userDid for audit logging:", error);
2835
2977
  // Continue without userDid - audit events can still be logged
2836
2978
  }
2837
2979
  }
@@ -2862,7 +3004,7 @@ export class ConsentService {
2862
3004
  });
2863
3005
  }
2864
3006
  catch (error) {
2865
- console.error("[ConsentService] Audit failed but continuing", {
3007
+ logger.debug("[ConsentService] Audit failed but continuing", {
2866
3008
  sessionId: approvalRequest.session_id,
2867
3009
  error: error instanceof Error ? error.message : String(error),
2868
3010
  eventTypes: ["consent:approved", "consent:delegation_created"],
@@ -2881,7 +3023,7 @@ export class ConsentService {
2881
3023
  });
2882
3024
  }
2883
3025
  catch (error) {
2884
- console.error("[ConsentService] Error handling approval:", error);
3026
+ logger.error("[ConsentService] Error handling approval:", error);
2885
3027
  return new Response(JSON.stringify({
2886
3028
  success: false,
2887
3029
  error: "Internal server error",
@@ -2902,7 +3044,7 @@ export class ConsentService {
2902
3044
  const agentShieldUrl = this.env.AGENTSHIELD_API_URL || DEFAULT_AGENTSHIELD_URL;
2903
3045
  const apiKey = this.env.AGENTSHIELD_API_KEY;
2904
3046
  if (!apiKey) {
2905
- console.warn("[ConsentService] No API key configured, cannot create delegation");
3047
+ logger.warn("[ConsentService] No API key configured, cannot create delegation");
2906
3048
  return {
2907
3049
  success: false,
2908
3050
  error: "API key not configured",
@@ -2920,7 +3062,7 @@ export class ConsentService {
2920
3062
  // Only fetch from storage if not already provided in request
2921
3063
  if (!userDid && request.session_id) {
2922
3064
  try {
2923
- console.error("[ConsentService] Getting User DID for session:", {
3065
+ logger.debug("[ConsentService] Getting User DID for session:", {
2924
3066
  sessionId: request.session_id.substring(0, 20) + "...",
2925
3067
  hasOAuthIdentity: !!request.oauth_identity,
2926
3068
  oauthProvider: request.oauth_identity?.provider,
@@ -2932,27 +3074,27 @@ export class ConsentService {
2932
3074
  userDid =
2933
3075
  (await this.getUserDidForSession(request.session_id, request.oauth_identity || undefined // Explicitly handle null as undefined
2934
3076
  )) ?? undefined;
2935
- console.error("[ConsentService] User DID retrieved from storage:", {
3077
+ logger.debug("[ConsentService] User DID retrieved from storage:", {
2936
3078
  userDid: userDid?.substring(0, 20) + "...",
2937
3079
  hasUserDid: !!userDid,
2938
3080
  });
2939
3081
  }
2940
3082
  catch (error) {
2941
- console.error("[ConsentService] Failed to get/generate userDid:", error);
3083
+ logger.debug("[ConsentService] Failed to get/generate userDid:", error);
2942
3084
  // Continue without userDid - delegation will work without user_identifier
2943
3085
  // This is valid for non-OAuth scenarios, but we should log this as a warning
2944
- console.warn("[ConsentService] Delegation will be created without user_identifier - this may affect user tracking");
3086
+ logger.warn("[ConsentService] Delegation will be created without user_identifier - this may affect user tracking");
2945
3087
  }
2946
3088
  }
2947
3089
  else if (userDid) {
2948
3090
  // userDid was provided in request (e.g., from credential auth flow)
2949
- console.error("[ConsentService] Using provided user_did from request:", {
3091
+ logger.debug("[ConsentService] Using provided user_did from request:", {
2950
3092
  userDid: userDid.substring(0, 20) + "...",
2951
3093
  source: "request.user_did",
2952
3094
  });
2953
3095
  }
2954
3096
  else {
2955
- console.error("[ConsentService] No session_id provided - skipping User DID generation");
3097
+ logger.debug("[ConsentService] No session_id provided - skipping User DID generation");
2956
3098
  }
2957
3099
  const expiresInDays = 7; // Default to 7 days
2958
3100
  // Phase 2 VC-Only: Issue Delegation VC if we have a session and userDid
@@ -2983,21 +3125,21 @@ export class ConsentService {
2983
3125
  const vcResult = await this.issueDelegationVC(localDelegation, request.session_id, request.oauth_identity || undefined);
2984
3126
  credentialJwt = vcResult ?? undefined;
2985
3127
  if (credentialJwt) {
2986
- console.error("[ConsentService] VC issued for delegation:", {
3128
+ logger.debug("[ConsentService] VC issued for delegation:", {
2987
3129
  delegationId,
2988
3130
  jwtLength: credentialJwt.length,
2989
3131
  });
2990
3132
  }
2991
3133
  }
2992
3134
  catch (error) {
2993
- console.warn("[ConsentService] Failed to issue VC, continuing without it:", error);
3135
+ logger.warn("[ConsentService] Failed to issue VC, continuing without it:", error);
2994
3136
  // Non-fatal - delegation will work without VC
2995
3137
  }
2996
3138
  }
2997
3139
  // Build delegation request with error-based format detection
2998
3140
  // Try full format first, fallback to simplified format on error
2999
3141
  const delegationRequest = await this.buildDelegationRequest(request, userDid, expiresInDays, fieldName, credentialJwt);
3000
- console.error("[ConsentService] Creating delegation:", {
3142
+ logger.debug("[ConsentService] Creating delegation:", {
3001
3143
  url: `${agentShieldUrl}${AGENTSHIELD_ENDPOINTS.DELEGATIONS_CREATE}`,
3002
3144
  agentDid: request.agent_did.substring(0, 20) + "...",
3003
3145
  scopes: request.scopes,
@@ -3028,7 +3170,7 @@ export class ConsentService {
3028
3170
  // AgentShield now returns delegation_token for stateless verification
3029
3171
  const responseDataObj = wrappedResponse.data;
3030
3172
  const delegationToken = responseDataObj.delegation_token;
3031
- console.error("[ConsentService] ✅ Delegation created successfully:", {
3173
+ logger.info("[ConsentService] ✅ Delegation created successfully:", {
3032
3174
  delegationId,
3033
3175
  agentDid: wrappedResponse.data.agent_did.substring(0, 20) + "...",
3034
3176
  scopes: wrappedResponse.data.scopes,
@@ -3051,7 +3193,7 @@ export class ConsentService {
3051
3193
  // Extract delegation_token (JWT) if present in response
3052
3194
  const unwrappedDataObj = unwrappedResponse;
3053
3195
  const delegationToken = unwrappedDataObj.delegation_token;
3054
- console.error("[ConsentService] ✅ Delegation created successfully:", {
3196
+ logger.info("[ConsentService] ✅ Delegation created successfully:", {
3055
3197
  delegationId,
3056
3198
  agentDid: unwrappedResponse.agent_did.substring(0, 20) + "...",
3057
3199
  scopes: unwrappedResponse.scopes,
@@ -3074,7 +3216,7 @@ export class ConsentService {
3074
3216
  data?.id ||
3075
3217
  delegationObj?.id;
3076
3218
  if (!delegationId) {
3077
- console.error("[ConsentService] Invalid response format - missing delegation_id:", responseData);
3219
+ logger.debug("[ConsentService] Invalid response format - missing delegation_id:", responseData);
3078
3220
  return {
3079
3221
  success: false,
3080
3222
  error: "Invalid API response format - missing delegation_id",
@@ -3084,7 +3226,7 @@ export class ConsentService {
3084
3226
  // Extract delegation_token from fallback parsing
3085
3227
  const delegationToken = data?.delegation_token ||
3086
3228
  delegationObj?.delegation_token;
3087
- console.warn("[ConsentService] ⚠️ Response format not fully validated, using fallback parsing:", {
3229
+ logger.warn("[ConsentService] ⚠️ Response format not fully validated, using fallback parsing:", {
3088
3230
  delegationId,
3089
3231
  hasDelegationToken: !!delegationToken,
3090
3232
  tokenLength: delegationToken?.length,
@@ -3097,7 +3239,7 @@ export class ConsentService {
3097
3239
  };
3098
3240
  }
3099
3241
  catch (error) {
3100
- console.error("[ConsentService] Error creating delegation:", error);
3242
+ logger.error("[ConsentService] Error creating delegation:", error);
3101
3243
  return {
3102
3244
  success: false,
3103
3245
  error: error instanceof Error ? error.message : "Unknown error",
@@ -3118,7 +3260,7 @@ export class ConsentService {
3118
3260
  async storeDelegationToken(sessionId, agentDid, token, delegationId) {
3119
3261
  const delegationStorage = this.env.DELEGATION_STORAGE;
3120
3262
  if (!delegationStorage) {
3121
- console.warn("[ConsentService] No delegation storage configured, token not stored");
3263
+ logger.warn("[ConsentService] No delegation storage configured, token not stored");
3122
3264
  return;
3123
3265
  }
3124
3266
  try {
@@ -3137,7 +3279,7 @@ export class ConsentService {
3137
3279
  await delegationStorage.put(userAgentKey, token, {
3138
3280
  expirationTtl: ttl,
3139
3281
  });
3140
- console.error("[ConsentService] ✅ Token stored with user+agent DID:", {
3282
+ logger.info("[ConsentService] ✅ Token stored with user+agent DID:", {
3141
3283
  key: userAgentKey,
3142
3284
  ttl,
3143
3285
  delegationId,
@@ -3162,7 +3304,7 @@ export class ConsentService {
3162
3304
  await delegationStorage.put(sessionKey, JSON.stringify(sessionDataToStore), {
3163
3305
  expirationTtl: ttl, // Use full TTL - this is the primary storage for session
3164
3306
  });
3165
- console.error("[ConsentService] ✅ Token stored for session:", {
3307
+ logger.info("[ConsentService] ✅ Token stored for session:", {
3166
3308
  key: sessionKey,
3167
3309
  ttl,
3168
3310
  sessionId: sessionId.substring(0, 20) + "...",
@@ -3170,7 +3312,7 @@ export class ConsentService {
3170
3312
  preservedIdentityState: sessionData?.identityState || "none",
3171
3313
  });
3172
3314
  // Metrics: Log delegation key type for monitoring
3173
- console.error("[ConsentService] 📊 Delegation storage metrics:", {
3315
+ logger.debug("[ConsentService] 📊 Delegation storage metrics:", {
3174
3316
  delegationKeyType: userDid ? "user_agent_scoped" : "session_scoped",
3175
3317
  hasUserDid: !!userDid,
3176
3318
  userDidPrefix: userDid
@@ -3186,7 +3328,7 @@ export class ConsentService {
3186
3328
  }
3187
3329
  catch (error) {
3188
3330
  // Storage errors are non-fatal - log but don't fail the request
3189
- console.error("[ConsentService] Storage error (non-fatal):", error);
3331
+ logger.debug("[ConsentService] Storage error (non-fatal):", error);
3190
3332
  }
3191
3333
  }
3192
3334
  /**
@@ -3208,7 +3350,7 @@ export class ConsentService {
3208
3350
  }
3209
3351
  catch (error) {
3210
3352
  // Ignore errors, use default (autoClose = false)
3211
- console.warn("[ConsentService] Failed to fetch config for autoClose:", error);
3353
+ logger.warn("[ConsentService] Failed to fetch config for autoClose:", error);
3212
3354
  }
3213
3355
  }
3214
3356
  const html = this.renderer.renderSuccess({
@@ -3285,9 +3427,24 @@ export class ConsentService {
3285
3427
  * @returns JSON response
3286
3428
  */
3287
3429
  async handleCredentialApproval(body) {
3288
- console.error("[ConsentService] Processing credential approval");
3430
+ logger.debug("[ConsentService] Processing credential approval");
3289
3431
  // Extract standard fields
3290
3432
  const { tool, scopes: rawScopes, agent_did, session_id, project_id, provider, provider_type, csrf_token, ...credentials } = body;
3433
+ // DEBUG: Log credentials to diagnose password encoding issues
3434
+ // SECURITY: Mask password, but show length and first/last char for debugging
3435
+ const pwd = credentials.password || "";
3436
+ logger.debug("[ConsentService] DEBUG: Credential values received", {
3437
+ hasUsername: !!credentials.username,
3438
+ usernameLength: (credentials.username || "").length,
3439
+ usernameValue: credentials.username, // Safe to log email
3440
+ hasPassword: !!credentials.password,
3441
+ passwordLength: pwd.length,
3442
+ passwordFirstChar: pwd.length > 0 ? pwd[0] : "",
3443
+ passwordLastChar: pwd.length > 0 ? pwd[pwd.length - 1] : "",
3444
+ // Check for special chars that might be escaped
3445
+ passwordContainsDollar: pwd.includes("$"),
3446
+ passwordContainsDoubleD: pwd.includes("$$"),
3447
+ });
3291
3448
  // Parse scopes - handles double JSON encoding from form submission
3292
3449
  // The form stores scopes as JSON string, then JS submits it as JSON again
3293
3450
  const scopes = this.parseScopes(rawScopes);
@@ -3308,7 +3465,7 @@ export class ConsentService {
3308
3465
  }
3309
3466
  // Validate CSRF token
3310
3467
  if (!csrf_token || typeof csrf_token !== "string") {
3311
- console.warn("[ConsentService] Missing or invalid CSRF token");
3468
+ logger.warn("[ConsentService] Missing or invalid CSRF token");
3312
3469
  return new Response(JSON.stringify({
3313
3470
  success: false,
3314
3471
  error: "Invalid or missing CSRF token",
@@ -3318,7 +3475,7 @@ export class ConsentService {
3318
3475
  // Validate CSRF token against stored value
3319
3476
  const csrfValid = await this.validateCredentialCsrfToken(csrf_token, session_id);
3320
3477
  if (!csrfValid) {
3321
- console.warn("[ConsentService] CSRF token validation failed", {
3478
+ logger.warn("[ConsentService] CSRF token validation failed", {
3322
3479
  sessionId: session_id.substring(0, 20) + "...",
3323
3480
  });
3324
3481
  return new Response(JSON.stringify({
@@ -3331,7 +3488,7 @@ export class ConsentService {
3331
3488
  // 1. Fetch credential provider config from AgentShield
3332
3489
  const providerConfig = await this.getCredentialProviderConfig(project_id, provider);
3333
3490
  if (!providerConfig) {
3334
- console.error("[ConsentService] Credential provider config not found", {
3491
+ logger.debug("[ConsentService] Credential provider config not found", {
3335
3492
  projectId: project_id,
3336
3493
  provider,
3337
3494
  });
@@ -3347,20 +3504,37 @@ export class ConsentService {
3347
3504
  // See: https://developers.cloudflare.com/workers/observability/errors/#illegal-invocation-errors
3348
3505
  const credentialHandler = createCredentialAuthHandler({
3349
3506
  fetch: (...args) => globalThis.fetch(...args),
3350
- logger: (msg, data) => console.error(msg, data),
3507
+ logger: (msg, data) => logger.debug(msg, data),
3351
3508
  });
3352
3509
  const authResult = await credentialHandler.authenticate(providerConfig, credentials);
3353
3510
  if (!authResult.success) {
3354
- console.error("[ConsentService] Credential authentication failed", {
3511
+ logger.error("[ConsentService] Credential authentication failed", {
3355
3512
  error: authResult.error,
3356
3513
  });
3514
+ // Log credential auth failure for audit trail
3515
+ const auditService = await this.getAuditService(project_id);
3516
+ if (auditService) {
3517
+ await auditService
3518
+ .logCredentialAuthFailed({
3519
+ sessionId: session_id,
3520
+ agentDid: agent_did,
3521
+ targetTools: [tool],
3522
+ scopes: scopes,
3523
+ projectId: project_id,
3524
+ provider: provider,
3525
+ errorMessage: authResult.error,
3526
+ })
3527
+ .catch((err) => {
3528
+ logger.warn("[ConsentService] Failed to log credential auth failure:", err);
3529
+ });
3530
+ }
3357
3531
  return new Response(JSON.stringify({
3358
3532
  success: false,
3359
3533
  error: authResult.error || "Authentication failed",
3360
3534
  error_code: "auth_failed",
3361
3535
  }), { status: 401, headers: { "Content-Type": "application/json" } });
3362
3536
  }
3363
- console.error("[ConsentService] ✅ Credential authentication successful");
3537
+ logger.info("[ConsentService] ✅ Credential authentication successful");
3364
3538
  // 3. Resolve identity via AgentShield
3365
3539
  const identityResult = await this.resolveCredentialIdentity({
3366
3540
  projectId: project_id,
@@ -3376,15 +3550,32 @@ export class ConsentService {
3376
3550
  error_code: "identity_resolution_failed",
3377
3551
  }), { status: 500, headers: { "Content-Type": "application/json" } });
3378
3552
  }
3379
- console.error("[ConsentService] ✅ Identity resolved", {
3553
+ logger.info("[ConsentService] ✅ Identity resolved", {
3380
3554
  userDid: identityResult.userDid.substring(0, 30) + "...",
3381
3555
  });
3556
+ // Log credential auth success for audit trail (now that we have userDid)
3557
+ const auditService = await this.getAuditService(project_id);
3558
+ if (auditService) {
3559
+ await auditService
3560
+ .logCredentialAuthSuccess({
3561
+ sessionId: session_id,
3562
+ userDid: identityResult.userDid,
3563
+ agentDid: agent_did,
3564
+ targetTools: [tool],
3565
+ scopes: scopes,
3566
+ projectId: project_id,
3567
+ provider: provider,
3568
+ })
3569
+ .catch((err) => {
3570
+ logger.warn("[ConsentService] Failed to log credential auth success:", err);
3571
+ });
3572
+ }
3382
3573
  // NEW: Update session cache with userDid for proper delegation scoping
3383
3574
  // This ensures storeDelegationToken() can create user+agent scoped keys
3384
3575
  // instead of falling back to legacy agent-only keys
3385
3576
  await this.updateSessionWithIdentity(session_id, identityResult.userDid, null // No OAuth identity for credential auth
3386
3577
  );
3387
- console.error("[ConsentService] ✅ Session updated with identity");
3578
+ logger.info("[ConsentService] ✅ Session updated with identity");
3388
3579
  // 4. Store token in IdpTokenStorage with usage metadata
3389
3580
  // Include userId from authResult for ToolExecutionContext.userId
3390
3581
  await this.storeCredentialToken({
@@ -3396,48 +3587,59 @@ export class ConsentService {
3396
3587
  scopes,
3397
3588
  userId: authResult.userId, // Pass extracted userId from credential provider response
3398
3589
  });
3399
- console.error("[ConsentService] ✅ Token stored");
3400
- // 5. Create delegation using standard flow
3401
- // Include provider_type and provider in customFields for AgentShield dashboard display
3402
- const approvalRequest = {
3403
- tool: tool,
3404
- scopes,
3405
- agent_did: agent_did,
3406
- session_id: session_id,
3407
- project_id: project_id,
3408
- auth_mode: "credentials",
3409
- provider_type: CONSENT_PROVIDER_TYPES.CREDENTIAL,
3410
- termsAccepted: true,
3411
- user_did: identityResult.userDid,
3412
- customFields: {
3413
- provider: provider,
3414
- },
3415
- };
3416
- const delegationResult = await this.createDelegation(approvalRequest);
3417
- if (!delegationResult.success) {
3418
- return new Response(JSON.stringify({
3419
- success: false,
3420
- error: delegationResult.error || "Delegation creation failed",
3421
- error_code: delegationResult.error_code || "delegation_failed",
3422
- }), { status: 500, headers: { "Content-Type": "application/json" } });
3590
+ logger.info("[ConsentService] ✅ Token stored");
3591
+ // ================================================================================
3592
+ // 5. REDIRECT TO CLICKWRAP PAGE (3-screen flow)
3593
+ // ================================================================================
3594
+ // Flow: Credential Auth → Clickwrap (consent-only UI) → Success
3595
+ //
3596
+ // Instead of creating the delegation here, redirect to the clickwrap page
3597
+ // where the user can see their identity and approve the permission request.
3598
+ // The clickwrap approval will then create the delegation with the stored
3599
+ // credential auth info.
3600
+ //
3601
+ // This matches the OAuth flow pattern for consistency.
3602
+ // ================================================================================
3603
+ const serverUrl = this.env.MCP_SERVER_URL || "";
3604
+ // Build clickwrap URL with all necessary parameters
3605
+ const clickwrapUrl = new URL(`${serverUrl}/consent`);
3606
+ // Mode is consent-only since credential auth is complete
3607
+ clickwrapUrl.searchParams.set("mode", "consent-only");
3608
+ // CRITICAL: Pass provider_type so delegation is created with 'password' not 'none'
3609
+ // This ensures authorization.type matches tool protection expectation
3610
+ clickwrapUrl.searchParams.set("credential_provider_type", CONSENT_PROVIDER_TYPES.PASSWORD);
3611
+ clickwrapUrl.searchParams.set("credential_provider", provider);
3612
+ // Preserve important state from credential flow
3613
+ clickwrapUrl.searchParams.set("project_id", project_id);
3614
+ clickwrapUrl.searchParams.set("agent_did", agent_did);
3615
+ clickwrapUrl.searchParams.set("session_id", session_id);
3616
+ // Include tool and scopes for display
3617
+ clickwrapUrl.searchParams.set("tool", tool);
3618
+ if (Array.isArray(scopes) && scopes.length > 0) {
3619
+ clickwrapUrl.searchParams.set("scopes", scopes.join(","));
3423
3620
  }
3424
- console.error("[ConsentService] Credential approval complete", {
3425
- delegationId: delegationResult.delegation_id?.substring(0, 20) + "...",
3621
+ // Include user info for display on clickwrap page
3622
+ if (authResult.userEmail) {
3623
+ clickwrapUrl.searchParams.set("credential_user_email", authResult.userEmail);
3624
+ }
3625
+ if (authResult.userId) {
3626
+ clickwrapUrl.searchParams.set("credential_user_id", authResult.userId);
3627
+ }
3628
+ logger.debug("[ConsentService] ✅ Credential auth complete, redirecting to clickwrap", {
3629
+ sessionId: session_id.substring(0, 20) + "...",
3630
+ userDid: identityResult.userDid.substring(0, 30) + "...",
3631
+ provider: provider,
3632
+ clickwrapUrl: clickwrapUrl.toString().substring(0, 100) + "...",
3426
3633
  });
3427
- // Store delegation token
3428
- await this.storeDelegationToken(session_id, agent_did, delegationResult.delegation_token, delegationResult.delegation_id);
3429
- // Return success with redirect URL
3430
- const serverUrl = this.env.MCP_SERVER_URL || "";
3431
- const redirectUrl = `${serverUrl}/consent/success?delegation_id=${encodeURIComponent(delegationResult.delegation_id)}&project_id=${encodeURIComponent(project_id)}`;
3634
+ // Return success with redirect to clickwrap page
3432
3635
  return new Response(JSON.stringify({
3433
3636
  success: true,
3434
- delegation_id: delegationResult.delegation_id,
3435
- delegation_token: delegationResult.delegation_token,
3436
- redirectUrl,
3637
+ redirectUrl: clickwrapUrl.toString(),
3638
+ // Note: delegation_id is NOT returned here - it will be created on clickwrap approval
3437
3639
  }), { status: 200, headers: { "Content-Type": "application/json" } });
3438
3640
  }
3439
3641
  catch (error) {
3440
- console.error("[ConsentService] Credential approval error:", error);
3642
+ logger.error("[ConsentService] Credential approval error:", error);
3441
3643
  return new Response(JSON.stringify({
3442
3644
  success: false,
3443
3645
  error: error instanceof Error ? error.message : "Internal error",
@@ -3469,7 +3671,7 @@ export class ConsentService {
3469
3671
  }
3470
3672
  }
3471
3673
  catch {
3472
- console.warn("[ConsentService] Failed to parse scopes JSON:", rawScopes);
3674
+ logger.warn("[ConsentService] Failed to parse scopes JSON:", rawScopes);
3473
3675
  }
3474
3676
  }
3475
3677
  // Single string scope - wrap in array
@@ -3491,7 +3693,7 @@ export class ConsentService {
3491
3693
  const agentShieldUrl = this.env.AGENTSHIELD_API_URL || DEFAULT_AGENTSHIELD_URL;
3492
3694
  const apiKey = this.env.AGENTSHIELD_API_KEY;
3493
3695
  if (!apiKey) {
3494
- console.warn("[ConsentService] No AgentShield API key configured");
3696
+ logger.warn("[ConsentService] No AgentShield API key configured");
3495
3697
  return null;
3496
3698
  }
3497
3699
  try {
@@ -3505,7 +3707,7 @@ export class ConsentService {
3505
3707
  },
3506
3708
  });
3507
3709
  if (!response.ok) {
3508
- console.warn("[ConsentService] Providers API returned error:", {
3710
+ logger.warn("[ConsentService] Providers API returned error:", {
3509
3711
  status: response.status,
3510
3712
  statusText: response.statusText,
3511
3713
  });
@@ -3515,7 +3717,7 @@ export class ConsentService {
3515
3717
  // { success: true, data: { providers: { ... }, configuredProvider: "..." } }
3516
3718
  const result = (await response.json());
3517
3719
  if (!result.success || !result.data?.providers) {
3518
- console.warn("[ConsentService] Invalid providers response:", {
3720
+ logger.warn("[ConsentService] Invalid providers response:", {
3519
3721
  hasSuccess: result.success,
3520
3722
  hasData: !!result.data,
3521
3723
  hasProviders: !!result.data?.providers,
@@ -3530,13 +3732,13 @@ export class ConsentService {
3530
3732
  // AgentShield API may return snake_case fields from database
3531
3733
  const provider = this.mapCredentialProviderFields(rawProvider, providerName);
3532
3734
  if (!provider) {
3533
- console.error("[ConsentService] Credential provider validation failed:", {
3735
+ logger.debug("[ConsentService] Credential provider validation failed:", {
3534
3736
  projectId,
3535
3737
  providerName,
3536
3738
  });
3537
3739
  return null;
3538
3740
  }
3539
- console.error("[ConsentService] Found credential provider:", {
3741
+ logger.debug("[ConsentService] Found credential provider:", {
3540
3742
  providerName,
3541
3743
  hasAuthEndpoint: !!provider.authEndpoint,
3542
3744
  hasResponseFields: !!provider.responseFields,
@@ -3547,7 +3749,7 @@ export class ConsentService {
3547
3749
  return null;
3548
3750
  }
3549
3751
  catch (error) {
3550
- console.error("[ConsentService] Failed to fetch provider config:", error);
3752
+ logger.error("[ConsentService] Failed to fetch provider config:", error);
3551
3753
  return null;
3552
3754
  }
3553
3755
  }
@@ -3619,7 +3821,7 @@ export class ConsentService {
3619
3821
  raw.auth_endpoint ??
3620
3822
  "");
3621
3823
  if (!authEndpoint) {
3622
- console.error("[ConsentService] Credential provider missing required authEndpoint", { providerName: providerName ?? "unknown" });
3824
+ logger.debug("[ConsentService] Credential provider missing required authEndpoint", { providerName: providerName ?? "unknown" });
3623
3825
  return null;
3624
3826
  }
3625
3827
  return {
@@ -3646,7 +3848,7 @@ export class ConsentService {
3646
3848
  const agentShieldUrl = this.env.AGENTSHIELD_API_URL || DEFAULT_AGENTSHIELD_URL;
3647
3849
  const apiKey = this.env.AGENTSHIELD_API_KEY;
3648
3850
  if (!apiKey) {
3649
- console.warn("[ConsentService] No AgentShield API key for identity resolution");
3851
+ logger.warn("[ConsentService] No AgentShield API key for identity resolution");
3650
3852
  return { success: false };
3651
3853
  }
3652
3854
  try {
@@ -3676,7 +3878,7 @@ export class ConsentService {
3676
3878
  };
3677
3879
  }
3678
3880
  catch (error) {
3679
- console.error("[ConsentService] Identity resolution failed:", error);
3881
+ logger.error("[ConsentService] Identity resolution failed:", error);
3680
3882
  return { success: false };
3681
3883
  }
3682
3884
  }
@@ -3686,7 +3888,7 @@ export class ConsentService {
3686
3888
  async storeCredentialToken(params) {
3687
3889
  const delegationStorage = this.env.DELEGATION_STORAGE;
3688
3890
  if (!delegationStorage) {
3689
- console.warn("[ConsentService] No DELEGATION_STORAGE for credential tokens");
3891
+ logger.warn("[ConsentService] No DELEGATION_STORAGE for credential tokens");
3690
3892
  return;
3691
3893
  }
3692
3894
  const oauthSecurityService = new OAuthSecurityService(delegationStorage, this.env.OAUTH_ENCRYPTION_SECRET);
@@ -3724,7 +3926,7 @@ export class ConsentService {
3724
3926
  async validateCredentialCsrfToken(token, sessionId) {
3725
3927
  const delegationStorage = this.env.DELEGATION_STORAGE;
3726
3928
  if (!delegationStorage) {
3727
- console.warn("[ConsentService] No DELEGATION_STORAGE for CSRF validation, skipping");
3929
+ logger.warn("[ConsentService] No DELEGATION_STORAGE for CSRF validation, skipping");
3728
3930
  // Return true to allow flow to continue (graceful degradation)
3729
3931
  // This matches OAuth behavior when storage is unavailable
3730
3932
  return true;
@@ -3733,7 +3935,7 @@ export class ConsentService {
3733
3935
  const csrfKey = STORAGE_KEYS.credentialCsrf(sessionId);
3734
3936
  const storedToken = await delegationStorage.get(csrfKey);
3735
3937
  if (!storedToken) {
3736
- console.warn("[ConsentService] No stored CSRF token found");
3938
+ logger.warn("[ConsentService] No stored CSRF token found");
3737
3939
  return false;
3738
3940
  }
3739
3941
  // Constant-time comparison to prevent timing attacks
@@ -3745,7 +3947,7 @@ export class ConsentService {
3745
3947
  return isValid;
3746
3948
  }
3747
3949
  catch (error) {
3748
- console.error("[ConsentService] CSRF validation error:", error);
3950
+ logger.error("[ConsentService] CSRF validation error:", error);
3749
3951
  return false;
3750
3952
  }
3751
3953
  }
@@ -3766,7 +3968,7 @@ export class ConsentService {
3766
3968
  .replace(/\//g, "_")
3767
3969
  .replace(/=/g, "");
3768
3970
  if (!delegationStorage) {
3769
- console.warn("[ConsentService] No DELEGATION_STORAGE for CSRF storage");
3971
+ logger.warn("[ConsentService] No DELEGATION_STORAGE for CSRF storage");
3770
3972
  // Return token anyway - form will submit but validation will skip
3771
3973
  return token;
3772
3974
  }
@@ -3774,10 +3976,10 @@ export class ConsentService {
3774
3976
  const csrfKey = STORAGE_KEYS.credentialCsrf(sessionId);
3775
3977
  // 10 minute TTL matches OAuth state TTL
3776
3978
  await delegationStorage.put(csrfKey, token, { expirationTtl: 600 });
3777
- console.error("[ConsentService] CSRF token stored for credential form");
3979
+ logger.debug("[ConsentService] CSRF token stored for credential form");
3778
3980
  }
3779
3981
  catch (error) {
3780
- console.error("[ConsentService] CSRF token storage error:", error);
3982
+ logger.error("[ConsentService] CSRF token storage error:", error);
3781
3983
  }
3782
3984
  return token;
3783
3985
  }
@@ -3864,26 +4066,40 @@ export class ConsentService {
3864
4066
  // user_identifier can be the same as user_did or a human-readable version
3865
4067
  // If we have a human-readable identifier from OAuth, use it; otherwise use DID
3866
4068
  simplifiedRequest.user_identifier = userDid;
3867
- console.error("[ConsentService] Including user_did in delegation request:", {
4069
+ logger.debug("[ConsentService] Including user_did in delegation request:", {
3868
4070
  user_did: userDid.substring(0, 20) + "...",
3869
4071
  });
3870
4072
  }
3871
4073
  else {
3872
- console.error("[ConsentService] No user_did (session is anonymous) - delegation will proceed without it");
4074
+ logger.debug("[ConsentService] No user_did (session is anonymous) - delegation will proceed without it");
3873
4075
  }
3874
4076
  // Phase 2 VC-Only: Include credential_jwt if available
3875
4077
  if (credentialJwt) {
3876
4078
  simplifiedRequest.credential_jwt = credentialJwt;
3877
- console.error("[ConsentService] Including credential_jwt in delegation request");
4079
+ logger.debug("[ConsentService] Including credential_jwt in delegation request");
3878
4080
  }
3879
4081
  // AgentShield API only accepts "custom_fields", not "metadata"
3880
4082
  // Always use "custom_fields" regardless of Day0 config
3881
4083
  // Include provider_type and provider for dashboard authorization display
4084
+ //
4085
+ // CRITICAL FIX: request.provider_type is at the TOP LEVEL of ConsentApprovalRequest,
4086
+ // NOT inside customFields. We need to read from both locations:
4087
+ // - request.provider_type (set by handleCredentialApproval, handleApproval, etc.)
4088
+ // - customFieldsFromRequest.provider (set in customFields for backward compat)
3882
4089
  const customFieldsFromRequest = request.customFields || {};
3883
- const hasProviderInfo = customFieldsFromRequest.provider_type || customFieldsFromRequest.provider;
4090
+ // FIX: Read provider_type from request root (where handleCredentialApproval sets it)
4091
+ // Fall back to customFields for backward compatibility
4092
+ const providerType = request.provider_type || customFieldsFromRequest.provider_type;
4093
+ const provider = customFieldsFromRequest.provider;
4094
+ const hasProviderInfo = providerType || provider;
3884
4095
  if (userDid || hasProviderInfo) {
3885
4096
  // Include issuer_did and subject_did in custom_fields when we have userDid
3886
4097
  // Also include provider_type and provider for AgentShield dashboard
4098
+ // CRITICAL: AgentShield derives authorization from metadata.provider_type:
4099
+ // - provider_type === 'password' → authorization.type = 'password' (credential auth)
4100
+ // - provider_type === 'none' → authorization.type = 'none' (consent-only)
4101
+ // - oauth_provider present → authorization.type = 'oauth'
4102
+ // NOTE: Tool protection expects 'password' for credential flows, NOT 'credential'
3887
4103
  simplifiedRequest.custom_fields = {
3888
4104
  ...(userDid
3889
4105
  ? {
@@ -3892,13 +4108,18 @@ export class ConsentService {
3892
4108
  }
3893
4109
  : {}),
3894
4110
  format_version: "simplified_v1",
3895
- // Merge with any existing custom_fields from request (includes provider_type, provider)
4111
+ // Include provider_type at the custom_fields level (where AgentShield reads it)
4112
+ ...(providerType ? { provider_type: providerType } : {}),
4113
+ // Merge with any existing custom_fields from request
3896
4114
  ...customFieldsFromRequest,
3897
4115
  };
3898
4116
  if (hasProviderInfo) {
3899
- console.error("[ConsentService] Including provider info in custom_fields:", {
3900
- provider_type: customFieldsFromRequest.provider_type,
3901
- provider: customFieldsFromRequest.provider,
4117
+ logger.debug("[ConsentService] Including provider info in custom_fields:", {
4118
+ provider_type: providerType,
4119
+ provider: provider,
4120
+ source: request.provider_type
4121
+ ? "request.provider_type"
4122
+ : "customFields",
3902
4123
  });
3903
4124
  }
3904
4125
  }
@@ -3929,7 +4150,7 @@ export class ConsentService {
3929
4150
  return fullResponse;
3930
4151
  }
3931
4152
  // Full format failed with validation error, try simplified
3932
- console.error("[ConsentService] Full format failed, trying simplified format...");
4153
+ logger.debug("[ConsentService] Full format failed, trying simplified format...");
3933
4154
  const simplifiedResponse = await this.makeAPICall(agentShieldUrl, apiKey, request.simplifiedFormat);
3934
4155
  if (simplifiedResponse.success) {
3935
4156
  await this.cacheFormatPreference("simplified");
@@ -3951,11 +4172,11 @@ export class ConsentService {
3951
4172
  // This provides defense-in-depth protection
3952
4173
  const sanitizedBody = { ...requestBody };
3953
4174
  if ("session_id" in sanitizedBody) {
3954
- console.warn("[ConsentService] ⚠️ session_id detected in request body - removing (not in schema)");
4175
+ logger.warn("[ConsentService] ⚠️ session_id detected in request body - removing (not in schema)");
3955
4176
  delete sanitizedBody.session_id;
3956
4177
  }
3957
4178
  if ("project_id" in sanitizedBody) {
3958
- console.warn("[ConsentService] ⚠️ project_id detected in request body - removing (not in schema)");
4179
+ logger.warn("[ConsentService] ⚠️ project_id detected in request body - removing (not in schema)");
3959
4180
  delete sanitizedBody.project_id;
3960
4181
  }
3961
4182
  const response = await fetch(`${agentShieldUrl}${AGENTSHIELD_ENDPOINTS.DELEGATIONS_CREATE}`, {
@@ -4009,7 +4230,7 @@ export class ConsentService {
4009
4230
  };
4010
4231
  }
4011
4232
  catch (error) {
4012
- console.error("[ConsentService] API call failed:", error);
4233
+ logger.error("[ConsentService] API call failed:", error);
4013
4234
  return {
4014
4235
  success: false,
4015
4236
  error: error instanceof Error ? error.message : "Network request failed",
@@ -4031,10 +4252,10 @@ export class ConsentService {
4031
4252
  }), {
4032
4253
  expirationTtl: 3600, // 1 hour
4033
4254
  });
4034
- console.error(`[ConsentService] Cached format preference: ${format}`);
4255
+ logger.debug(`[ConsentService] Cached format preference: ${format}`);
4035
4256
  }
4036
4257
  catch (error) {
4037
- console.warn("[ConsentService] Failed to cache format preference:", error);
4258
+ logger.warn("[ConsentService] Failed to cache format preference:", error);
4038
4259
  }
4039
4260
  }
4040
4261
  }