pyric-admin 0.1.0-alpha.10 → 0.1.0-alpha.11

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.
@@ -14,6 +14,24 @@
14
14
  * default-app resolution and throw the captured `app/no-app` error when
15
15
  * nothing is initialized. The original `getFirestore(ctx)` context form
16
16
  * (the load-bearing shape the existing suite uses) is preserved verbatim.
17
+ *
18
+ * RULES-BYPASS PARITY (#394): the two APP-resolution forms — `getFirestore(app)`
19
+ * and no-arg `getFirestore()` — mirror `firebase-admin/firestore`'s
20
+ * `getFirestore(app?)`, and REAL firebase-admin bypasses security rules. So both
21
+ * app forms resolve to the rules-BYPASS admin lens (`getAdminFirestore` →
22
+ * `{ mode: 'admin' }`), exactly as `pyric-admin/database`'s `getDatabase(app)`
23
+ * and `pyric-admin/storage`'s `getStorage(app)` already do. Previously the app
24
+ * forms routed through the anon-lens `getFirestore(sandbox.withAuth(null))`,
25
+ * which evaluates `request.auth == null` and is DENIED by any real ruleset — a
26
+ * deny-direction divergence from production that blocked the RTDB-trigger →
27
+ * Firestore-stamp pattern (a Cloud Function's admin write).
28
+ *
29
+ * The `getFirestore(ctx)` CONTEXT form is UNCHANGED and stays rules-ENFORCED
30
+ * (its captured identity is load-bearing for the rules-simulation suite). No
31
+ * page ever reaches this module: a page's `firebase/firestore` resolves to
32
+ * `pyric/firestore` (the rules-enforced client), not `pyric-admin`; only the
33
+ * `firebase-admin/*` → `pyric-admin/*` swap in the trusted functions child
34
+ * imports this. See {@link getFirestore}.
17
35
  */
18
36
  export * from 'pyric/sandbox/admin-firestore';
19
37
  import { type SandboxFirestore } from 'pyric/sandbox/admin-firestore';
@@ -22,11 +40,19 @@ import { type PyricAdminApp } from '../app/index.js';
22
40
  /**
23
41
  * Return the admin Firestore handle.
24
42
  *
25
- * - `getFirestore(ctx)` — the original context form (rules-applied for the
43
+ * - `getFirestore(ctx)` — the original context form (rules-APPLIED for the
26
44
  * ctx's captured identity). Unchanged; idempotent per `SandboxContext`.
27
- * - `getFirestore(app)` resolves a {@link PyricAdminApp}'s sandbox.
28
- * - `getFirestore()` resolves the default app; throws `app/no-app` when
29
- * nothing is initialized.
45
+ * This is the pyric-internal rules-simulation shape, not a firebase-admin
46
+ * shape, so it keeps rule evaluation.
47
+ * - `getFirestore(app)` — resolves a {@link PyricAdminApp}'s sandbox to the
48
+ * rules-BYPASS admin lens (firebase-admin parity, #394).
49
+ * - `getFirestore()` — resolves the default app to the rules-BYPASS admin
50
+ * lens; throws `app/no-app` when nothing is initialized.
51
+ *
52
+ * The app forms mirror `firebase-admin/firestore`'s `getFirestore(app?)`,
53
+ * which bypasses security rules — so a Cloud Function's admin write lands the
54
+ * same way it does in production, instead of being denied as `request.auth ==
55
+ * null` by the sandbox's anon lens (the #394 deny-direction divergence).
30
56
  */
31
57
  export declare function getFirestore(target?: SandboxContext | PyricAdminApp): SandboxFirestore;
32
58
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/firestore/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,cAAc,+BAA+B,CAAC;AAE9C,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,iBAAiB,CAAC;AAoBzB;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,MAAM,CAAC,EAAE,cAAc,GAAG,aAAa,GACtC,gBAAgB,CAUlB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/firestore/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,cAAc,+BAA+B,CAAC;AAE9C,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,iBAAiB,CAAC;AAsBzB;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAC1B,MAAM,CAAC,EAAE,cAAc,GAAG,aAAa,GACtC,gBAAgB,CAUlB"}
@@ -14,18 +14,38 @@
14
14
  * default-app resolution and throw the captured `app/no-app` error when
15
15
  * nothing is initialized. The original `getFirestore(ctx)` context form
16
16
  * (the load-bearing shape the existing suite uses) is preserved verbatim.
17
+ *
18
+ * RULES-BYPASS PARITY (#394): the two APP-resolution forms — `getFirestore(app)`
19
+ * and no-arg `getFirestore()` — mirror `firebase-admin/firestore`'s
20
+ * `getFirestore(app?)`, and REAL firebase-admin bypasses security rules. So both
21
+ * app forms resolve to the rules-BYPASS admin lens (`getAdminFirestore` →
22
+ * `{ mode: 'admin' }`), exactly as `pyric-admin/database`'s `getDatabase(app)`
23
+ * and `pyric-admin/storage`'s `getStorage(app)` already do. Previously the app
24
+ * forms routed through the anon-lens `getFirestore(sandbox.withAuth(null))`,
25
+ * which evaluates `request.auth == null` and is DENIED by any real ruleset — a
26
+ * deny-direction divergence from production that blocked the RTDB-trigger →
27
+ * Firestore-stamp pattern (a Cloud Function's admin write).
28
+ *
29
+ * The `getFirestore(ctx)` CONTEXT form is UNCHANGED and stays rules-ENFORCED
30
+ * (its captured identity is load-bearing for the rules-simulation suite). No
31
+ * page ever reaches this module: a page's `firebase/firestore` resolves to
32
+ * `pyric/firestore` (the rules-enforced client), not `pyric-admin`; only the
33
+ * `firebase-admin/*` → `pyric-admin/*` swap in the trusted functions child
34
+ * imports this. See {@link getFirestore}.
17
35
  */
18
36
  export * from 'pyric/sandbox/admin-firestore';
19
- import { getFirestore as baseGetFirestore, } from 'pyric/sandbox/admin-firestore';
37
+ import { getFirestore as baseGetFirestore, getAdminFirestore as baseGetAdminFirestore, } from 'pyric/sandbox/admin-firestore';
20
38
  import { ADMIN_APP_TARGET, getApp, isSandboxAdminApp, } from '../app/index.js';
21
39
  import { assertAdminAppActive } from '../app/lifecycle.js';
22
- /** Narrow a `PyricAdminApp` to the anonymous {@link SandboxContext} the
23
- * admin firestore backend runs against. Sandbox apps expose their
24
- * `Sandbox` — LOCAL and REMOTE alike: the base `getFirestore` is
25
- * remote-aware (it dispatches a remote-branded sandbox to the
26
- * channel-backed arm), so no guard is needed here. Prod apps require
27
- * firebase-admin's real Firestore, which the in-process backend does
28
- * not model. */
40
+ /** Narrow a `PyricAdminApp` to the {@link SandboxContext} the admin
41
+ * firestore backend runs against. Sandbox apps expose their `Sandbox` —
42
+ * LOCAL and REMOTE alike: the base resolvers are remote-aware (they
43
+ * dispatch a remote-branded sandbox to the channel-backed arm), so no
44
+ * guard is needed here. The context's captured auth is IRRELEVANT on the
45
+ * admin path (rules are bypassed, so no rule reads `request.auth`); it is
46
+ * normalised to `withAuth(null)` only to obtain a context. Prod apps
47
+ * require firebase-admin's real Firestore, which the in-process backend
48
+ * does not model. */
29
49
  function adminAppToContext(app) {
30
50
  if (isSandboxAdminApp(app)) {
31
51
  return app.sandbox.withAuth(null);
@@ -36,20 +56,28 @@ function adminAppToContext(app) {
36
56
  /**
37
57
  * Return the admin Firestore handle.
38
58
  *
39
- * - `getFirestore(ctx)` — the original context form (rules-applied for the
59
+ * - `getFirestore(ctx)` — the original context form (rules-APPLIED for the
40
60
  * ctx's captured identity). Unchanged; idempotent per `SandboxContext`.
41
- * - `getFirestore(app)` resolves a {@link PyricAdminApp}'s sandbox.
42
- * - `getFirestore()` resolves the default app; throws `app/no-app` when
43
- * nothing is initialized.
61
+ * This is the pyric-internal rules-simulation shape, not a firebase-admin
62
+ * shape, so it keeps rule evaluation.
63
+ * - `getFirestore(app)` — resolves a {@link PyricAdminApp}'s sandbox to the
64
+ * rules-BYPASS admin lens (firebase-admin parity, #394).
65
+ * - `getFirestore()` — resolves the default app to the rules-BYPASS admin
66
+ * lens; throws `app/no-app` when nothing is initialized.
67
+ *
68
+ * The app forms mirror `firebase-admin/firestore`'s `getFirestore(app?)`,
69
+ * which bypasses security rules — so a Cloud Function's admin write lands the
70
+ * same way it does in production, instead of being denied as `request.auth ==
71
+ * null` by the sandbox's anon lens (the #394 deny-direction divergence).
44
72
  */
45
73
  export function getFirestore(target) {
46
74
  if (target === undefined) {
47
- return baseGetFirestore(adminAppToContext(getApp()));
75
+ return baseGetAdminFirestore(adminAppToContext(getApp()));
48
76
  }
49
77
  if (typeof target === 'object' && target !== null && ADMIN_APP_TARGET in target) {
50
78
  const app = target;
51
79
  assertAdminAppActive(app);
52
- return baseGetFirestore(adminAppToContext(app));
80
+ return baseGetAdminFirestore(adminAppToContext(app));
53
81
  }
54
82
  return baseGetFirestore(target);
55
83
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/firestore/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,cAAc,+BAA+B,CAAC;AAE9C,OAAO,EACL,YAAY,IAAI,gBAAgB,GAEjC,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,gBAAgB,EAChB,MAAM,EACN,iBAAiB,GAElB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3D;;;;;;iBAMiB;AACjB,SAAS,iBAAiB,CAAC,GAAkB;IAC3C,IAAI,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IACD,MAAM,IAAI,KAAK,CACb,wEAAwE;QACtE,sEAAsE,CACzE,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAC1B,MAAuC;IAEvC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,gBAAgB,CAAC,iBAAiB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,gBAAgB,IAAI,MAAM,EAAE,CAAC;QAChF,MAAM,GAAG,GAAG,MAAuB,CAAC;QACpC,oBAAoB,CAAC,GAAG,CAAC,CAAC;QAC1B,OAAO,gBAAgB,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,gBAAgB,CAAC,MAAwB,CAAC,CAAC;AACpD,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/firestore/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,cAAc,+BAA+B,CAAC;AAE9C,OAAO,EACL,YAAY,IAAI,gBAAgB,EAChC,iBAAiB,IAAI,qBAAqB,GAE3C,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,gBAAgB,EAChB,MAAM,EACN,iBAAiB,GAElB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3D;;;;;;;;sBAQsB;AACtB,SAAS,iBAAiB,CAAC,GAAkB;IAC3C,IAAI,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IACD,MAAM,IAAI,KAAK,CACb,wEAAwE;QACtE,sEAAsE,CACzE,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,YAAY,CAC1B,MAAuC;IAEvC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,qBAAqB,CAAC,iBAAiB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,gBAAgB,IAAI,MAAM,EAAE,CAAC;QAChF,MAAM,GAAG,GAAG,MAAuB,CAAC;QACpC,oBAAoB,CAAC,GAAG,CAAC,CAAC;QAC1B,OAAO,qBAAqB,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,gBAAgB,CAAC,MAAwB,CAAC,CAAC;AACpD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pyric-admin",
3
- "version": "0.1.0-alpha.10",
3
+ "version": "0.1.0-alpha.11",
4
4
  "license": "Apache-2.0",
5
5
  "homepage": "https://pyric.dev",
6
6
  "repository": {
@@ -46,7 +46,7 @@
46
46
  "typecheck": "bun x tsc -p tsconfig.json --noEmit"
47
47
  },
48
48
  "dependencies": {
49
- "pyric": "^0.1.0-alpha.10"
49
+ "pyric": "^0.1.0-alpha.11"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/bun": "latest",