Skip to content

Release: merge develop into main - #29

Merged
jhosepmyr merged 72 commits into
mainfrom
develop
Jul 10, 2026
Merged

jhosepmyr merged 72 commits into
mainfrom
develop

Conversation

@jhosepmyr

Copy link
Copy Markdown
Contributor

Summary

Merges develop into main, companion release to reqsai-api#71. Billing/Stripe UI code was already on main from an earlier merge — this release brings:

Test plan

  • CI (lint + test + build) green on this PR
  • After merging, confirm the deploy pipeline builds and the CloudFront distribution serves the new bundle
  • Smoke-test the Jira connect flow (Organization → Integrations) in production
  • Smoke-test the live session presence avatars in production
  • Confirm https://app.tamci.app loads and logs in cleanly after rollout

Eric396 and others added 30 commits July 6, 2026 23:57
Implement the Billing frontend consuming the backend Billing API (subscriptions,
token quota and Stripe payments):

- data/: BillingApiService (subscription / usage / upgrade / cancel / reactivate),
  BillingStore signal store, response/request models and a display plan catalog
  (limits + pricing) kept in sync with the backend PlanCatalog.
- Settings -> Billing page: current plan with status/renewal, a plan grid (Free/Pro/
  Enterprise) with upgrade, and cancel/reactivate. Immediate activation with the fake
  gateway; redirect to Stripe hosted checkout when the response requires it.
- Settings -> Usage page: AI token consumption vs. the plan allowance for the current
  period, with an amber/red progress bar.
- Checkout return landings (/billing/success, /billing/cancel) for the Stripe flow.
- Wire the routes, enable the previously "soon" Billing/Usage nav items, and add
  billing/usage i18n plus billing error-code messages (en + es).
Adds SessionParticipant and SessionPresenceMessage (PRESENCE_STATE) to
the session realtime union, mirroring the backend contract: a full
roster snapshot with a distinct participant count carried on the
existing per-session topic.
Handles PRESENCE_STATE on the existing per-session subscription and
exposes activeParticipants/activeParticipantCount for the live session
only (historical sessions show no roster). Presence is cleared on reset.
An overlapping avatar stack with a live pulse, a "+N" overflow bubble
and a viewer count, reusing the shared Avatar (image + monogram
fallback). New joiners animate in and names show as tooltips. Adds the
discovery.presence i18n keys (en/es).
Renders the active-participants roster in the discovery-chat header and
inside the live session bar, bound to the store's activeParticipants.
It appears only while a session is live and someone is present.
Verifies PRESENCE_STATE populates the roster for the live session,
presence for a non-live session is not surfaced, and reset clears it.
apiUrl was never actually read anywhere (HTTP calls use hardcoded
relative /api paths), but wsUrl is real and pointed at a domain that
doesn't exist. Both empty now: HTTP stays relative, and the WebSocket
client falls back to the current origin. CloudFront (reqsai-infra)
proxies /api/* and /ws/* to the backend under the same origin, so no
absolute URL is needed.
Bumps nginx from 1.27-alpine to 1.31-alpine.

---
updated-dependencies:
- dependency-name: nginx
  dependency-version: 1.31-alpine
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps node from 24-alpine to 26-alpine.

---
updated-dependencies:
- dependency-name: node
  dependency-version: 26-alpine
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps the actions group with 4 updates: [actions/checkout](https://github.com/actions/checkout), [actions/upload-artifact](https://github.com/actions/upload-artifact), [github/codeql-action](https://github.com/github/codeql-action) and [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials).


Updates `actions/checkout` from 6 to 7
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@v6...v7)

Updates `actions/upload-artifact` from 4 to 7
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v4...v7)

Updates `github/codeql-action` from 3 to 4
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@v3...v4)

Updates `aws-actions/configure-aws-credentials` from 4 to 6
- [Release notes](https://github.com/aws-actions/configure-aws-credentials/releases)
- [Changelog](https://github.com/aws-actions/configure-aws-credentials/blob/main/CHANGELOG.md)
- [Commits](aws-actions/configure-aws-credentials@v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: github/codeql-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: aws-actions/configure-aws-credentials
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [@spartan-ng/cli](https://github.com/spartan-ng/spartan) from 0.0.1-alpha.720 to 1.0.4.
- [Release notes](https://github.com/spartan-ng/spartan/releases)
- [Changelog](https://github.com/spartan-ng/spartan/blob/main/CHANGELOG.md)
- [Commits](https://github.com/spartan-ng/spartan/commits/v1.0.4)

---
updated-dependencies:
- dependency-name: "@spartan-ng/cli"
  dependency-version: 1.0.4
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Verifies the roster hides when empty, renders one avatar per
participant under the cap, collapses the rest into a "+N" bubble past
the cap, and exposes an accessible viewer-count label.
In the tighter session-bar layout the "{n} viewing" label could wrap
to two lines. whitespace-nowrap keeps it on a single line so the roster
stays visually balanced next to the timer and controls.
feat(billing): subscription, usage and plan management UI
…lop/actions-3aa25f1076

ci(deps): bump the actions group with 4 updates
…-26-alpine

ci(deps): bump node from 24-alpine to 26-alpine
…x-1.31-alpine

ci(deps): bump nginx from 1.27-alpine to 1.31-alpine
fix(shared): fix typos and double-encoding errors in translation files
apiUrl was never actually read anywhere (HTTP calls use hardcoded
relative /api paths), but wsUrl is real and pointed at a domain that
doesn't exist. Both empty now: HTTP stays relative, and the WebSocket
client falls back to the current origin. CloudFront (reqsai-infra)
proxies /api/* and /ws/* to the backend under the same origin, so no
absolute URL is needed.
fix: sync prod environment URL fix into develop
The session bar overflowed on small screens ("Recording  1:48  ||
Pause  [] Stop" is too wide to fit). The status text is now hidden
below sm: (the pulse color already conveys recording vs. paused) and
the Pause/Resume/Stop buttons collapse to icon-only, following the
same hidden/sm:inline pattern already used by the discovery header's
history/panel-toggle buttons. Adds aria-label/title so the icon-only
buttons stay accessible.
Verifies pause/stop keep an aria-label and title once their visible
text is hidden, the hidden/sm:inline classes are actually present on
the collapsing labels, the icon and timer always render, and the
resume button replaces pause once the session is paused.
The header and the session bar both rendered app-active-participants,
so anyone (owner included) saw the roster duplicated. The session bar
is the more contextual spot — it's the one place already scoped to
"a session is live" — so the header copy is removed.
The pill had asymmetric padding (pl-1.5 vs pr-2.5), crowding the green
live-pulse dot against the rounded edge. Matches the right padding.
app-session-bar only renders for users with record permission
(canRecord() && recording.isActive()); a plain member (or an owner
without that permission) falls into the else-branch banner instead,
which never included the roster. Moving it out of session-bar to the
page header — rendered unconditionally for every role — fixes the
regression where members lost the roster entirely after the previous
"remove duplicate" fix.
The avatar stack only ever names people via native title tooltips on
the visible avatars, which breaks down past the "+N" cap and doesn't
work at all on touch. Clicking (or, on desktop, hovering) the pill now
opens a CDK-overlay popover listing every participant with avatar +
name, scrollable past a handful of viewers. Closes on outside click,
Escape, or shortly after the pointer leaves (grace period so moving
from the trigger into the panel doesn't flicker-close it).
Verifies the panel is closed by default and click opens it listing
every participant (not just the ones collapsed into the avatar
stack), a second click closes it, hover opens it without a click, and
mouseleave closes it only after the grace-period delay.
jhosepmyr added 26 commits July 10, 2026 07:05
Org admins can now GET the organization, so the general settings page
loads for them but stays editable only by the owner. Non-owners see the
fields disabled, the per-field Save controls hidden, and an inline hint;
the owner flow is unchanged. Ownership is derived from the org ownerId vs
the authenticated user id.
The issue-type select is now disabled with a hint until a Jira project is
chosen, and its options are keyed by the unique issue-type id (deduped by
name) so it binds to the id and displays the name — avoiding duplicate
select keys (NG0955) when Jira returns types that share a name. The saved
target still stores the issue-type name, resolved from the selected id.
The GET target 404 stays handled silently as the unconfigured state.

Adds an optional disabled/disabledLabel input to the shared Select.
…ntegrations

Normalizes long template lines flagged by the formatter; no behavior change.
Adds an "Import from Jira" action on the backlog next to "Push all to
Jira". It previews the candidate Jira issues, opens a picker modal that
flags duplicates (already-mapped) with a badge and pre-selects only the
non-duplicates, then imports the chosen keys and toasts an
imported/skipped/failed summary before refreshing the list. An
unconfigured target points the user at project settings.

Adds the import models + IntegrationsApiService preview/import methods,
pure defaultImportSelection/summarizeImport helpers with unit tests, the
integrations.import.* strings (EN+ES) and the JIRA_IMPORT_FAILED error.
…ns service

Normalizes long lines flagged by the formatter; no behavior change.
…s configured

The backlog's 'Import from Jira' and 'Push all to Jira' buttons rendered enabled
even when the project had no Jira target and only failed on click; they now
resolve the target on load (the 404 is the expected not-configured answer) and
stay disabled with an explanatory tooltip until a mapping exists.
…ayer

Add deleteStory (DELETE .../stories/{id} -> 204) and batchDeleteStories
(POST .../stories/batch-delete -> { deleted }) to DiscoveryApiService, plus
the matching request/result models. Extend IntegrationsApiService.pushAllStories
to take an optional { storyIds } body so a selection can be pushed while the
no-arg call still pushes every eligible story. Covered by HttpTestingController
specs.
Add a per-page selection to the backlog table: a checkbox per row plus a
select-all/indeterminate header checkbox (reusing the Indeterminate directive).
Selection is a signal<ReadonlySet<string>> scoped to the visible page and cleared
on page/filter/sort change. When rows are selected a contextual action bar shows
the count, a clear button, 'Push to Jira (n)' (reuses the async job flow with an
optional storyIds body) and 'Delete (n)' (confirm modal -> batchDeleteStories ->
toast + reload). Adds a row-level trash action with a single-delete confirm modal.
Selection toggle/select-all/indeterminate logic lives in a pure, unit-tested
selection.helpers module.
A Delete button next to Push-to-Jira opens a confirm modal; on the 204 it toasts
and navigates back to the project backlog. Failures keep the page open with a
localized error toast.
feat(integrations): Jira integration UI — OAuth connect, project mapping & story push
CI failed at 'bun install --frozen-lockfile' because the grouped dependabot bump
(@angular/cdk 22.0.4, @playwright/test 1.61.1, typescript-eslint 8.63.0) updated
package.json but left bun.lock out of sync. Regenerated the lockfile; lint, the
189 Vitest tests and the production build all pass with the new versions.
…p/minor-and-patch-85c04f7892

build(deps): bump the minor-and-patch group across 1 directory with 3 updates
refactor(billing): refactor billing plan prices according to landing …
feature/billing-ui (subscription/usage/plan management, Stripe checkout
return landings) and bugfix/billing-prices had no CHANGELOG entry.
…leased

docs: document Stripe billing UI in CHANGELOG
@jhosepmyr
jhosepmyr merged commit fda64c6 into main Jul 10, 2026
5 checks passed
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.

2 participants