Skip to content

Release: main → prod (2026-07-07) - #1530

Merged
rlho merged 76 commits into
prodfrom
main
Jul 8, 2026
Merged

rlho merged 76 commits into
prodfrom
main

Conversation

@rlho

@rlho rlho commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Summary of Changes

Production release: merge main into prod. This aggregates ~1 month of changes (since the last prod release, #1493 on 2026-06-04). All commits were already reviewed and merged into main.

Notable changes included:

Schema Changes

Checklist

Release PR aggregating changes already reviewed, tested, and merged into main. Per-change testing/screenshots live on the individual linked PRs.

  • I linked relevant issue(s) in the Development section
  • I checked for existing implementations and confirmed there is no duplication
  • I thoroughly tested this feature locally
  • I added or updated unit tests (or explained why not in the PR description)
  • I attached screenshots or a video demonstrating the feature (or explained why not in the PR description)
  • I incorporated Copilot's feedback (or explained why not in the PR description), and marked conversations as resolved
  • I confirmed my PR passed all unit and end-to-end (E2E) tests
  • I confirmed there are no conflicts (git diff main...prod is empty; main is a superset of prod)
  • I requested a code review from at least one other teammate

Screenshots / Video

N/A — release PR. Individual changes carry their own screenshots on the linked PRs.

pearmini and others added 30 commits April 28, 2026 12:12
Introduce backupTenantSchemaToDisk.ts and npm run backup:tenant-schema.
Default run copies tenantSchema documents into tenantSchemaBackup using
the shared tenantSchemaBackup helpers; --dry-run writes JSON under
scripts/output only. Extend createBackupDocId with an optional shared
timestamp for batched disk exports. Document usage in docs/TENANT_SCHEMA_BACKUP.md
and link from SCHEMA_SYNC_GUIDE and scripts/README.

Co-authored-by: Cursor <cursoragent@cursor.com>
`enforceRequestLimits` previously fetched every booking for the user's
email and filtered the time window in memory. For heavy users that's
O(N) reads per booking attempt, plus an `in` query on bookingLogs for
every requestNumber returned. On App Engine F1 this dominates the
per-request Firestore cost and adds to instance memory pressure.

Pre-compute the windows for every configured period, take the earliest
start, and add `requestedAt >= earliestStart` to the Firestore query so
only the bookings that can possibly matter come back. The per-period
in-memory aggregation now reuses these windows instead of recomputing
them.

Requires a new composite index `(email ASC, requestedAt ASC)` on each
tenant's bookings collection; added to firestore.indexes.json for
mc-bookings and itp-bookings. NOTE: deploy the indexes
(`firebase deploy --only firestore:indexes`) before this change reaches
production — without the index the bounded query throws and the
existing fail-open try/catch silently disables enforcement.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts:
#	booking-app/firestore.indexes.json
Asserts that when the request-limits endpoint returns 429 the
BookingStatusBar shows the server's error message and the Next button
is disabled. This is the only UI-level guard against shipping a regression
that silently disables enforcement.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts:
#	booking-app/components/src/client/routes/components/SchemaProvider.tsx
#	booking-app/package.json
#	booking-app/tests/unit/schema-completeness.unit.test.ts
The tenant schema migration changed top-level `tenant` from a string slug
to a TenantBranding object. `useCheckRequestLimits` still keyed its
"schema loaded" guard and effect dependency on `schema.tenant`, which is
now always a truthy object compared by identity. Switch to `schema.tenantId`
(the new string slug) so the guard works again and the effect dependency is
a stable primitive.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…mmit

migrateTenantSchemaFirestore.ts and coerce-tenant-schema-migration.unit.test.ts
come from main's tenant-schema migration and must be kept in this merge. They
were unintentionally removed in the previous commit; restore them verbatim from
origin/main.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…1238)

All tenant docs (prod/staging/default, mc + itp) are stored in the canonical
nested shape now that the Phase 2 migration has been applied, so the read-time
backward-compat layer is no longer needed.

- coerceTenantSchema: drop the legacy flat-schema branch and the
  partial-migration shims (mapLegacyEmailMessages, agreements -> attestations
  fallback, legacy resource training mapping, top-level
  timeSensitiveRequestWarning pickup). It is now a new-shape merge over the
  tenant defaults (~388 -> ~70 lines).
- Delete the one-off migration tooling it has already run:
  scripts/migrateTenantSchemaFirestore.ts, its detection helpers
  (tenantSchemaFirestoreDocNeedsShapeMigration / isNestedTenantSchemaDocument /
  STALE_LEGACY_* / isNewSchemaShape), and the migrate:tenant-schema[:dry-run]
  npm scripts.
- Remove deprecated type aliases Agreement / PermissionLabels and the
  defaultAgreement const (Attestation / ContextLabels / defaultAttestation are
  the canonical names).
- Update unit tests that ran legacy-shaped fixtures through coerce to use the
  nested shape; delete the migration-detection unit test.

Satisfies the #1238 goal of removing the legacy field names from code.
type-check clean; unit suite green.
The deploy workflows created Firestore composite indexes from a hard-coded
list duplicated across all three environment files. That list also omitted
the (email, requestedAt) index that the request-limits feature (#1403)
requires, so request-limit queries failed with FAILED_PRECONDITION and the
fail-open enforcement silently allowed bookings through.

Make firestore.indexes.json the single source of truth and add
scripts/deploy-firestore-indexes.sh, which reads that file and runs
'gcloud firestore indexes composite create' for each index against the
environment's database. Each workflow's 'Deploy Firestore indexes' step now
just invokes the script with its database id. Adding/changing an index is now
a one-line edit to firestore.indexes.json with no workflow changes.

The (email, requestedAt) index is already present in firestore.indexes.json
(added in #1403), so this also provisions it. We keep gcloud rather than
'firebase deploy --only firestore:indexes' because firebase-tools 15.x throws
on the multi-database firestore array in firebase.json.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
refactor(schema): remove legacy tenantSchema compat code (Phase 3 of #1238)
ci(firestore): drive index deploy from firestore.indexes.json (single source)
Bumps the npm_and_yarn group with 1 update in the /booking-app directory: [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `vitest` from 3.2.4 to 3.2.6
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v3.2.6/packages/vitest)

---
updated-dependencies:
- dependency-name: vitest
  dependency-version: 3.2.6
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>

This branch was previously deployed

3 inactive deployments
staging — 6c16c054 Deployed Jul 9, 2026 by rlho via trigger-auto-cancel-declined (staging) #3778
production — 6c16c054 Deployed Jul 9, 2026 by rlho via trigger-auto-cancel-declined (production) #3778
dev — 6c16c054 Deployed Jul 6, 2026 by rlho via deploy #728
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants