@prmichaelsen/firebase-admin-sdk-v8 2.4.0 → 2.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENT.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # Agent Context Protocol (ACP)
2
2
 
3
- **Also Known As**: The Agent Directory Pattern
4
- **Version**: 1.0.3
5
- **Created**: 2026-02-11
6
- **Status**: Production Pattern
3
+ **Also Known As**: The Agent Directory Pattern
4
+ **Version**: 1.4.3
5
+ **Created**: 2026-02-11
6
+ **Status**: Production Pattern
7
7
 
8
8
  ---
9
9
 
@@ -81,6 +81,14 @@ ACP solves these by:
81
81
  project-root/
82
82
  ├── AGENT.md # This file - ACP documentation
83
83
  ├── agent/ # Agent directory (ACP structure)
84
+ │ ├── commands/ # Command system
85
+ │ │ ├── .gitkeep
86
+ │ │ ├── command.template.md # Command template
87
+ │ │ ├── acp.init.md # @acp-init
88
+ │ │ ├── acp.proceed.md # @acp-proceed
89
+ │ │ ├── acp.status.md # @acp-status
90
+ │ │ └── ... # More commands
91
+ │ │
84
92
  │ ├── design/ # Design documents
85
93
  │ │ ├── .gitkeep
86
94
  │ │ ├── requirements.md # Core requirements
@@ -551,6 +559,91 @@ The Agent Pattern represents a **paradigm shift** in how we approach AI-assisted
551
559
 
552
560
  ---
553
561
 
562
+ ## ACP Commands
563
+
564
+ ACP supports a command system for common workflows. Commands are file-based triggers that provide standardized, discoverable interfaces for ACP operations.
565
+
566
+ ### What are ACP Commands?
567
+
568
+ Commands are markdown files in [`agent/commands/`](agent/commands/) that contain step-by-step instructions for AI agents. Instead of typing long prompts like "AGENT.md: Initialize", you can reference command files like `@acp.init` to trigger specific workflows.
569
+
570
+ **Benefits**:
571
+ - **Discoverable**: Browse [`agent/commands/`](agent/commands/) to see all available commands
572
+ - **Consistent**: All commands follow the same structure
573
+ - **Extensible**: Create custom commands for your project
574
+ - **Self-Documenting**: Each command file contains complete documentation
575
+ - **Autocomplete-Friendly**: Type `@acp.` to see all ACP commands
576
+
577
+ ### Core Commands
578
+
579
+ Core ACP commands use the `acp.` prefix and are available in [`agent/commands/`](agent/commands/):
580
+
581
+ - **[`@acp.init`](agent/commands/acp.init.md)** - Initialize agent context (replaces "AGENT.md: Initialize")
582
+ - **[`@acp.proceed`](agent/commands/acp.proceed.md)** - Continue with next task (replaces "AGENT.md: Proceed")
583
+ - **[`@acp.status`](agent/commands/acp.status.md)** - Display project status
584
+ - **[`@acp.version-check`](agent/commands/acp.version-check.md)** - Show current ACP version
585
+ - **[`@acp.version-check-for-updates`](agent/commands/acp.version-check-for-updates.md)** - Check for ACP updates
586
+ - **[`@acp.version-update`](agent/commands/acp.version-update.md)** - Update ACP to latest version
587
+
588
+ ### Command Invocation
589
+
590
+ Commands are invoked using the `@` syntax with dot notation:
591
+
592
+ ```
593
+ @acp.init → agent/commands/acp.init.md
594
+ @acp.proceed → agent/commands/acp.proceed.md
595
+ @acp.status → agent/commands/acp.status.md
596
+ @deploy.production → agent/commands/deploy.production.md
597
+ ```
598
+
599
+ **Format**: `@{namespace}.{action}` resolves to `agent/commands/{namespace}.{action}.md`
600
+
601
+ ### Creating Custom Commands
602
+
603
+ To create custom commands for your project:
604
+
605
+ 1. **Choose a namespace** (e.g., `deploy`, `test`, `custom`)
606
+ - ⚠️ The `acp` namespace is reserved for core commands
607
+ - Use descriptive, single-word namespaces
608
+
609
+ 2. **Copy the command template**:
610
+ ```bash
611
+ cp agent/commands/command.template.md agent/commands/{namespace}.{action}.md
612
+ ```
613
+
614
+ 3. **Fill in the template sections**:
615
+ - Purpose and description
616
+ - Prerequisites
617
+ - Step-by-step instructions
618
+ - Verification checklist
619
+ - Examples and troubleshooting
620
+
621
+ 4. **Invoke your command**: `@{namespace}.{action}`
622
+
623
+ **Example**: Creating a deployment command:
624
+ ```bash
625
+ # Create the command file
626
+ cp agent/commands/command.template.md agent/commands/deploy.production.md
627
+
628
+ # Edit the file with your deployment steps
629
+ # ...
630
+
631
+ # Invoke it
632
+ @deploy.production
633
+ ```
634
+
635
+ ### Command Template
636
+
637
+ See [`agent/commands/command.template.md`](agent/commands/command.template.md) for the complete command template with all sections and examples.
638
+
639
+ ### Installing Third-Party Commands
640
+
641
+ Use `@acp.install` to install command packages from git repositories (available in future release).
642
+
643
+ **Security Note**: Third-party commands can instruct agents to modify files and execute scripts. Always review command files before installation.
644
+
645
+ ---
646
+
554
647
  ## Sample Prompts for Using ACP
555
648
 
556
649
  ### Initialize Prompt
@@ -782,7 +875,17 @@ Run ./agent/scripts/uninstall.sh to remove all ACP files (agent/ directory and A
782
875
  - Update percentages
783
876
  - Add recent work notes
784
877
 
785
- 7. **NEVER handle secrets or sensitive data**
878
+ 7. **CRITICAL: Always update CHANGELOG.md for version changes**
879
+ - ❌ **DO NOT** commit version changes without updating CHANGELOG.md
880
+ - ❌ **DO NOT** forget to update version numbers in all project files
881
+ - ✅ **DO** use [`@git.commit`](agent/commands/git.commit.md) for version-aware commits
882
+ - ✅ **DO** detect version impact: major (breaking), minor (features), patch (fixes)
883
+ - ✅ **DO** update CHANGELOG.md with clear, user-focused descriptions
884
+ - ✅ **DO** update all version files (package.json, AGENT.md, etc.)
885
+ - ✅ **DO** use Conventional Commits format for commit messages
886
+ - **Rationale**: CHANGELOG.md is the primary communication tool for users. Every version change must be documented with clear descriptions of what changed, why it changed, and how it affects users. Forgetting to update CHANGELOG.md breaks the project's version history and makes it impossible for users to understand what changed between versions.
887
+
888
+ 8. **NEVER handle secrets or sensitive data**
786
889
  - ❌ **DO NOT** read `.env` files, `.env.local`, or any environment files
787
890
  - ❌ **DO NOT** read files containing API keys, tokens, passwords, or credentials
788
891
  - ❌ **DO NOT** include secrets in messages, documentation, or code examples
@@ -793,6 +896,14 @@ Run ./agent/scripts/uninstall.sh to remove all ACP files (agent/ directory and A
793
896
  - ✅ **DO** create `.env.example` files with placeholder values only
794
897
  - **Rationale**: Secrets must never be exposed in chat logs, documentation, or version control. Agents should treat all credential files as off-limits to prevent accidental exposure.
795
898
 
899
+ 9. **CRITICAL: Respect user's intentional file edits**
900
+ - ❌ **DO NOT** assume missing content needs to be added back
901
+ - ❌ **DO NOT** revert changes without confirming with user
902
+ - ✅ **DO** read files before editing to see current state
903
+ - ✅ **DO** ask user if unexpected changes were intentional
904
+ - ✅ **DO** confirm before reverting user's manual edits
905
+ - **Rationale**: If you read a file and it is missing contents or has changed contents (i.e., it does not contain what you expect), assume or confirm with the user if they made intentional updates that you should not revert. Do not assume "The file is missing <xyz>, I need to add it back". The user may have edited files manually with intention.
906
+
796
907
  ---
797
908
 
798
909
  ## Best Practices
@@ -882,7 +993,7 @@ This repository is actively maintained with improvements to the ACP methodology
882
993
  ./agent/scripts/update.sh
883
994
 
884
995
  # Or download and run directly
885
- curl -fsSL https://raw.githubusercontent.com/prmichaelsen/agent-context-protocol/mainlin./agent/scripts/update.sh | bash
996
+ curl -fsSL https://raw.githubusercontent.com/prmichaelsen/agent-context-protocol/mainline/agent/scripts/update.sh | bash
886
997
  ```
887
998
 
888
999
  The update script will:
package/dist/index.js CHANGED
@@ -330,23 +330,41 @@ async function importPublicKeyFromX509(pem) {
330
330
  }
331
331
 
332
332
  // src/auth.ts
333
- var publicKeysCache = null;
334
- var publicKeysCacheExpiry = 0;
333
+ var idTokenKeysCache = null;
334
+ var idTokenKeysCacheExpiry = 0;
335
+ var sessionKeysCache = null;
336
+ var sessionKeysCacheExpiry = 0;
335
337
  async function fetchPublicKeys(issuer) {
336
- let endpoint = "https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com";
337
- if (issuer && issuer.includes("session.firebase.google.com")) {
338
+ const isSessionCookie = issuer && issuer.includes("session.firebase.google.com");
339
+ let endpoint;
340
+ let cache;
341
+ let cacheExpiry;
342
+ if (isSessionCookie) {
338
343
  endpoint = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/publicKeys";
344
+ cache = sessionKeysCache;
345
+ cacheExpiry = sessionKeysCacheExpiry;
346
+ } else {
347
+ endpoint = "https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com";
348
+ cache = idTokenKeysCache;
349
+ cacheExpiry = idTokenKeysCacheExpiry;
339
350
  }
340
- if (publicKeysCache && Date.now() < publicKeysCacheExpiry) {
341
- return publicKeysCache;
351
+ if (cache && Date.now() < cacheExpiry) {
352
+ return cache;
342
353
  }
343
354
  const response = await fetch(endpoint);
344
355
  if (!response.ok) {
345
356
  throw new Error(`Failed to fetch Firebase public keys from ${endpoint}`);
346
357
  }
347
- publicKeysCache = await response.json();
348
- publicKeysCacheExpiry = Date.now() + 36e5;
349
- return publicKeysCache;
358
+ const keys = await response.json();
359
+ const newExpiry = Date.now() + 36e5;
360
+ if (isSessionCookie) {
361
+ sessionKeysCache = keys;
362
+ sessionKeysCacheExpiry = newExpiry;
363
+ } else {
364
+ idTokenKeysCache = keys;
365
+ idTokenKeysCacheExpiry = newExpiry;
366
+ }
367
+ return keys;
350
368
  }
351
369
  function base64UrlDecode(str) {
352
370
  let base64 = str.replace(/-/g, "+").replace(/_/g, "/");
@@ -421,8 +439,14 @@ async function verifyIdToken(idToken) {
421
439
  let publicKeys = await fetchPublicKeys(payload.iss);
422
440
  let publicKeyPem = publicKeys[header.kid];
423
441
  if (!publicKeyPem) {
424
- publicKeysCache = null;
425
- publicKeysCacheExpiry = 0;
442
+ const isSessionCookie = payload.iss && payload.iss.includes("session.firebase.google.com");
443
+ if (isSessionCookie) {
444
+ sessionKeysCache = null;
445
+ sessionKeysCacheExpiry = 0;
446
+ } else {
447
+ idTokenKeysCache = null;
448
+ idTokenKeysCacheExpiry = 0;
449
+ }
426
450
  publicKeys = await fetchPublicKeys(payload.iss);
427
451
  publicKeyPem = publicKeys[header.kid];
428
452
  if (!publicKeyPem) {
package/dist/index.mjs CHANGED
@@ -98,23 +98,41 @@ async function importPublicKeyFromX509(pem) {
98
98
  }
99
99
 
100
100
  // src/auth.ts
101
- var publicKeysCache = null;
102
- var publicKeysCacheExpiry = 0;
101
+ var idTokenKeysCache = null;
102
+ var idTokenKeysCacheExpiry = 0;
103
+ var sessionKeysCache = null;
104
+ var sessionKeysCacheExpiry = 0;
103
105
  async function fetchPublicKeys(issuer) {
104
- let endpoint = "https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com";
105
- if (issuer && issuer.includes("session.firebase.google.com")) {
106
+ const isSessionCookie = issuer && issuer.includes("session.firebase.google.com");
107
+ let endpoint;
108
+ let cache;
109
+ let cacheExpiry;
110
+ if (isSessionCookie) {
106
111
  endpoint = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/publicKeys";
112
+ cache = sessionKeysCache;
113
+ cacheExpiry = sessionKeysCacheExpiry;
114
+ } else {
115
+ endpoint = "https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com";
116
+ cache = idTokenKeysCache;
117
+ cacheExpiry = idTokenKeysCacheExpiry;
107
118
  }
108
- if (publicKeysCache && Date.now() < publicKeysCacheExpiry) {
109
- return publicKeysCache;
119
+ if (cache && Date.now() < cacheExpiry) {
120
+ return cache;
110
121
  }
111
122
  const response = await fetch(endpoint);
112
123
  if (!response.ok) {
113
124
  throw new Error(`Failed to fetch Firebase public keys from ${endpoint}`);
114
125
  }
115
- publicKeysCache = await response.json();
116
- publicKeysCacheExpiry = Date.now() + 36e5;
117
- return publicKeysCache;
126
+ const keys = await response.json();
127
+ const newExpiry = Date.now() + 36e5;
128
+ if (isSessionCookie) {
129
+ sessionKeysCache = keys;
130
+ sessionKeysCacheExpiry = newExpiry;
131
+ } else {
132
+ idTokenKeysCache = keys;
133
+ idTokenKeysCacheExpiry = newExpiry;
134
+ }
135
+ return keys;
118
136
  }
119
137
  function base64UrlDecode(str) {
120
138
  let base64 = str.replace(/-/g, "+").replace(/_/g, "/");
@@ -189,8 +207,14 @@ async function verifyIdToken(idToken) {
189
207
  let publicKeys = await fetchPublicKeys(payload.iss);
190
208
  let publicKeyPem = publicKeys[header.kid];
191
209
  if (!publicKeyPem) {
192
- publicKeysCache = null;
193
- publicKeysCacheExpiry = 0;
210
+ const isSessionCookie = payload.iss && payload.iss.includes("session.firebase.google.com");
211
+ if (isSessionCookie) {
212
+ sessionKeysCache = null;
213
+ sessionKeysCacheExpiry = 0;
214
+ } else {
215
+ idTokenKeysCache = null;
216
+ idTokenKeysCacheExpiry = 0;
217
+ }
194
218
  publicKeys = await fetchPublicKeys(payload.iss);
195
219
  publicKeyPem = publicKeys[header.kid];
196
220
  if (!publicKeyPem) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prmichaelsen/firebase-admin-sdk-v8",
3
- "version": "2.4.0",
3
+ "version": "2.4.2",
4
4
  "description": "Firebase Admin SDK for Cloudflare Workers and edge runtimes using REST APIs",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -26,8 +26,8 @@
26
26
  "typecheck": "tsc --noEmit",
27
27
  "test": "jest",
28
28
  "test:watch": "jest --watch",
29
- "test:e2e": "jest --config jest.e2e.config.js",
30
- "test:e2e:watch": "jest --config jest.e2e.config.js --watch",
29
+ "test:e2e": "node --env-file=.env node_modules/.bin/jest --config jest.e2e.config.js",
30
+ "test:e2e:watch": "node --env-file=.env node_modules/.bin/jest --config jest.e2e.config.js --watch",
31
31
  "test:all": "npm test && npm run test:e2e",
32
32
  "prepublishOnly": "npm run build"
33
33
  },