fireemu 0.19.0 → 0.20.0

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.
Files changed (2) hide show
  1. package/README.md +32 -26
  2. package/package.json +6 -6
package/README.md CHANGED
@@ -14,7 +14,7 @@ Fireemu is being developed to close these gaps. For example, it provides:
14
14
 
15
15
  Fireemu is still in development and does not yet reproduce every feature and behavior of production Firebase. Before relying on Fireemu’s test results in CI or other automated workflows, we recommend differential testing against production Firebase services for the features and critical workflows your application uses. Run the same tests against Fireemu and a dedicated Firebase test project, and check for differences in results and behavior that could affect your application. Use a dedicated test project, not your live production project.
16
16
 
17
- See the [capability manifest](https://github.com/t-k/fireemu/blob/v0.19.0/crates/fireemu/src/capabilities.json) and [compatibility documentation](https://github.com/t-k/fireemu/blob/v0.19.0/docs/compatibility-contract.md) for supported features, known differences, and the status of compatibility verification.
17
+ See the [capability manifest](https://github.com/t-k/fireemu/blob/v0.20.0/crates/fireemu/src/capabilities.json) and [compatibility documentation](https://github.com/t-k/fireemu/blob/v0.20.0/docs/compatibility-contract.md) for supported features, known differences, and the status of compatibility verification.
18
18
 
19
19
  ## Quick start
20
20
 
@@ -65,18 +65,18 @@ Fireemu supports Cloud Firestore, Firebase Authentication (Identity Platform), C
65
65
  |---|---|
66
66
  | Cloud Firestore | The Enterprise Pipeline API supports a limited subset of read operations. Full-text search supports index definition validation, but local search execution is not supported. |
67
67
  | Firebase Authentication (Identity Platform) | Authentication flows that communicate with external identity providers, authorization-code exchange, and SAML XML signature verification are outside the supported scope. These are separate from local authentication behavior and provider configuration. |
68
- | Cloud Storage for Firebase | Object versioning, signed URLs, ACL-based access control, object composition (`compose`), and notification configuration are not supported. |
69
- | Cloud Functions for Firebase | Triggers that depend on unsupported products, such as Realtime Database (deferred), Remote Config, and Data Connect (deferred), cannot run. Storage archive events do not occur because object versioning is not supported. |
68
+ | Cloud Storage for Firebase | Signed-URL and POST-policy signatures are not verified (their expiry and conditions are), object ACLs other than `allUsers` read are not enforced, and IAM and bucket-level public access are not modeled. Object composition (`compose`) and notification configuration are not supported. |
69
+ | Cloud Functions for Firebase | Triggers that depend on unsupported products, such as Realtime Database (deferred), Remote Config, and Data Connect (deferred), cannot run. Storage archive events occur only for a bucket whose versioning was enabled, and their shape is unrecorded. |
70
70
  | Cloud Pub/Sub | Schemas, BigQuery and Cloud Storage subscription delivery, and some APIs such as `UpdateTopic` are not supported. |
71
71
  | Firebase App Check | Local testing with debug tokens is supported. Real attestation through Play Integrity, App Attest, DeviceCheck, or reCAPTCHA, and replay protection using limited-use tokens, are not supported. |
72
72
 
73
- This table highlights key limitations; it is not exhaustive. Check individual API support and conditions with the following command or the [capability manifest](https://github.com/t-k/fireemu/blob/v0.19.0/crates/fireemu/src/capabilities.json).
73
+ This table highlights key limitations; it is not exhaustive. Check individual API support and conditions with the following command or the [capability manifest](https://github.com/t-k/fireemu/blob/v0.20.0/crates/fireemu/src/capabilities.json).
74
74
 
75
75
  ```sh
76
76
  npx fireemu capabilities
77
77
  ```
78
78
 
79
- See the [Functions support inventory](https://github.com/t-k/fireemu/blob/v0.19.0/docs/functions-export-inventory.md) for support by trigger type.
79
+ See the [Functions support inventory](https://github.com/t-k/fireemu/blob/v0.20.0/docs/functions-export-inventory.md) for support by trigger type.
80
80
 
81
81
  ### Unsupported products
82
82
 
@@ -137,7 +137,7 @@ Use `--ui-port 0` to disable the UI. When automatic UI startup cannot bind the d
137
137
 
138
138
  When a Functions codebase is loaded, the Functions page shows registered functions, triggers, invocation results, and logs. You can run scheduled functions immediately or advance the virtual clock to their next scheduled execution.
139
139
 
140
- For clock-sensitive and parallel integration tests, [test clocks and independent worlds](https://github.com/t-k/fireemu/blob/v0.19.0/docs/test-worlds.md) describes explicit Node Date/timer/Cloud Tasks policies and the `fireemu/testing` helper. Separate worlds isolate their clocks, Rules, Functions and service state, including when they use the same project ID.
140
+ For clock-sensitive and parallel integration tests, [test clocks and independent worlds](https://github.com/t-k/fireemu/blob/v0.20.0/docs/test-worlds.md) describes explicit Node Date/timer/Cloud Tasks policies and the `fireemu/testing` helper. Separate worlds isolate their clocks, Rules, Functions and service state, including when they use the same project ID.
141
141
 
142
142
  ### Export data
143
143
 
@@ -267,10 +267,14 @@ Fireemu is mostly run by tests, in CI and on a developer's machine. Where produc
267
267
  |---|---|---|
268
268
  | Unsigned emulator custom tokens are accepted | `auth.allowUnsignedCustomTokens` | refused |
269
269
  | Firestore and Storage Security Rules accept `@firebase/rules-unit-testing`'s unsigned mock ID token (`authenticatedContext()`, the client SDK's `mockUserToken`) | `auth.allowUnsignedIdTokens` | mock-token fallback disabled; normally verified fireemu-issued tokens still accepted |
270
- | Identity-provider sign-in accepts the fixture assertions and the sign-in widget (`/emulator/auth/handler`), for built-in, `oidc.*` and `saml.*` providers | `auth.idpAssertions` (`"fixture"`) | `"signed"`: OIDC ID tokens must verify with an `auth.idpSigners` key, SAML responses with the provider's certificates, and the fixture and built-in providers are refused |
271
- | The strict Eventarc listener admits any credential or none, so the Admin SDK publishes with a fake credential (see [Eventarc authentication](https://github.com/t-k/fireemu/blob/v0.19.0/docs/eventarc-authentication.md)) | `eventarc.authentication` (`"permissive"`) | `"production"`: a missing, malformed or JWT-shaped bearer is refused with production's 401 |
270
+ | Identity-provider sign-in accepts the fixture assertions and the sign-in widget (`/emulator/auth/handler`), for built-in, `oidc.*` and `saml.*` providers; under `strict` an `oidc.*` or `saml.*` provider must still be configured and enabled (`auth.providers` or the Admin API), as production requires | `auth.idpAssertions` (`"fixture"`) | `"signed"`: OIDC ID tokens must verify with an `auth.idpSigners` key, SAML responses with the provider's certificates, and the fixture and built-in providers are refused |
271
+ | The strict Eventarc listener admits any credential or none, so the Admin SDK publishes with a fake credential (see [Eventarc authentication](https://github.com/t-k/fireemu/blob/v0.20.0/docs/eventarc-authentication.md)) | `eventarc.authentication` (`"permissive"`) | `"production"`: a missing, malformed or JWT-shaped bearer is refused with production's 401 |
272
272
  | A tenant of `auth.tenants` can have any readable id, such as `tenant-a` | `auth.tenantIdFormat` (`"readable"`) | the id must have production's generated form, the display name, a hyphen and five characters of `a-z0-9` (`"generated"`) |
273
+ | Multi-tenancy is on: the Admin API creates tenants and `auth.tenants` loads without an `updateConfig` call | `auth.multiTenant.allowTenants` (`true`) | unset until it is enabled, as in a new production project: tenant routes are refused and `auth.tenants` needs `allowTenants: true` |
274
+ | Multi-factor authentication is on, SMS and TOTP, without a console toggle, an `updateConfig` call or an `auth.mfa` block | `auth.mfa` (`state: "ENABLED"`, `PHONE_SMS` and TOTP) | off until enabled, as in a new production project: enrollment is refused with `OPERATION_NOT_ALLOWED : SMS based MFA not enabled.` or `TOTP based MFA not enabled.` |
273
275
  | An end user's native gRPC `Listen` stream stays open however long it is held. `POST /v1/firestore/listen:expire` on the control API ends every held end-user stream at once, with production's status, to test a client's reconnect | `firestore.listenStreamLifetime` (`"unlimited"`) | ended with `INTERNAL` an hour after it opened, as production ends it (`"oneHour"`) |
276
+ | App Check is served without registering an app: any well-formed debug token (a UUIDv4) exchanges for any app, so an `enforceAppCheck` callable works with no `appCheck` block and a missing or malformed token is still refused | `appCheck.debugTokens` (`"any"`) | only registered apps and digests exchange (`"registered"`); an `appCheck` block asks for this too |
277
+ | Dead-letter forwarding needs neither a project number nor IAM grants | `pubsub.deadLetterAuthorization` (`"implicit"`) | forwarded only after the service agent holds `roles/pubsub.subscriber` on the subscription and `roles/pubsub.publisher` on the dead-letter topic (`"iam"`); naming `pubsub.projectNumbers` selects it |
274
278
 
275
279
  The start banner and `fireemu capabilities` report whether `productionExact` is set.
276
280
 
@@ -289,8 +293,8 @@ When a test fails under `strict` but passed on the official emulator, it is usua
289
293
  | Setting | What it does under `strict` |
290
294
  |---|---|
291
295
  | `auth.improvedEmailPrivacy` | Email enumeration protection, on for a new production project. Set `false` only if your production project turned it off; sign-ins then answer `EMAIL_NOT_FOUND` and `INVALID_PASSWORD` as the official Auth emulator does |
292
- | `auth.mfa` | Your project's multi-factor configuration (an object, see [Enable multi-factor authentication at start](#enable-multi-factor-authentication-at-start)). `strict` starts with multi-factor off, as a new production project does, and the official emulator has no TOTP at all |
293
- | `firestore.enforceLimits` | Production always enforces the Standard edition query limits. `false` lets queries pass that production refuses, so leave it on unless you have a specific reason |
296
+ | `auth.mfa` | Your project's multi-factor configuration (an object, see [Enable multi-factor authentication at start](#enable-multi-factor-authentication-at-start)). `strict` starts with SMS and TOTP enabled as a development default, `productionExact` starts with multi-factor off as a new production project does, and the official emulator has no TOTP at all. A declared block always decides, so `{"state": "DISABLED"}` makes enrollment fail as it does in a project that never enabled it |
297
+ | `firestore.enforceLimits` | Production always enforces the Standard edition query limits. `false` lets queries pass that production refuses, so leave it on unless you have a specific reason. Under `strict` it switches only the query limits |
294
298
 
295
299
  ### Basic configuration
296
300
 
@@ -314,7 +318,7 @@ You can also name the configuration file with `--config`.
314
318
  npx fireemu up --config ./fireemu.json
315
319
  ```
316
320
 
317
- Keep Fireemu-specific settings in a Fireemu configuration file containing `"schemaVersion": 1`, rather than in `firebase.json`. See the [configuration schema](https://github.com/t-k/fireemu/blob/v0.19.0/spec/config/fireemu.schema.json) for all available settings.
321
+ Keep Fireemu-specific settings in a Fireemu configuration file containing `"schemaVersion": 1`, rather than in `firebase.json`. See the [configuration schema](https://github.com/t-k/fireemu/blob/v0.20.0/spec/config/fireemu.schema.json) for all available settings.
318
322
 
319
323
  ### Firebase Authentication (Identity Platform) configuration
320
324
 
@@ -345,13 +349,13 @@ Unsigned custom tokens minted by the Firebase Admin SDK in emulator mode are acc
345
349
 
346
350
  The unsigned mock ID token of `@firebase/rules-unit-testing` is accepted by default when Firestore and Storage Security Rules are evaluated, including with the `strict` profile. This is the token `authenticatedContext()` and the client SDKs' `mockUserToken` option send (`createMockUserToken` in `@firebase/util`). Normal verification runs first. Only after it fails can the mock-token fallback accept a token. Under `strict` that fallback accepts only the exact SDK shape: a JWT whose header is exactly `{"alg":"none","type":"JWT"}` and whose signature is empty. `request.auth` is built from the token's claims, as the official emulator builds it, when the token names a subject (`sub`) and its audience (`aud`) is the project the request goes to. Its `exp` is not checked, because the SDK sets `iat: 0` and `exp: 3600` by default. Every other token is verified as before, expiry included. That covers the unsigned ID tokens fireemu itself issues (their header carries `typ`, not `type`), and a token that claims a signature that does not verify is still refused. The `emulator` profile accepts any unsigned token, as the official emulator does, and its Storage also accepts another project's token. Set `auth.allowUnsignedIdTokens` to `false` (in either profile) or set `productionExact` to disable this fallback. Neither setting refuses fireemu-issued unsigned ID tokens that pass normal verification. Changing only an issued token's header to the SDK shape can still pass normal verification of its payload; it is not a refusal test. For a refusal test, use `createMockUserToken` with its default `iat: 0` / `exp: 3600`, or construct that exact header and empty signature with those times, a subject and the routed project as audience, and run with a clock after expiry (including Firestore's 30-second allowance). A session with `auth.idTokenSigning: "session-rsa"` accepts no unsigned token. The setting does not affect callable Functions, Identity Toolkit or App Check.
347
351
 
348
- See the [configuration schema](https://github.com/t-k/fireemu/blob/v0.19.0/spec/config/fireemu.schema.json) for the format and accepted values of each setting.
352
+ See the [configuration schema](https://github.com/t-k/fireemu/blob/v0.20.0/spec/config/fireemu.schema.json) for the format and accepted values of each setting.
349
353
 
350
- Declare `auth.authorizedDomains`, for example `["localhost", "app.test"]`, to set the initial project-wide list in either profile. The list replaces the defaults, so include `localhost` if your tests use it. An empty list authorizes no host under `strict`; an absent or `null` setting keeps the existing defaults (`localhost` and the project's `firebaseapp.com` and `web.app` domains). Validation uses the Admin API's rules for the selected profile, including its conversion of numeric and boolean entries to strings and omission of `null` entries; use strings when writing the list. Fireemu intentionally keeps `localhost` in its defaults for development. The [recorded production sandbox baseline](https://github.com/t-k/fireemu/blob/v0.19.0/conformance/auth-action-production.json) does not include it; new production projects may also omit it. This default is a Fireemu-only convenience, and declaring the list replaces it. Tenant-scoped strict action links currently check the tenant's default domains rather than this project declaration; support for the parent project's live list is pending.
354
+ Declare `auth.authorizedDomains`, for example `["localhost", "app.test"]`, to set the initial project-wide list in either profile. The list replaces the defaults, so include `localhost` if your tests use it. An empty list authorizes no host under `strict`; an absent or `null` setting keeps the existing defaults (`localhost` and the project's `firebaseapp.com` and `web.app` domains). Validation uses the Admin API's rules for the selected profile, including its conversion of numeric and boolean entries to strings and omission of `null` entries; use strings when writing the list. Fireemu intentionally keeps `localhost` in its defaults for development. The [recorded production sandbox baseline](https://github.com/t-k/fireemu/blob/v0.20.0/conformance/auth-action-production.json) does not include it; new production projects may also omit it. This default is a Fireemu-only convenience, and declaring the list replaces it. Tenant-scoped strict action links currently check the tenant's default domains rather than this project declaration; support for the parent project's live list is pending.
351
355
 
352
356
  An Admin update changes the live list. A session reset restores the declared list, when present, and preserves an Admin-written list when no initial list was declared. Projects created later receive the declaration word for word, independently of the default project's live list; listing a particular project's `firebaseapp.com` or `web.app` domain therefore gives later projects that same domain. Clearing accounts leaves the live list alone. Auth export/import carries accounts without the domain list or its declaration. The `emulator` profile accepts the setting and exposes the list, while continuing to allow action-link continue URLs outside it.
353
357
 
354
- Declare project OIDC and SAML resources with `auth.providers.oidc` and `auth.providers.saml`, using the Admin v2 resource fields and an ID-only `name` such as `oidc.fixture` or `saml.fixture`. Full resource names are refused. For example, `"providers": {"oidc": [{"name": "oidc.fixture", "enabled": true, "clientId": "local-client", "issuer": "https://issuer.test", "responseType": {"idToken": true}}]}` initializes that provider in both profiles. By default both profiles accept the fixture assertions the official emulator accepts (a JSON or unsigned ID token, a JSON SAML response, the sign-in widget), whether or not the provider is declared. With `auth.idpAssertions` set to `"signed"` (or `productionExact`, or `auth.idpSigners` present), strict OIDC sign-in needs matching public issuer keys in `auth.idpSigners`; no key is fetched. Strict SAML then uses the declared provider certificates and retains its existing assertion checks.
358
+ Declare project OIDC and SAML resources with `auth.providers.oidc` and `auth.providers.saml`, using the Admin v2 resource fields and an ID-only `name` such as `oidc.fixture` or `saml.fixture`. Full resource names are refused. For example, `"providers": {"oidc": [{"name": "oidc.fixture", "enabled": true, "clientId": "local-client", "issuer": "https://issuer.test", "responseType": {"idToken": true}}]}` initializes that provider in both profiles. By default both profiles accept the fixture assertions the official emulator accepts (a JSON or unsigned ID token, a JSON SAML response, the sign-in widget); the emulator profile accepts them whether or not the provider is declared, and the strict profile refuses an `oidc.*` or `saml.*` provider that is not declared (or is disabled), as production does. With `auth.idpAssertions` set to `"signed"` (or `productionExact`, or `auth.idpSigners` present), strict OIDC sign-in needs matching public issuer keys in `auth.idpSigners`; no key is fetched. Strict SAML then uses the declared provider certificates and retains its existing assertion checks.
355
359
 
356
360
  Each declared array replaces that provider kind; `[]` explicitly starts it empty, while an absent or `null` kind declares no initial resources. Admin operations change live resources until a session reset restores the declared kinds. Later session and routed projects inherit the declaration independently of the default project's live changes. Tenant resources and built-in providers remain separate. Clearing accounts preserves live resources; snapshots and Auth export/import transfer no provider resources or declarations. The emulator profile continues to accept its unsigned fixture credentials without requiring configured or enabled provider resources. These declarations require a canonical document with `"schemaVersion": 1`; a Firebase deployment `auth.providers` section without that version remains deployment data and installs no provider seeds.
357
361
 
@@ -416,7 +420,7 @@ These settings are separate from creating the project or tenant. Naming a tenant
416
420
 
417
421
  #### Enable multi-factor authentication at start
418
422
 
419
- Under the `strict` profile, TOTP is enabled only through the project's MFA configuration, as in production, so `auth.totp` alone enables nothing there. Use `auth.mfa` to declare that configuration in the file instead of calling the Admin API in every session. It has the shape Identity Platform uses (`state`, `enabledProviders`, and `providerConfigs` with `totpProviderConfig.adjacentIntervals`):
423
+ Under the `strict` profile, TOTP is enabled only through the project's MFA configuration, as in production, so `auth.totp` alone enables nothing there. By default that configuration is on (SMS and TOTP enabled), so a test needs nothing to enrol a second factor; `productionExact` starts a project with multi-factor off, as production does until it is enabled. Use `auth.mfa` to declare the configuration in the file instead of calling the Admin API in every session, to turn multi-factor off (`{"state": "DISABLED"}`), or to enable only what your production project does. It has the shape Identity Platform uses (`state`, `enabledProviders`, and `providerConfigs` with `totpProviderConfig.adjacentIntervals`):
420
424
 
421
425
  ```json
422
426
  {
@@ -434,14 +438,14 @@ Under the `strict` profile, TOTP is enabled only through the project's MFA confi
434
438
  ```
435
439
 
436
440
  - The configuration applies when the daemon starts, in both profiles, and to every project created afterward (not the default project's current value). It is validated as the Admin API validates an update of `mfa`, and a value production would refuse stops the daemon at startup.
437
- - Nothing else changes. An Admin API update replaces the current configuration, and disabling MFA refuses TOTP as production does. A tenant follows its own `mfaConfig`, not this setting.
438
- - `POST /v1/sessions/{session}/reset` returns the project to the declared configuration. Without `auth.mfa`, a reset leaves a configuration set through the Admin API alone, as it does the rest of the project configuration. `DELETE /emulator/v1/projects/{project}/accounts` clears accounts only.
441
+ - Nothing else changes. An Admin API update replaces the current configuration, and disabling MFA refuses TOTP as production does. A tenant follows its own `mfaConfig`, not this setting. The accepted TOTP window stays `auth.totp.windowSteps` unless the configuration sets `adjacentIntervals`.
442
+ - `POST /v1/sessions/{session}/reset` returns the project to the declared configuration, or to the default (SMS and TOTP enabled) when none is declared. Under `productionExact` without `auth.mfa`, a reset leaves a configuration set through the Admin API alone, as it does the rest of the project configuration. `DELETE /emulator/v1/projects/{project}/accounts` clears accounts only.
439
443
  - An export does not carry the project's `mfa` configuration, so an imported project keeps its own `auth.mfa` or Admin-set configuration.
440
- - The `emulator` profile keeps `auth.totp` working. Under `strict`, `auth.totp` without an `auth.mfa` that enables TOTP prints a startup warning naming `auth.mfa`.
444
+ - The `emulator` profile keeps `auth.totp` working. Under `strict`, `auth.totp` is enough by default; under `productionExact`, or with an `auth.mfa` that leaves TOTP off, it prints a startup warning naming `auth.mfa`.
441
445
 
442
446
  #### Enable multi-tenancy
443
447
 
444
- Under the `strict` profile, enable `multiTenant.allowTenants` before using multi-tenancy: through the Admin API, or with `auth.multiTenant` in the file (see "Start with tenants" below). See the [compatibility documentation](https://github.com/t-k/fireemu/blob/v0.19.0/docs/compatibility-contract.md) for the supported Admin API scope.
448
+ Multi-tenancy works by default under both profiles: a new project allows tenants, so the Admin API creates them and `auth.tenants` loads without `multiTenant.allowTenants`. `productionExact` (`strict` only) starts a project as production does, with the switch unset until it is enabled through the Admin API, or with `auth.multiTenant` in the file (see "Start with tenants" below). A declared `allowTenants: false` always turns it off. See the [compatibility documentation](https://github.com/t-k/fireemu/blob/v0.20.0/docs/compatibility-contract.md) for the supported Admin API scope.
445
449
 
446
450
  #### Start with tenants
447
451
 
@@ -467,7 +471,7 @@ Instead of creating tenants through the Admin API in every session, declare the
467
471
 
468
472
  - A document is read by the code the Admin tenant create route reads one with, so a value production refuses stops the daemon at startup. The tenants are created empty, in file order, and settings such as `mfaConfig` and `passwordPolicyConfig` come from the document. The file is stricter than the route in the `emulator` profile: it also refuses an unknown member and a missing or invalid `displayName`, as production does.
469
473
  - A declared tenant has what an Admin create with that document gives: an omitted `allowPasswordSignup`, `enableEmailLinkSignin` or `enableAnonymousUser` is off and multi-factor is off. A tenant the `emulator` profile creates on the way for a request that names an unknown id gets the official emulator's defaults instead (all three on, `PHONE_SMS` multi-factor), so declare what your test needs.
470
- - Under the `strict` profile tenants are created only in a project that allows them, as in production, so `auth.tenants` needs `auth.multiTenant.allowTenants: true` (the daemon refuses to start otherwise). The `emulator` profile takes tenants without the switch.
474
+ - Under the `strict` profile tenants are created only in a project that allows them, as in production. A new project allows them by default; with `productionExact`, or with `allowTenants: false` declared, `auth.tenants` needs `auth.multiTenant.allowTenants: true` (the daemon refuses to start otherwise). The `emulator` profile takes tenants without the switch.
471
475
  - The default project and every session project (`POST /v1/sessions`) start with the declared switch and tenants. `POST /v1/sessions/{session}/reset` (the default session's included) creates them again, empty, and returns the switch to the declared value; without these keys a reset leaves an Admin-set switch alone. A namespace the `emulator` profile creates for an unknown project id (as the official emulator does) starts with the declared switch and tenants too: it is created by the requests that already created one (a user, a provider or a project setting written there) and by a request that writes a tenant there (creating one, or naming one that does not exist yet), not by a read alone. A session created for that project id (`POST /v1/sessions`) replaces the namespace, tenants included, and starts with the declared ones.
472
476
  - With `--import`, an imported tenant is authoritative for its id, and a declared tenant the import did not carry is still created. If you keep re-importing your own export (`--import dir --export-on-exit dir`), an edit to a declared tenant is therefore ignored once its exported copy exists: the daemon prints a warning naming the tenant when the imported tenant's document differs from the declared one (every setting the file can declare is compared). The switch is the other way round: a declared `allowTenants` wins over the import. After a reset the declared version of a tenant comes back, not the imported one.
473
477
 
@@ -492,7 +496,9 @@ A schedule is driven by the virtual clock alone: real time passing runs nothing.
492
496
 
493
497
  A manual run (`POST /v1/sessions/{session}/functions/{name}:run`) enqueues one run of a scheduled function stamped with the current virtual time. It does not consume the next occurrence, which still comes due and is subject to `scheduler.overlap` like any run. It answers `400 INVALID_ARGUMENT` for an unknown function, a function that is not scheduled, an overlap policy refusal, or a runtime that is shutting down, and `429 RESOURCE_EXHAUSTED` when the event queue is full. This is fireemu's own control, not a claim about production's run-now.
494
498
 
495
- See the [configuration schema](https://github.com/t-k/fireemu/blob/v0.19.0/spec/config/fireemu.schema.json) for available settings and values.
499
+ On a task-queue function (`onTaskDispatched`), the same `POST /v1/sessions/{session}/functions/{name}:run` releases the Cloud Tasks that wait for their `scheduleTime`: all of them, or the one named by a `{"task": "<task id>"}` body (404 when no waiting task has that id). Under the strict profile a task enqueued with a `scheduleTime` waits for it, so this is how a test runs a task due in an hour without moving the clock; a released task still obeys the queue's rate and concurrency limits. The Functions page of the Emulator UI lists the waiting tasks with their due time and a **Run now** button.
500
+
501
+ See the [configuration schema](https://github.com/t-k/fireemu/blob/v0.20.0/spec/config/fireemu.schema.json) for available settings and values.
496
502
 
497
503
  ### Firestore history limits
498
504
 
@@ -570,7 +576,7 @@ Fireemu is compatible with the listed Local Emulator Suite products as shipped b
570
576
 
571
577
  The `strict` and `emulator` profiles differ in some behaviors to serve their respective purposes. Where the official emulator and production Firebase disagree, Fireemu also adopts production behavior in some cases and records the difference.
572
578
 
573
- Check support for the specific APIs and conditions your application uses, rather than relying on product names alone. The [compatibility contract](https://github.com/t-k/fireemu/blob/v0.19.0/spec/compatibility/contract.json) records scope and known differences. The [compatibility documentation](https://github.com/t-k/fireemu/blob/v0.19.0/docs/compatibility-contract.md) explains the verification process and how to interpret its records.
579
+ Check support for the specific APIs and conditions your application uses, rather than relying on product names alone. The [compatibility contract](https://github.com/t-k/fireemu/blob/v0.20.0/spec/compatibility/contract.json) records scope and known differences. The [compatibility documentation](https://github.com/t-k/fireemu/blob/v0.20.0/docs/compatibility-contract.md) explains the verification process and how to interpret its records.
574
580
 
575
581
  ### Network exposure of the Storage port
576
582
 
@@ -597,7 +603,7 @@ By default every listener is on loopback, which a published container port canno
597
603
 
598
604
  ### Changes between versions
599
605
 
600
- Configuration and behavior may change between releases. See the [CHANGELOG](https://github.com/t-k/fireemu/blob/v0.19.0/CHANGELOG.md) for release changes.
606
+ Configuration and behavior may change between releases. See the [CHANGELOG](https://github.com/t-k/fireemu/blob/v0.20.0/CHANGELOG.md) for release changes.
601
607
 
602
608
  ## Performance
603
609
 
@@ -614,7 +620,7 @@ The following results come from one `standard` run at commit `f3b942c`. Ratios a
614
620
 
615
621
  The 95% confidence interval for the startup-time ratio is `[21.4, 21.8]`. For the peak-memory ratio, calculated as official emulator divided by Fireemu, it is `[10.2, 11.1]`.
616
622
 
617
- See [benchmark.yml](https://github.com/t-k/fireemu/blob/v0.19.0/.github/workflows/benchmark.yml) for the workflow and [`tools/bench/`](https://github.com/t-k/fireemu/tree/v0.19.0/tools/bench/) for the benchmark implementation.
623
+ See [benchmark.yml](https://github.com/t-k/fireemu/blob/v0.20.0/.github/workflows/benchmark.yml) for the workflow and [`tools/bench/`](https://github.com/t-k/fireemu/tree/v0.20.0/tools/bench/) for the benchmark implementation.
618
624
 
619
625
  ## Reporting issues and contributing
620
626
 
@@ -622,8 +628,8 @@ When reporting an issue, include the Fireemu and Firebase SDK versions, the prof
622
628
 
623
629
  For compatibility issues, also state whether you are comparing against the actual Firebase service or the official emulator, along with the expected and actual results. Remove credentials and personal information before sharing configuration files or logs.
624
630
 
625
- See the [development guide](https://github.com/t-k/fireemu/blob/v0.19.0/docs/development.md) for build and test instructions.
631
+ See the [development guide](https://github.com/t-k/fireemu/blob/v0.20.0/docs/development.md) for build and test instructions.
626
632
 
627
633
  ## License
628
634
 
629
- Fireemu is licensed under the [Apache License 2.0](https://github.com/t-k/fireemu/blob/v0.19.0/LICENSE). Third-party notices are listed in [THIRD_PARTY_LICENSES.txt](https://github.com/t-k/fireemu/blob/v0.19.0/THIRD_PARTY_LICENSES.txt).
635
+ Fireemu is licensed under the [Apache License 2.0](https://github.com/t-k/fireemu/blob/v0.20.0/LICENSE). Third-party notices are listed in [THIRD_PARTY_LICENSES.txt](https://github.com/t-k/fireemu/blob/v0.20.0/THIRD_PARTY_LICENSES.txt).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fireemu",
3
- "version": "0.19.0",
3
+ "version": "0.20.0",
4
4
  "description": "A local runtime for testing Firebase SDK and Functions code, checked against production Firebase behavior",
5
5
  "keywords": [
6
6
  "emulator",
@@ -31,11 +31,11 @@
31
31
  ],
32
32
  "type": "module",
33
33
  "optionalDependencies": {
34
- "@fireemu/darwin-arm64": "0.19.0",
35
- "@fireemu/darwin-x64": "0.19.0",
36
- "@fireemu/linux-x64": "0.19.0",
37
- "@fireemu/linux-arm64": "0.19.0",
38
- "@fireemu/win32-x64": "0.19.0"
34
+ "@fireemu/darwin-arm64": "0.20.0",
35
+ "@fireemu/darwin-x64": "0.20.0",
36
+ "@fireemu/linux-x64": "0.20.0",
37
+ "@fireemu/linux-arm64": "0.20.0",
38
+ "@fireemu/win32-x64": "0.20.0"
39
39
  },
40
40
  "engines": {
41
41
  "node": ">=20"