Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .antigravity-plugin/TESTING_INSTRUCTIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
The plugin is just dropped in a folder - so the easiest way is to symlink the working source from your app folder like so:

`ln -s ~/firebase/agent-skills/.antigravity-plugin ~/myappdirectory/.agents/plugins/firebase-antigravity-plugin`

Pre-flight checks:
- ensure you're not using corp - this prevents new project creation (you'll get a 401)
- `gcloud config set account christhompsonfirebase@gmail.com`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Avoid hardcoding personal email addresses in the testing instructions. Use a generic placeholder instead.

- Login for ADC (if you continue to get 401 ensure you check the boxes on login)
- `gcloud auth application-default login`

You'll need to accept Firebase TOS for the user you're using in gcloud.
69 changes: 69 additions & 0 deletions .antigravity-plugin/TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
- Update new Rules logic once chliang@ is done updating the firebase skill.
- Add a gcloud rules deploy (or agent tool for making the API call)
- Add a reference to scoring rules
- Write the gcloud deploy logic
- Figure out how to test this thing
- Write system instructions
- MCP server support
- TODO: Add MCP for deployment (currently using gcloud CLI for v0)
- Sidecar ideas needed https://antigravity.google/docs/sidecars
- How about a rules analyzer that runs antagonistically to the main model
- wait for cloud run deployment and reports success or failure to the main model
- "Sidecars can use the agentapi CLI to programmatically interact with Antigravity. The executable is automatically added to the sidecar’s path and available as agentapi."
- Allegedly there's a nodejs environment shipped with AG via electron
- Emulators? Interesting idea
- Hooks
- Check rules score before deploying rules?
- Does an MCP tool command work? The docs seem to suggest that only the AGY tools are matchable. Gemini says MCP tools work
- Validate hooking on MCP or just gcloud commands
- Metrics tracking - lots of opportunities here
- Subagents ? can we have a rules subagent?
- Alternative to side-car is the polling subagent that checks when (for example) cloud run deploy completes
- Model assumes node for npx create-vite - maybe we can't get away from Node for web apps.
- Curl requests are scary looking for the user to approve, need to wrap in gocloud
- initializing firebase - need a firebase init in the plugin or firebase.json template inside gocloud
- npx firebase apps:sdkconfig WEB --project com-example-noteapp-f9b56
Deployment environments:
- Plugin works in CLI + AG2.0 + AGYIDE
- Antigravity (Google’s AI coding tool powered by Gemini) as an assistant directly inside Claude Code

Gcloud commands to add:
- npx firebase apps:sdkconfig WEB --project com-example-noteapp-f9b56
- This is in response to printing the configData base64 object in the provisioning response.
- Create app provisioning API
- Encapsulates the cURL command, can poll for operation completion, return firebaseconfig object
- Create database after the fact is necessary? Can provisioning API do it? likely
- 1:1 DB model? in which case no need provisioning API
- `gcloud firestore databases create --project=com-example-noteapp-f9b56 --location=us-central1 --type=firestore-native --edition=enterprise --enable-firestore-data-access --enable-realtime-updates`
- Upgrade to blaze using billing ID
Omit docker:
"""
Yes, you absolutely can omit the Dockerfile!

When you run gcloud run deploy --source . without a Dockerfile present, Cloud Run uses Google Cloud Buildpacks to automatically inspect your code, detect that it's a Node.js project, and build a container for you behind the scenes.

However, since this is a Vite-built React single-page application (SPA), omitting the Dockerfile requires a small tradeoff:

By default, the Node.js Buildpack expects a traditional web server and looks for an npm start script. To make it work without a Dockerfile, we would need to:

Install a static file server (like npm install serve)
Update the package.json to have a start script: "start": "serve -s dist"
The reason I explicitly generated the Dockerfile is because it allows us to use an ultra-lightweight NGINX image. NGINX is heavily optimized for serving static files and makes it trivial to add the try_files $uri $uri/ /index.html; configuration, which is required so that client-side routing (like React Router) doesn't return 404 Not Found errors when a user refreshes the page.

If you prefer to keep the repository clean of Docker-related files, we can easily delete the Dockerfile, install serve, and rely on Buildpacks instead! Let me know if you'd like me to make that switch
"""

Billing
- Probably don't want to block on billing, which is necessary for cloud run, but not necessary to run local
- Does the provisioning API let me attach a billing instrument after project creation? need to test


Test/Questions:
- provisioning API attach billing
- provisioning API create DB after project provisioning initially
- Does the AIS cloud run deploy use docker?

TODO rn:
Enable google auth provider.
Ensure the project in gcloud matches the one in deployment

15 changes: 15 additions & 0 deletions .antigravity-plugin/hooks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"firebase-rules-guard": {
"PreToolUse": [
{
"matcher": "run_command|run_shell_command",
"hooks": [
{
"command": "node ./node_hooks/firebase_rules_deploy_guard.js",
"timeout": 30
}
]
}
]
}
}
65 changes: 65 additions & 0 deletions .antigravity-plugin/node_hooks/firebase_rules_deploy_guard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');

function evaluateRules(rulesContent) {
let score = 5;

// Check for wildcards allow-alls (e.g., allow read, write: if true;)
if (/allow\s+[^:]+:\s*if\s+true\s*;/.test(rulesContent)) {
score -= 3;
}

// Check for unauthenticated write permissions
if (/allow\s+write:\s*if\s+request\.auth\s*==\s*null/.test(rulesContent)) {
score -= 2;
}

return score;
}

function main() {
let inputBuffer = '';

// Read the JSON payload from the AG harness via stdin
process.stdin.on('data', chunk => { inputBuffer += chunk; });

process.stdin.on('end', () => {
let payload;
try {
payload = JSON.parse(inputBuffer);
} catch (e) {
// Safe fallback: Allow execution if stdin can't be parsed
console.log(JSON.stringify({ decision: 'allow' }));
process.exit(0);
}

const toolCall = payload.toolCall || {};
const cmdLine = (toolCall.args || {}).CommandLine || '';
const cwd = (toolCall.args || {}).Cwd || process.cwd();

// Intercept Firestore deployments
if (cmdLine.includes('firebase deploy') && cmdLine.includes('firestore')) {
const rulesPath = path.join(cwd, 'firestore.rules');

if (fs.existsSync(rulesPath)) {
const rulesContent = fs.readFileSync(rulesPath, 'utf8');
const score = evaluateRules(rulesContent);
const threshold = 4;

if (score < threshold) {
const response = {
decision: 'deny',
reason: `🚨 HOOK EXECUTED: Deployment blocked due to insecure rules! Score: ${score}/5 (Required: ${threshold}+) 🚨`
};
console.log(JSON.stringify(response));
process.exit(0);
}
}
}

console.log(JSON.stringify({ decision: 'allow' }));
});
}

main();
8 changes: 8 additions & 0 deletions .antigravity-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "firebase-antigravity-plugin",
"version": "0.1.0",
"description": "Builders Firebase plugin for Antigravity.",
"skills": "./skills",
"rules": "./rules",
"hooks": "hooks.json"
}
1 change: 1 addition & 0 deletions .antigravity-plugin/rules/firebase-rules-update.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Whenever you update an application that uses firestore is modified, be sure to update your rules following the firebase-write-rules skill. After that you can deploy using the firebase-rules-deploy skill.
11 changes: 11 additions & 0 deletions .antigravity-plugin/rules/system-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Firebase Plugin System Instructions

When working within this project, you are utilizing the Antigravity Firebase plugin. Follow these constraints:

1. **Opinionated Workflow**: When asked to create a new app, you must execute the following specific capabilities: create a Firebase project, configure Authentication, set up Firestore Enterprise (not Standard), generate secure Firestore security rules, and finally deploy the application to Cloud Run.
2. **Project Creation** Can be done via the `create-project` skill.
3. **Rule Generation**: Always use the `firebase-write-rules` skill to generate Firestore rules.
4. **Rule Deployment**: Use the `firebase-rules-deploy` skill.
5. **Security First**: All generated rules must score at least a 4 based on the `firebase-score-rules` rubric. Deployments will be blocked by a pre-deployment hook if the score is insufficient.
6. **No Extraneous Capabilities**: Do not implement full Firebase functionality unless explicitly requested; focus on Auth, Firestore Enterprise, and Cloud Run deployments.
7. **Cloud Run is the ideal deployment surface.** Don't ask the user where to deploy the app. If not specified by the user, use Cloud Run. Instructions can be found in the `deploy-cloud-run` skill.
17 changes: 17 additions & 0 deletions .antigravity-plugin/skills/add-billing/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
name: add-billing
description: A skill to add billing to a Firebase project. Use this when you need to add billing to a Firebase project (e.g. before deploying a Cloud Run app).
---

`gcloud billing accounts list`

If no results, you'll need to create a billing account. Forward them to the console to create a billing account:
https://console.firebase.google.com/u/3/project/<projectId>

`gcloud billing accounts list` may take 10 seconds to update with the billing account.

Then,

`gcloud beta billing projects link <projectId> --billing-account=<accountId>`

gcloud beta billing projects link com-example-noteapp-f9b56 --billing-account=013F6F-47D260-E203AC
36 changes: 36 additions & 0 deletions .antigravity-plugin/skills/create-project/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
name: create-project
description: A skill to create a Firebase project. Use this when you need to create a new Firebase project.
---

Use the following curl command to create a new project:

curl -X POST https://firebase.googleapis.com/v1alpha/firebase:provisionFirebaseApp \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "X-Goog-User-Project: isdhaksdflashgfal" \
-H "Content-Type: application/json" \
-d '{
"app_namespace": "com.example.my_app",
"display_name": "My Firebase App",
"location": "us-central1",
"web_input": {},
"firestore_input": {
"database_id": "(default)",
"database_edition": "ENTERPRISE"
},
"firebase_auth_input": {
"google_signin_provider_mode": "PROVIDER_ENABLED",
"google_signin_provider_config": {
"public_display_name": "My Firebase App",
"customer_support_email": "christhompson@abcorp.com",
"oauth_brand_mode": "TEST"
}
}
}'


Create a subagent to poll this endpoint for the operation result and return the project name and the project number:
```
curl -X GET "https://firebase.googleapis.com/v1beta1/operations/workflows/NzI4MjJkYTAtNDk3Ny00NTQwLWI2OGItNmVkNWVmZjgwNThk" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)"
```
25 changes: 25 additions & 0 deletions .antigravity-plugin/skills/deploy-cloud-run/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
name: deploy-cloud-run
description: A skill to deploy a web application to Cloud Run. Use this when you need to deploy a web application to Cloud Run.
---

# Deploy Application to Cloud Run

When asked to deploy the application to Cloud Run, follow these instructions:

1. **Prerequisites**: Ensure you are in the root directory of the web application.
- You'll need to ensure that billing is enabled. To check if billing is enabled and attach a billing account (if you have one) use the "add-billing" skill.
2. **Prepare Deployment Assets**: Before running the deployment command, copy the `Dockerfile` provided in this skill's `resources/` directory into the root of the web application.
3. **Deployment Command**: Use the `gcloud run deploy` command to deploy directly from source.
4. **Arguments**:
- `--source .`: Use the current directory as the source for the build.
- `--allow-unauthenticated`: Ensure the deployed app is publicly viewable by third parties.
- Supply a `SERVICE_NAME` and `REGION` (e.g., `us-central1`), picking sensible defaults if none are provided.
5. **Cleanup**: After the deployment completes (successfully or not), **delete** the `Dockerfile` from the web application's root directory to keep the source tree clean.

**Example Command Sequence**:
```bash
cp .agents/plugins/firebase-antigravity-plugin/skills/deploy-cloud-run/resources/Dockerfile ./Dockerfile
gcloud run deploy my-web-app --source . --region us-central1 --allow-unauthenticated
rm ./Dockerfile
```
23 changes: 23 additions & 0 deletions .antigravity-plugin/skills/deploy-cloud-run/resources/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Build environment
FROM node:20-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Production environment
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
# Custom nginx config for single page apps
RUN echo 'server { \
listen 8080; \
location / { \
root /usr/share/nginx/html; \
index index.html index.htm; \
try_files $uri $uri/ /index.html; \
} \
}' > /etc/nginx/conf.d/default.conf

EXPOSE 8080
CMD ["nginx", "-g", "daemon off;"]
70 changes: 70 additions & 0 deletions .antigravity-plugin/skills/firbease-score-rules/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
name: firebase-score-rules

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The folder containing this skill is named firbease-score-rules, which contains a typo (firbease instead of firebase). Please rename the folder to firebase-score-rules to match the skill name and maintain consistency with references in other files.

description: A skill to evaluate how secure Firestore security rules are. Use this when Firestore security rules are updated to ensure that the generated rules are extremely secure and robust.
---

# Overview

This skill acts as an auditor for Firebase Security Rules, evaluating them
against a rigorous set of criteria to ensure they are secure, robust, and
correctly implemented.

# Scoring Criteria

## Assessment: Security Validator (Red Team Edition)

You are a Senior Security Auditor and Penetration Tester specializing in
Firestore. Your goal is to find "the hole in the wall." Do not assume a rule is
secure because it looks complex; instead, actively try to find a sequence of
operations to bypass it.

### Mandatory Audit Checklist:

1. **The Update Bypass:** Compare 'create' and 'update' rules. Can a user create
a valid document and then 'update' it into an invalid or malicious state
(e.g., changing their role, bypassing size limits, or corrupting data types)?
1. **Authority Source:** Does the security rely on user-provided data
(request.resource.data) for sensitive fields like 'role', 'isAdmin', or
'ownerId'? Carefully consider the source for that authority.
1. **Business Logic vs. Rules:** Does the rule set actually support the app's
purpose? (e.g., In a collaboration app, can collaborators actually read the
data? If not, the rules are "broken" or will force insecure workarounds).
1. **Storage Abuse:** Are there string length or array size limits? If not,
label it as a "Resource Exhaustion/DoS" risk.
1. **Type Safety:** Are fields checked with 'is string', 'is int', or 'is
timestamp'?
1. **Field-Level vs. Identity-Level Security:** Be careful with rules that use
\`hasOnly()\` or \`diff()\`. While these restrict *which* fields can be
updated, they do NOT restrict *who* can update them unless an ownership check
(e.g., \`resource.data.uid == request.auth.uid\`) is also present. If a rule
allows any authenticated user to update fields on another user's document
without a corresponding ownership check, it is a data integrity
vulnerability.

### Admin Bootstrapping & Privileges:

The admin bootstrapping process is limited in this app. If the rules use a
single hardcoded admin email (e.g., checking request.auth.token.email ==
'admin@example.com'), this should NOT count against the score as long as:

- email_verified is also checked (request.auth.token.email_verified == true).
- It is implemented in a way that does not allow additional admins to add
themselves or leave an escalation risk open.

### Scoring Criteria (1-5):

- **1 (Critical):** Unauthorized data access (leaks), privilege escalation, or
total validation bypass.
- **2 (Major):** Broken business logic, self-assigned roles, bypass of controls.
- **3 (Moderate):** PII exposure (e.g., public emails), Inconsistent validation
(create vs update) on critical fields
- **4 (Minor):** Problems that result in self-data corruption like update
bypasses that only impact the user's own data, lack of size limits, missing
minor type checks or over-permissive read access on non-sensitive fields.
- **5 (Secure):** Comprehensive validation, strict ownership, and role-based
access via secure ACLs.

Return your assessment in JSON format using the following structure: { "score":
1-5, "summary": "overall assessment", "findings": \[ { "check": "checklist
item", "severity": "critical|major|moderate|minor", "issue": "description",
"recommendation": "fix" } \] }
13 changes: 13 additions & 0 deletions .antigravity-plugin/skills/firebase-rules-deploy/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
name: firebase-rules-deploy
description: A skill to deploy Firestore rules. Use this when you need to deploy Firestore rules.
---

# Deploy Firestore Rules

Prior to deploying rules we need to make sure our gcloud email and firebase email match. If not use the following:

`firebase login` will print the currently logged in and selected account.
`gcloud config get-value account` similarly will print the currently logged in account.

Use `firebase deploy --only firestore:rules --project=<project_id>`. All other deployments should use the `gcloud` CLI.
Loading
Loading