Skip to content

Sync dev with master#103

Merged
cleot merged 5 commits intodevfrom
master
Jan 12, 2026
Merged

Sync dev with master#103
cleot merged 5 commits intodevfrom
master

Conversation

@cleot
Copy link
Contributor

@cleot cleot commented Jan 12, 2026

Sync dev with master before merging dev again

codingpeanut157 and others added 5 commits November 24, 2025 09:23
it was mistakenly greied out all the times, now we have a new field in
InfoReply that informs us on the status of the minting.
Bumps the all-github-actions group with 3 updates: [actions/checkout](https://github.com/actions/checkout), [actions/setup-node](https://github.com/actions/setup-node) and [docker/metadata-action](https://github.com/docker/metadata-action).


Updates `actions/checkout` from 4.2.2 to 6.0.0
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@v4.2.2...1af3b93)

Updates `actions/setup-node` from 4.4.0 to 6.0.0
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](actions/setup-node@v4.4.0...2028fbc)

Updates `docker/metadata-action` from 5.9.0 to 5.10.0
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](docker/metadata-action@318604b...c299e40)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: all-github-actions
- dependency-name: actions/setup-node
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: all-github-actions
- dependency-name: docker/metadata-action
  dependency-version: 5.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the all-github-actions group with 4 updates: [actions/checkout](https://github.com/actions/checkout), [actions/setup-node](https://github.com/actions/setup-node), [codecov/codecov-action](https://github.com/codecov/codecov-action) and [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action).


Updates `actions/checkout` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@1af3b93...8e8c483)

Updates `actions/setup-node` from 6.0.0 to 6.1.0
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](actions/setup-node@2028fbc...395ad32)

Updates `codecov/codecov-action` from 5.5.1 to 5.5.2
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@5a10915...671740a)

Updates `docker/setup-buildx-action` from 3.11.1 to 3.12.0
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](docker/setup-buildx-action@e468171...8d2750c)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-github-actions
- dependency-name: actions/setup-node
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-github-actions
- dependency-name: codecov/codecov-action
  dependency-version: 5.5.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-github-actions
- dependency-name: docker/setup-buildx-action
  dependency-version: 3.12.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@qodo-code-review
Copy link

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Token exfil via env

Description: Runtime environment overrides are sourced from the global window.ENV (populated by
/config.js) and then used to set security-critical endpoints (e.g., env.apiBaseUrl,
env.keycloakUrl), so if an attacker can tamper with config.js delivery or inject/overwrite
window.ENV, they can redirect API/Keycloak traffic to attacker-controlled hosts and
potentially exfiltrate bearer tokens via the API client's auth interceptor.
env.ts [10-33]

Referred Code
const runtimeEnv: RuntimeEnv =
  typeof window !== "undefined" ? (window as { __ENV__?: RuntimeEnv }).__ENV__ ?? {} : {}

const fallbackEnv = import.meta.env as ImportMetaEnv & RuntimeEnv

const getEnvValue = <K extends keyof RuntimeEnv>(key: K): RuntimeEnv[K] | undefined => {
  const value = runtimeEnv[key]

  if (value !== undefined && value !== null && value !== "") {
    return value
  }

  return fallbackEnv[key]
}

export const env = {
  devModeEnabled: fallbackEnv.DEV,
  apiBaseUrl: getEnvValue("VITE_API_BASE_URL")!,
  apiMocksEnabled: (getEnvValue("VITE_API_MOCKING_ENABLED") ?? "false") === "true",
  keycloakUrl: getEnvValue("VITE_KEYCLOAK_URL")!,
  keycloakRealm: getEnvValue("VITE_KEYCLOAK_REALM")!,


 ... (clipped 3 lines)
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status:
Inverted boolean usage: The boolean mintingEnabled is used with inverted UI semantics (showing
"Disabled" when mintingEnabled is true), making the code misleading and not
self-documenting.

Referred Code
const mintingEnabled = value.status === "Accepted" && value.minting_status.status === "Enabled"

return (
  <div className="flex flex-col gap-1">
    <Table className="my-2">
      <TableBody>
        <TableRow>
          <TableCell className="font-bold">Quote ID: </TableCell>
          <TableCell>
            <span className="font-mono">{value.id}</span>
          </TableCell>
        </TableRow>
        <TableRow>
          <TableCell className="font-bold">Bill ID: </TableCell>
          <TableCell>
            <span className="font-mono">{value.bill.id}</span>
          </TableCell>
        </TableRow>
        {(value.status === "Offered" || value.status === "Accepted") && "keyset_id" in value ? (
          <TableRow>
            <TableCell className="font-bold">Keyset ID: </TableCell>


 ... (clipped 14 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Missing env validation: Required environment values are asserted with non-null (!) without explicit validation or
contextual error handling, which can cause opaque runtime crashes when values are missing.

Referred Code
export const env = {
  devModeEnabled: fallbackEnv.DEV,
  apiBaseUrl: getEnvValue("VITE_API_BASE_URL")!,
  apiMocksEnabled: (getEnvValue("VITE_API_MOCKING_ENABLED") ?? "false") === "true",
  keycloakUrl: getEnvValue("VITE_KEYCLOAK_URL")!,
  keycloakRealm: getEnvValue("VITE_KEYCLOAK_REALM")!,
  keycloakClientId: getEnvValue("VITE_KEYCLOAK_CLIENT_ID")!,
  crowdinInContextToolingEnabled:
    (getEnvValue("VITE_BITCR_DEV_INCLUDE_CROWDIN_IN_CONTEXT_TOOLING") ?? "false") === "true",

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Unvalidated runtime config: Values sourced from window.ENV (runtime-injected external input) are consumed without
validation/allowlisting (e.g., URL format, expected enums), which may be acceptable
depending on deployment hardening but cannot be verified from the diff alone.

Referred Code
const runtimeEnv: RuntimeEnv =
  typeof window !== "undefined" ? (window as { __ENV__?: RuntimeEnv }).__ENV__ ?? {} : {}

const fallbackEnv = import.meta.env as ImportMetaEnv & RuntimeEnv

const getEnvValue = <K extends keyof RuntimeEnv>(key: K): RuntimeEnv[K] | undefined => {
  const value = runtimeEnv[key]

  if (value !== undefined && value !== null && value !== "") {
    return value
  }

  return fallbackEnv[key]
}

export const env = {
  devModeEnabled: fallbackEnv.DEV,
  apiBaseUrl: getEnvValue("VITE_API_BASE_URL")!,
  apiMocksEnabled: (getEnvValue("VITE_API_MOCKING_ENABLED") ?? "false") === "true",
  keycloakUrl: getEnvValue("VITE_KEYCLOAK_URL")!,
  keycloakRealm: getEnvValue("VITE_KEYCLOAK_REALM")!,


 ... (clipped 3 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@codecov
Copy link

codecov bot commented Jan 12, 2026

Codecov Report

❌ Patch coverage is 50.00000% with 20 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/pages/quotes/QuotePage.tsx 0.00% 8 Missing ⚠️
src/constants/meta.ts 0.00% 5 Missing ⚠️
src/keycloak.tsx 0.00% 4 Missing ⚠️
src/lib/api-client.ts 0.00% 2 Missing ⚠️
public/config.js 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@qodo-code-review
Copy link

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix badge label inversion

Invert the label and class names for the Badge component to correctly reflect
the mintingEnabled state.

src/pages/quotes/QuotePage.tsx [738-743]

 <Badge
   variant={mintingEnabled ? "default" : "destructive"}
-  className={mintingEnabled ? "bg-red-500" : "bg-blue-500"}
+  className={mintingEnabled ? "bg-blue-500" : "bg-red-500"}
 >
-  {mintingEnabled ? "Disabled" : "Enabled"}
+  {mintingEnabled ? "Enabled" : "Disabled"}
 </Badge>
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why: The suggestion correctly identifies and fixes an inverted logic in the UI badge, which currently displays "Disabled" and a red color when minting is enabled, and vice-versa.

Low
General
Add missing env var default

Add the missing VITE_BITCR_DEV_INCLUDE_CROWDIN_IN_CONTEXT_TOOLING variable to
the .env.example file for completeness.

.env.example [10-11]

 VITE_KEYCLOAK_CLIENT_ID=bff-dashboard
 VITE_API_MOCKING_ENABLED=false
+VITE_BITCR_DEV_INCLUDE_CROWDIN_IN_CONTEXT_TOOLING=false
  • Apply / Chat
Suggestion importance[1-10]: 5

__

Why: The suggestion correctly points out that a newly used environment variable VITE_BITCR_DEV_INCLUDE_CROWDIN_IN_CONTEXT_TOOLING is missing from the .env.example file, which improves developer experience.

Low
  • More

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR synchronizes the dev branch with master, introducing a runtime environment configuration system and updating the quote minting status tracking logic. The changes enable environment variables to be injected at runtime via Docker rather than at build time, improving deployment flexibility.

Changes:

  • Refactored environment variable handling to support runtime configuration via window.__ENV__
  • Updated quote page to use API-provided minting status instead of derived keyset state
  • Added GitHub Actions workflows for CI, nightly builds, and releases
  • Updated GitHub Actions dependencies to newer versions

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/lib/env.ts New runtime environment configuration module with fallback to build-time values
src/lib/env.test.ts Comprehensive tests for runtime environment resolution
src/lib/api-client.ts Updated to use new env module instead of import.meta.env
src/keycloak.tsx Updated to use new env module instead of import.meta.env
src/constants/meta.ts Updated to use new env module instead of import.meta.env
src/pages/quotes/QuotePage.tsx Renamed newKeyset to mintingEnabled and changed logic to use API minting_status field
src/generated/client/types.gen.ts Added MintingStatus type and minting_status field to Accepted quote variant
public/config.js Runtime configuration initialization script
index.html Added config.js script tag before main application
docker/entrypoint.d/00-env-config.sh Script to inject environment variables into config.js at container startup
docker/nginx/templates/default.conf.template Added no-cache directive for config.js
Dockerfile Added jq dependency and entrypoint script setup
docker-compose.yml Added missing environment variables
.github/workflows/ci.yml New CI workflow replacing build.yml
.github/workflows/nightly.yml New nightly build workflow
.github/workflows/release.yml New release workflow for tagged versions
.github/workflows/deploy.yml Updated action versions
.github/workflows/build.yml Removed (replaced by ci.yml)
.github/dependabot.yml New Dependabot configuration for GitHub Actions
.env.example Added VITE_API_MOCKING_ENABLED variable
src/main.tsx Exported App component

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

)}

{value.status === "Accepted" && "keyset_id" in value && !ebillPaid && !newKeyset && !requestedToPay ? (
{value.status === "Accepted" && "keyset_id" in value && !ebillPaid && !requestedToPay ? (
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition for showing the "Request to Pay" button was simplified by removing the !newKeyset check (previously !mintingEnabled after the rename). However, this changes the business logic.

The old logic required:

  • Status is "Accepted"
  • Has keyset_id
  • E-bill not paid
  • NOT a new keyset (meaning keyset exists and has active status)
  • Not already requested to pay

The new logic only requires:

  • Status is "Accepted"
  • Has keyset_id
  • E-bill not paid
  • Not already requested to pay

This means the "Request to Pay" button will now appear even when the keyset doesn't exist or doesn't have active status. Verify this is the intended behavior change.

Suggested change
{value.status === "Accepted" && "keyset_id" in value && !ebillPaid && !requestedToPay ? (
{value.status === "Accepted" && "keyset_id" in value && mintingEnabled && !ebillPaid && !requestedToPay ? (

Copilot uses AI. Check for mistakes.
Comment on lines +25 to +31
export const env = {
devModeEnabled: fallbackEnv.DEV,
apiBaseUrl: getEnvValue("VITE_API_BASE_URL")!,
apiMocksEnabled: (getEnvValue("VITE_API_MOCKING_ENABLED") ?? "false") === "true",
keycloakUrl: getEnvValue("VITE_KEYCLOAK_URL")!,
keycloakRealm: getEnvValue("VITE_KEYCLOAK_REALM")!,
keycloakClientId: getEnvValue("VITE_KEYCLOAK_CLIENT_ID")!,
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The non-null assertions (!) on lines 27, 29, 30, and 31 can lead to runtime errors if the required environment variables are not provided. If getEnvValue returns undefined, the non-null assertion will suppress TypeScript's safety checks but won't prevent undefined values at runtime.

Consider adding explicit validation with helpful error messages:

const apiBaseUrl = getEnvValue("VITE_API_BASE_URL")
if (!apiBaseUrl) throw new Error("VITE_API_BASE_URL is required")

Or create a helper function to get required env values that throws descriptive errors.

Suggested change
export const env = {
devModeEnabled: fallbackEnv.DEV,
apiBaseUrl: getEnvValue("VITE_API_BASE_URL")!,
apiMocksEnabled: (getEnvValue("VITE_API_MOCKING_ENABLED") ?? "false") === "true",
keycloakUrl: getEnvValue("VITE_KEYCLOAK_URL")!,
keycloakRealm: getEnvValue("VITE_KEYCLOAK_REALM")!,
keycloakClientId: getEnvValue("VITE_KEYCLOAK_CLIENT_ID")!,
const getRequiredEnvValue = <K extends keyof RuntimeEnv>(key: K): RuntimeEnv[K] => {
const value = getEnvValue(key)
if (value === undefined || value === null || value === "") {
throw new Error(`Missing required environment variable: ${String(key)}`)
}
return value
}
export const env = {
devModeEnabled: fallbackEnv.DEV,
apiBaseUrl: getRequiredEnvValue("VITE_API_BASE_URL"),
apiMocksEnabled: (getEnvValue("VITE_API_MOCKING_ENABLED") ?? "false") === "true",
keycloakUrl: getRequiredEnvValue("VITE_KEYCLOAK_URL"),
keycloakRealm: getRequiredEnvValue("VITE_KEYCLOAK_REALM"),
keycloakClientId: getRequiredEnvValue("VITE_KEYCLOAK_CLIENT_ID"),

Copilot uses AI. Check for mistakes.
run: npm run test -- --coverage

- name: Build
run: npm run build
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CI workflow's build step (line 38) runs npm run build but doesn't set any of the required VITE_* environment variables. Since the code now requires these variables at build time (via import.meta.env), and the new env.ts module uses non-null assertions on critical values, the build will likely fail or produce a broken application.

The workflow should set the necessary environment variables before the build step, even if they're just placeholder values for CI purposes:

- name: Build
  run: npm run build
  env:
    VITE_API_BASE_URL: "http://localhost"
    VITE_KEYCLOAK_URL: "http://localhost"
    VITE_KEYCLOAK_REALM: "test"
    VITE_KEYCLOAK_CLIENT_ID: "test"
Suggested change
run: npm run build
run: npm run build
env:
VITE_API_BASE_URL: "http://localhost"
VITE_KEYCLOAK_URL: "http://localhost"
VITE_KEYCLOAK_REALM: "test"
VITE_KEYCLOAK_CLIENT_ID: "test"

Copilot uses AI. Check for mistakes.
Comment on lines 738 to +742
<Badge
variant={newKeyset ? "default" : "destructive"}
className={newKeyset ? "bg-red-500" : "bg-blue-500"}
variant={mintingEnabled ? "default" : "destructive"}
className={mintingEnabled ? "bg-red-500" : "bg-blue-500"}
>
{newKeyset ? "Disabled" : "Enabled"}
{mintingEnabled ? "Disabled" : "Enabled"}
Copy link

Copilot AI Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The badge display logic is inverted. The variable mintingEnabled is true when minting status is "Enabled" (based on the API data), but the badge displays "Disabled" when mintingEnabled is true. This should be:

{mintingEnabled ? "Enabled" : "Disabled"}

Additionally, the color classes appear backwards - when minting is enabled (true), it shows red (bg-red-500) which typically indicates a problem state, but when disabled (false) it shows blue (bg-blue-500). The colors should likely be swapped or reconsidered.

Copilot uses AI. Check for mistakes.
@cleot cleot merged commit b19f3d7 into dev Jan 12, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants