@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 +117 -6
- package/dist/index.js +35 -11
- package/dist/index.mjs +35 -11
- package/package.json +3 -3
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.
|
|
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. **
|
|
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/
|
|
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
|
|
334
|
-
var
|
|
333
|
+
var idTokenKeysCache = null;
|
|
334
|
+
var idTokenKeysCacheExpiry = 0;
|
|
335
|
+
var sessionKeysCache = null;
|
|
336
|
+
var sessionKeysCacheExpiry = 0;
|
|
335
337
|
async function fetchPublicKeys(issuer) {
|
|
336
|
-
|
|
337
|
-
|
|
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 (
|
|
341
|
-
return
|
|
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
|
-
|
|
348
|
-
|
|
349
|
-
|
|
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
|
-
|
|
425
|
-
|
|
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
|
|
102
|
-
var
|
|
101
|
+
var idTokenKeysCache = null;
|
|
102
|
+
var idTokenKeysCacheExpiry = 0;
|
|
103
|
+
var sessionKeysCache = null;
|
|
104
|
+
var sessionKeysCacheExpiry = 0;
|
|
103
105
|
async function fetchPublicKeys(issuer) {
|
|
104
|
-
|
|
105
|
-
|
|
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 (
|
|
109
|
-
return
|
|
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
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
-
|
|
193
|
-
|
|
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.
|
|
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
|
},
|