@justmpm/firebase-audit 0.4.0 → 0.4.1
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/dist/{chunk-5PVQB3ZI.js → chunk-3SEVYYCX.js} +9 -4
- package/dist/{chunk-YVV7YRF3.js → chunk-GOLWQBD5.js} +5 -5
- package/dist/{chunk-TVEZQU7C.js → chunk-PSSMYRRU.js} +3 -1
- package/dist/cli.js +12 -3
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -3
- package/dist/mcp-cli.js +3 -3
- package/dist/mcp.js +3 -3
- package/dist/{scan-6FRUE5BE.js → scan-VREY2FGO.js} +1 -1
- package/dist/{verify-R6LI2KNZ.js → verify-O722ZZBV.js} +1 -1
- package/package.json +1 -1
|
@@ -783,6 +783,10 @@ async function runChecks(model, rootDir, opts = {}) {
|
|
|
783
783
|
}
|
|
784
784
|
}
|
|
785
785
|
const adminHits = await collectAdminImports(rootDir);
|
|
786
|
+
const isTestPath = (f) => {
|
|
787
|
+
const n = f.replace(/\\/g, "/");
|
|
788
|
+
return /\.test\.[tj]sx?$/.test(n) || /\.spec\.[tj]sx?$/.test(n) || /(^|\/)__tests__\//.test(n) || /(^|\/)(test|tests|testing)\//.test(n);
|
|
789
|
+
};
|
|
786
790
|
for (const hit of adminHits) {
|
|
787
791
|
let origin = "UNKNOWN";
|
|
788
792
|
try {
|
|
@@ -791,7 +795,7 @@ async function runChecks(model, rootDir, opts = {}) {
|
|
|
791
795
|
} catch {
|
|
792
796
|
origin = "UNKNOWN";
|
|
793
797
|
}
|
|
794
|
-
if (origin === "CLIENT") {
|
|
798
|
+
if (origin === "CLIENT" && !isTestPath(hit.file)) {
|
|
795
799
|
findings.push(
|
|
796
800
|
make(
|
|
797
801
|
"FBA003",
|
|
@@ -1329,16 +1333,17 @@ async function scan(rootDir, opts = {}) {
|
|
|
1329
1333
|
});
|
|
1330
1334
|
}
|
|
1331
1335
|
} else {
|
|
1336
|
+
const details = validated.error.issues.slice(0, 5).map((i) => `${String(i.path.join(".")) || "(raiz)"}: ${i.message}`).join("; ");
|
|
1332
1337
|
findings_pre.push({
|
|
1333
1338
|
rule: "CONTRACT_INVALID",
|
|
1334
1339
|
severity: "WARNING",
|
|
1335
1340
|
confidence: "CONFIRMED",
|
|
1336
|
-
message: `firebase-audit.yaml
|
|
1341
|
+
message: `firebase-audit.yaml inv\xE1lido (${validated.error.issues.length} problema(s): ${details}) \u2014 contrato ignorado neste scan.`,
|
|
1337
1342
|
fingerprint: "CONTRACT_INVALID",
|
|
1338
1343
|
evidence: [
|
|
1339
|
-
{ id: "ev-contract-invalid", kind: "contract-parse", summary:
|
|
1344
|
+
{ id: "ev-contract-invalid", kind: "contract-parse", summary: details.slice(0, 200), confidence: "CONFIRMED" }
|
|
1340
1345
|
],
|
|
1341
|
-
fix: "Valide contra templates/firebase-audit.yaml."
|
|
1346
|
+
fix: "Valide contra templates/firebase-audit.yaml (min\xFAsculas, sem chaves extras)."
|
|
1342
1347
|
});
|
|
1343
1348
|
}
|
|
1344
1349
|
} catch (err) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
scan
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-3SEVYYCX.js";
|
|
4
4
|
import {
|
|
5
5
|
verify
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-PSSMYRRU.js";
|
|
7
7
|
import {
|
|
8
8
|
drift
|
|
9
9
|
} from "./chunk-NJBCSW7E.js";
|
|
@@ -120,8 +120,8 @@ function createMcpServer() {
|
|
|
120
120
|
title: "Firebase Audit Drift (\xEDndices)",
|
|
121
121
|
description: "Compara \xEDndices locais vs implantados. Retorna MATCHED/LOCAL_ONLY/REMOTE_ONLY. Nunca diz 'unused', apenas NOT_OBSERVED.",
|
|
122
122
|
inputSchema: {
|
|
123
|
-
local: z.string().nullable().describe("Path do firestore.indexes.json local (ou null). Relativo resolve contra cwd."),
|
|
124
|
-
remote: z.string().nullable().describe("Path do JSON remoto (gcloud/REST) (ou null). Relativo resolve contra cwd."),
|
|
123
|
+
local: z.string().nullable().optional().describe("Path do firestore.indexes.json local (ou null). Relativo resolve contra cwd."),
|
|
124
|
+
remote: z.string().nullable().optional().describe("Path do JSON remoto (gcloud/REST) (ou null). Relativo resolve contra cwd."),
|
|
125
125
|
cwd: z.string().optional().describe("Diret\xF3rio base para paths relativos (default: cwd do servidor).")
|
|
126
126
|
}
|
|
127
127
|
},
|
|
@@ -130,7 +130,7 @@ function createMcpServer() {
|
|
|
130
130
|
const { resolve: resolveP, isAbsolute } = await import("path");
|
|
131
131
|
const base = cwd && cwd.length > 0 ? cwd : process.cwd();
|
|
132
132
|
const resPath = (p) => {
|
|
133
|
-
if (p === null) return null;
|
|
133
|
+
if (p === null || p === void 0) return null;
|
|
134
134
|
return isAbsolute(p) ? p : resolveP(base, p);
|
|
135
135
|
};
|
|
136
136
|
const res = drift(resPath(local), resPath(remote));
|
|
@@ -7,7 +7,7 @@ function collectVisitCounts(node, out) {
|
|
|
7
7
|
return;
|
|
8
8
|
}
|
|
9
9
|
const rec = node;
|
|
10
|
-
for (const k of ["visitCount", "visit_count"
|
|
10
|
+
for (const k of ["visitCount", "visit_count"]) {
|
|
11
11
|
const v = rec[k];
|
|
12
12
|
if (typeof v === "number" && Number.isFinite(v)) {
|
|
13
13
|
out.push(v);
|
|
@@ -26,6 +26,7 @@ function planVerify(model) {
|
|
|
26
26
|
};
|
|
27
27
|
const cases = [];
|
|
28
28
|
for (const rule of model.rules) {
|
|
29
|
+
if (rule.path === "/(unknown)") continue;
|
|
29
30
|
for (const role of roles) {
|
|
30
31
|
for (const op of rule.operations) {
|
|
31
32
|
for (const mapped of expand(op)) {
|
|
@@ -105,6 +106,7 @@ function verify(model, opts = {}) {
|
|
|
105
106
|
return { cases, uncovered: [], findings, coveragePct };
|
|
106
107
|
}
|
|
107
108
|
for (const rule of model.rules) {
|
|
109
|
+
if (rule.path === "/(unknown)") continue;
|
|
108
110
|
uncovered.push(rule.path);
|
|
109
111
|
}
|
|
110
112
|
return { cases, uncovered, findings, coveragePct };
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
scan
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3SEVYYCX.js";
|
|
5
5
|
|
|
6
6
|
// src/cli.ts
|
|
7
7
|
import { createRequire } from "module";
|
|
@@ -64,8 +64,8 @@ Uso: firebase-audit scan|check|verify|drift [--json] ...`);
|
|
|
64
64
|
const { resolve: resolveRoot } = await import("path");
|
|
65
65
|
const rootDir = cwdArg ? resolveRoot(process.cwd(), cwdArg) : process.cwd();
|
|
66
66
|
if (cmd === "verify") {
|
|
67
|
-
const { scan: scanForVerify } = await import("./scan-
|
|
68
|
-
const { verify } = await import("./verify-
|
|
67
|
+
const { scan: scanForVerify } = await import("./scan-VREY2FGO.js");
|
|
68
|
+
const { verify } = await import("./verify-O722ZZBV.js");
|
|
69
69
|
const { resolve: resolveVerify } = await import("path");
|
|
70
70
|
const coverageArg = getArg("coverage");
|
|
71
71
|
const coveragePath = coverageArg ? resolveVerify(rootDir, coverageArg) : void 0;
|
|
@@ -107,6 +107,15 @@ ${icon} ${f.rule} [${f.confidence}]
|
|
|
107
107
|
const remotePath = remoteArg ? resolveDrift(rootDir, remoteArg) : null;
|
|
108
108
|
for (const [label, p] of [["--local", localPath], ["--remote", remotePath]]) {
|
|
109
109
|
if (p && !existsDrift(p)) {
|
|
110
|
+
if (asJson) {
|
|
111
|
+
const { drift: driftMissing } = await import("./drift-KU7HWL7M.js");
|
|
112
|
+
const res2 = driftMissing(
|
|
113
|
+
localPath && existsDrift(localPath) ? localPath : null,
|
|
114
|
+
remotePath && existsDrift(remotePath) ? remotePath : null
|
|
115
|
+
);
|
|
116
|
+
console.log(JSON.stringify({ version: pkg.version, entries: res2.entries, findings: res2.findings }, null, 2));
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
110
119
|
console.error(`Arquivo ${label} n\xE3o encontrado: ${p}`);
|
|
111
120
|
process.exit(1);
|
|
112
121
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -643,6 +643,10 @@ declare function enrichWithGraph(rootDir: string, d: DiscoveryResult): Promise<v
|
|
|
643
643
|
/**
|
|
644
644
|
* Rules extractor — estrutura + referências + locations (sem avaliar).
|
|
645
645
|
* Parser leve e intencionalmente incompleto: avaliação real é do Emulator (V3).
|
|
646
|
+
*
|
|
647
|
+
* Limitação conhecida: `ALLOW_RE` corta a condição no primeiro `;` mesmo dentro
|
|
648
|
+
* de string literal (ex: `x != "a;b"`). Raríssimo em Rules reais; documentado aqui
|
|
649
|
+
* em vez de silêncio — Emulator acusa a regra de verdade.
|
|
646
650
|
*/
|
|
647
651
|
|
|
648
652
|
type Rule = z$1.infer<typeof RuleSchema>;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createMcpServer,
|
|
3
3
|
startMcpServer
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-GOLWQBD5.js";
|
|
5
5
|
import {
|
|
6
6
|
AccessOriginSchema,
|
|
7
7
|
AuditYamlSchema,
|
|
@@ -53,11 +53,11 @@ import {
|
|
|
53
53
|
stripOuterParens,
|
|
54
54
|
stripRuleComments,
|
|
55
55
|
validateClaimSamples
|
|
56
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-3SEVYYCX.js";
|
|
57
57
|
import {
|
|
58
58
|
planVerify,
|
|
59
59
|
verify
|
|
60
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-PSSMYRRU.js";
|
|
61
61
|
import {
|
|
62
62
|
drift
|
|
63
63
|
} from "./chunk-NJBCSW7E.js";
|
package/dist/mcp-cli.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
startMcpServer
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-GOLWQBD5.js";
|
|
5
|
+
import "./chunk-3SEVYYCX.js";
|
|
6
|
+
import "./chunk-PSSMYRRU.js";
|
|
7
7
|
import "./chunk-NJBCSW7E.js";
|
|
8
8
|
|
|
9
9
|
// src/mcp-cli.ts
|
package/dist/mcp.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createMcpServer,
|
|
3
3
|
startMcpServer
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-GOLWQBD5.js";
|
|
5
|
+
import "./chunk-3SEVYYCX.js";
|
|
6
|
+
import "./chunk-PSSMYRRU.js";
|
|
7
7
|
import "./chunk-NJBCSW7E.js";
|
|
8
8
|
export {
|
|
9
9
|
createMcpServer,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@justmpm/firebase-audit",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Auditor de consistência e segurança para projetos Firebase: código + Rules + índices + contrato vs comportamento. Static-first, nunca inventa certeza.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"firebase",
|