You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
v5.0.195: Fix 24-hour cancel guard comparing ms to seconds timestamp
The 24-hour cancellation guard in payments/cancel/post.js was silently broken — it subtracted a UNIX seconds timestamp from Date.now() (milliseconds), producing an "age" of ~56 years for every subscription. The guard never fired, allowing users to cancel brand-new subscriptions. Fixed by multiplying startDateUNIX by 1000 before the subtraction. Also updated CLAUDE.md and README.md to use `npx mgr` consistently instead of the deprecated `npx bm` alias, and added notes to TODO-2.md.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+6Lines changed: 6 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,6 +14,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
14
14
-`Fixed` for any bug fixes.
15
15
-`Security` in case of vulnerabilities.
16
16
17
+
# [5.0.195] - 2026-04-10
18
+
### Fixed
19
+
- 24-hour cancellation guard in `payments/cancel` was comparing `Date.now()` (milliseconds) against `startDateUNIX` (seconds), producing an "age" of ~56 years for every subscription — guard never fired and users could cancel brand-new subscriptions. Now multiplies `startDateUNIX` by 1000 before subtraction.
20
+
### Changed
21
+
- Standardized CLI examples in `CLAUDE.md` and `README.md` to use `npx mgr` instead of the deprecated `npx bm` alias
22
+
17
23
# [5.0.194] - 2026-04-08
18
24
### Fixed
19
25
- Fix email template data merge: caller's `settings.data` is now deep-merged at root of template data tree, removing the broken `data.` prefix indirection that caused empty order confirmation emails since 5.0.185
- **`functions/test.log`** — Test runner output (when running against an existing emulator)
615
-
- **`functions/logs.log`** — Cloud Function logs from `npx bm logs:read` or `npx bm logs:tail` (raw JSON for `read`, streaming text for `tail`)
615
+
- **`functions/logs.log`** — Cloud Function logs from `npx mgr logs:read` or `npx mgr logs:tail` (raw JSON for `read`, streaming text for `tail`)
616
616
617
-
When `npx bm test` starts its own emulator, logs go to `emulator.log` (since it delegates to the emulator command). When running against an already-running emulator, logs go to `test.log`.
617
+
When `npx mgr test` starts its own emulator, logs go to `emulator.log` (since it delegates to the emulator command). When running against an already-running emulator, logs go to `test.log`.
618
618
619
619
These files are overwritten on each run and are gitignored (`*.log`). Use them to search for errors, debug webhook pipelines, or review full function output after a test run.
620
620
621
621
### Filtering Tests
622
622
```bash
623
-
npx bm test rules/ # Run rules tests (both BEM and project)
624
-
npx bm test bem:rules/ # Only BEM's rules tests
625
-
npx bm test project:rules/ # Only project's rules tests
626
-
npx bm test user/ admin/ # Multiple paths
623
+
npx mgr test rules/ # Run rules tests (both BEM and project)
624
+
npx mgr test bem:rules/ # Only BEM's rules tests
625
+
npx mgr test project:rules/ # Only project's rules tests
BEM auto-starts Stripe CLI webhook forwarding when running `npx bm serve` or `npx bm emulator`. This forwards Stripe test webhooks to the local server so the full payment pipeline works end-to-end during development.
719
+
BEM auto-starts Stripe CLI webhook forwarding when running `npx mgr serve` or `npx mgr emulator`. This forwards Stripe test webhooks to the local server so the full payment pipeline works end-to-end during development.
720
720
721
721
**Requirements:**
722
722
- `STRIPE_SECRET_KEY` set in `functions/.env`
@@ -725,7 +725,7 @@ BEM auto-starts Stripe CLI webhook forwarding when running `npx bm serve` or `np
725
725
726
726
**Standalone usage:**
727
727
```bash
728
-
npx bm stripe
728
+
npx mgr stripe
729
729
```
730
730
731
731
If any prerequisite is missing, webhook forwarding is silently skipped with an info message.
@@ -736,50 +736,50 @@ The forwarding URL is: `http://localhost:{hostingPort}/backend-manager/payments/
736
736
737
737
Quick commands for reading/writing Firestore and managing Auth users directly from the terminal. Works in any BEM consumer project (requires `functions/service-account.json` for production, or `--emulator` for local).
738
738
739
-
**IMPORTANT: All CLI commands (`npx mgr ...` / `npx bm ...`) MUST be run from the consumer project's `functions/` subdirectory** (e.g., `cd /path/to/my-project/functions && npx mgr ...`). The`mgr` binary lives in`functions/node_modules/.bin/` — running from the project root or any other directory will fail.
739
+
**IMPORTANT: All CLI commands (`npx mgr ...`) MUST be run from the consumer project's `functions/` subdirectory** (e.g., `cd /path/to/my-project/functions && npx mgr ...`). The`mgr` binary lives in`functions/node_modules/.bin/` — running from the project root or any other directory will fail.
740
740
741
741
### Firestore Commands
742
742
743
743
```bash
744
-
npx bm firestore:get <path> # Read a document
745
-
npx bm firestore:set <path> '<json>' # Write/merge a document
npx mgr auth:delete <uid-or-email> # Delete user (prompts for confirmation)
760
+
npx mgr auth:set-claims <uid-or-email> '<json>' # Set custom claims
761
761
```
762
762
763
763
### Logs Commands
764
764
765
765
Fetch or stream Cloud Function logs from Google Cloud Logging. Requires`gcloud`CLI installed and authenticated. Auto-resolves the project ID from `service-account.json`, `.firebaserc`, or `GCLOUD_PROJECT`.
766
766
767
767
```bash
768
-
npx bm logs:read # Read last 1h of logs (default: 300 entries, newest first)
769
-
npx bm logs:read --fn bm_api # Filter by function name
npx mgr logs:read --filter 'jsonPayload.level="error"' # Raw gcloud filter passthrough
776
+
npx mgr logs:tail # Stream live logs
777
+
npx mgr logs:tail --fn bm_paymentsWebhookOnWrite # Stream filtered live logs
778
778
```
779
779
780
780
Both commands save output to `functions/logs.log` (overwritten on each run). `logs:read` saves raw JSON; `logs:tail` streams text.
781
781
782
-
**Cloud Logs vs Local Logs:** These commands query **production** Google Cloud Logging. For**local/dev** logs, read `functions/serve.log` (from `npx bm serve`) or `functions/emulator.log` (from `npx bm test`) directly — they are plain text files, not gcloud.
782
+
**Cloud Logs vs Local Logs:** These commands query **production** Google Cloud Logging. For**local/dev** logs, read `functions/serve.log` (from `npx mgr serve`) or `functions/emulator.log` (from `npx mgr test`) directly — they are plain text files, not gcloud.
783
783
784
784
| Flag | Description | Default | Commands |
785
785
|------|-------------|---------|----------|
@@ -834,22 +834,22 @@ The `--fn` flag uses the **deployed Cloud Function name**, not the route path.
@@ -1366,7 +1366,7 @@ Campaigns reference segments by SSOT key: `segments: ['subscription_free']`. Aut
1366
1366
1367
1367
### Seed Campaigns
1368
1368
1369
-
Created by `npx bm setup` (idempotent, enforced fields checked every run):
1369
+
Created by `npx mgr setup` (idempotent, enforced fields checked every run):
1370
1370
1371
1371
| ID | Type | Description |
1372
1372
|----|------|-------------|
@@ -1419,7 +1419,7 @@ marketing: {
1419
1419
1420
1420
8. **Increment usage before update** - Call `usage.increment()` then `usage.update()`
1421
1421
1422
-
9. **Add Firestore composite indexes for new compound queries** - Any new Firestore query using multiple `.where()` clauses or `.where()` + `.orderBy()` requires a composite index. Add it to `src/cli/commands/setup-tests/helpers/required-indexes.js` (the SSOT). Consumer projects pick these up via `npx bm setup`, which syncs them into `firestore.indexes.json`. Without the index, the query will crash with `FAILED_PRECONDITION` in production.
1422
+
9. **Add Firestore composite indexes for new compound queries** - Any new Firestore query using multiple `.where()` clauses or `.where()` + `.orderBy()` requires a composite index. Add it to `src/cli/commands/setup-tests/helpers/required-indexes.js` (the SSOT). Consumer projects pick these up via `npx mgr setup`, which syncs them into `firestore.indexes.json`. Without the index, the query will crash with `FAILED_PRECONDITION` in production.
1423
1423
1424
1424
## Key Files Reference
1425
1425
@@ -1463,7 +1463,7 @@ marketing: {
1463
1463
```javascript
1464
1464
assistant.isDevelopment() // true when ENVIRONMENT !== 'production' or in emulator
1465
1465
assistant.isProduction() // true when ENVIRONMENT === 'production'
1466
-
assistant.isTesting() // true when running tests (via npx bm test)
1466
+
assistant.isTesting() // true when running tests (via npx mgr test)
1467
1467
```
1468
1468
1469
1469
## Model Context Protocol (MCP)
@@ -1473,7 +1473,7 @@ BEM includes a built-in MCP server that exposes BEM routes as tools for Claude C
1473
1473
### Architecture
1474
1474
1475
1475
Two transport modes:
1476
-
- **Stdio** (local): `npx bm mcp` — for Claude Code / Claude Desktop
1476
+
- **Stdio** (local): `npx mgr mcp` — for Claude Code / Claude Desktop
1477
1477
- **Streamable HTTP** (remote): `POST/backend-manager/mcp` — for Claude Chat (stateless, Firebase Functions compatible)
1478
1478
1479
1479
### Available Tools (19)
@@ -1507,7 +1507,7 @@ Two transport modes:
1507
1507
1508
1508
### Hosting Rewrites
1509
1509
1510
-
The `npx bm setup` command automatically adds required Firebase Hosting rewrites for MCP OAuth:
1510
+
The `npx mgr setup` command automatically adds required Firebase Hosting rewrites for MCP OAuth:
Copy file name to clipboardExpand all lines: TODO-2.md
+39Lines changed: 39 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,10 +10,49 @@ payments/reactivate
10
10
payments/upgrade
11
11
* takes a subscription id and a new plan id and upgrades the user's subscription to the new plan. this can only be done if the user has an active subscription.
12
12
13
+
I'd call that cancellation-reversed — it pairs naturally with the existing cancellation-requested transition and clearly communicates the action (they reversed/undid the pending cancellation).
14
+
15
+
on the email we send, for payment recovered what is the category
16
+
Let me check the handler.
17
+
18
+
Read payment-recovered.js
19
+
The category is order/payment-recovered (line 13).
20
+
21
+
TODO-2.md
22
+
waht about when they request a cancel
23
+
Read cancellation-requested.js
24
+
The category is order/cancellation-requested (line 13).
25
+
26
+
----
27
+
add a dedicated BEM JSON field for usage to reset
28
+
* this way we can have clear LIMITS with their definitions like
0 commit comments