release_notes.py — sort repos by most-recently-updated first (based on latest CHANGELOG entry date) instead of hardcoded order
Show 14 older versions
v1.3.132026-03-20
Fixed
entrypoint.sh — fix SWA deploy failure caused by cd /tmp/swa-content triggering SWA CLI v2 "current directory cannot be identical to or contained within artifact folders" error; remove cd, restore --app-location /tmp/swa-content flag running from /analysis WORKDIR; remove --verbose and find diagnostic now that root cause is confirmed
Dockerfile — pre-cache StaticSitesClient binary for Linux (SWA CLI 2.0.8 builds a download URL with @hash suffix that 404s on the CDN); add libicu76 required by the .NET-based StaticSitesClient runtime (missing from python:3.12-slim)
v1.3.122026-03-20
Changed
entrypoint.sh — add find diagnostic before deploy to confirm staged files; cd /tmp/swa-content before swa deploy (no explicit --app-location) to avoid path resolution issues; add --verbose for deployment debug output
v1.3.112026-03-19
Fixed
entrypoint.sh — fix swa deploy positional arg not being picked up in SWA CLI v2; use --app-location /tmp/swa-content and --env production instead of positional path with --env default
v1.3.102026-03-19
Changed
Dockerfile — add Node.js 20 and @azure/static-web-apps-cli for SWA deployment
entrypoint.sh — replace az storage blob upload-batch to $web with swa deploy to Azure Static Web Apps; fetches SWA deployment token from Key Vault (analysis-swa-api-key)
v1.3.92026-03-19
Changed
release_notes.py — each repo now shows only the latest version entry by default; older versions collapsed under "Show N older versions" disclosure element
release_notes.py — fix inline code rendering: only backtick-delimited spans become <code>, not the entire bullet line; raw backtick characters no longer appear in rendered output
release_notes.py — HTML-escape all bullet text before rendering to prevent injection
release_notes.py — a elements get explicit color: inherit so back link no longer inherits browser default link color
v1.3.82026-03-19
Added
tz_utils.py — shared utc_span(dt, fmt) helper and TZ_SCRIPT JS snippet for client-side timezone conversion
Changed
All dashboards with timestamps — generation timestamps now render in the user's browser timezone (e.g. 2026-03-19 15:32 CET) via <span data-utc> + Intl.DateTimeFormat; UTC shown as fallback for non-JS
pipelines/pipeline_dashboard.py — pipeline last-run column also converted to local time
v1.3.72026-03-19
Fixed
quality.py — read REPOS_BASE_DIR env var (with Path(__file__).parent.parent as fallback) instead of always using the local filesystem path; in the container repos are cloned to /tmp/repos not /, so all file tables were empty on the deployed dashboard
v1.3.62026-03-19
Changed
All 10 dashboard generators — mobile-friendly layout: replace fixed repeat(N, 1fr) grid columns with repeat(auto-fit, minmax(..., 1fr)), add flex-wrap: wrap to mini-strips, add 768px and 480px media query breakpoints
index.py — removed inline style="grid-template-columns:repeat(7,1fr)" from all KPI strip divs (was overriding CSS media queries on iPhone)
delivery/delivery_dashboard.py — DORA grid responsive; tables wrapped in overflow-x: auto
leverage/report.py — table overflow scroll on small screens
All dashboards — tables wrapped with overflow-x: auto for horizontal scroll on narrow viewports
v1.3.52026-03-19
Changed
azure-pipelines/refresh.yml — fire-and-forget: remove wait/poll steps from both DEV and PRD stages; pipeline just starts the CAJ and exits
azure-pipelines/refresh.yml — PRD stage: change from deployment job (with environment: analysis-prd) to regular job; no approval gate required
v1.3.42026-03-19
Added
release_notes.py — generates release_notes.html: cross-repo CHANGELOG viewer grouped by project, newest entries first with section colour-coding (Added/Changed/Fixed/Removed); reads from all 9 cloned repos
entrypoint.sh — added python3 release_notes.py before python3 index.py
azure-pipelines/refresh.yml — fire-and-forget: remove wait/polling step from both DEV and PRD stages; pipeline starts the CAJ and exits immediately; monitoring is handled externally
v1.3.22026-03-19
Fixed
entrypoint.sh — removed --depth=1 from all repo clones; shallow clones only fetched the latest commit, making collect.py see ~1 LOC change per repo instead of full history — fixes time invested, NET LOC, lines written/deleted/refactored, and leverage calculations
entrypoint.sh — added analysis repo clone (analysis@main); the repo was in collect.py's REPOS list but never cloned in Azure, causing ~17K LOC and 9 sessions to be excluded from all metrics
v1.3.12026-03-19
Fixed
index.py — _kpis_delivery() was calling dd._get_builds_paginated(pat, id, days) but the function takes (pat, url); fixed to call dd._fetch_runs(pat, id, cutoff) — delivery Freq/CFR now populate correctly
index.py — ado_done always 0 because ado.py excludes Done items from its query; added a separate WIQL POST to count Done/Closed/Resolved items
index.py — _kpis_delivery() bare except Exception now logs error + traceback instead of silently returning muted
leverage/summary.py — ANALYSIS_AI_REVIEW=0 env var disables AI review entirely (checked before cache lookup)
v1.3.02026-03-19
Added
delivery/delivery_dashboard.py — new DORA metrics dashboard: Deployment Frequency, Lead Time for Changes, Change Failure Rate, and MTTR across all 5 apps over an 8-week window; Elite/High/Medium/Low classification per metric and overall
index.py — Delivery Health card (#5b) linking to the new dashboard with DORA class, frequency, and CFR KPIs inline
Changed
Makefile — refresh target now runs delivery/delivery_dashboard.py
azure-pipelines/build.yml — added az containerapp job update step after ACR push for both DEV and PRD, so CAJ image is updated automatically on every build
3DTrailsv1.1.21 · 54 versions
v1.1.212026-03-20latest
Fixed
SEO meta description and canonical URL now persist on What's New page (gen_release_notes.py template)
Show 14 older versions
v1.1.202026-03-19
Fixed
scripts/gen_release_notes.py — wrap client.messages.create() in try/except Exception so any API error (auth, network, rate-limit) degrades gracefully to None instead of crashing the build
v1.1.192026-03-19
Fixed
azure-pipelines/build.yml — replaced AzureKeyVault@2 + bash (with $[variables['anthropic-api-key']]) with a single AzureCLI@2 step that reads the KV secret directly via az keyvault secret show; runtime expressions are not evaluated in env: blocks, so the literal string was passed as the API key causing a 401
v1.1.182026-03-19
Changed
azure-pipelines/build.yml — added azure-pipelines/** to path triggers (both push and PR); pipeline YAML changes now trigger a build so fixes are validated on merge
v1.1.172026-03-19
Fixed
azure-pipelines/build.yml — use $[variables['anthropic-api-key']] instead of $(anthropic-api-key) when passing Key Vault secret to ANTHROPIC_API_KEY env var; ADO macro syntax does not resolve hyphenated variable names in env: blocks, causing an invalid API key to be passed to the Claude API
v1.1.162026-03-19
Added
scripts/gen_release_notes.py — generates frontend/whats-new.html from CHANGELOG.md; rule-based cleanup strips file paths; uses Claude API (claude-haiku-4-5) for AI-translated bullets if ANTHROPIC_API_KEY is set; translations cached in scripts/release-notes-cache.json
frontend/whats-new.html — user-friendly release notes page (dark theme, version pills, bullet list per release); served at /whats-new via existing FastAPI static mount
frontend/index.html — version badge (app-version) changed from <span> to <a href="/whats-new"> so users can click through to the release notes; added hover transition
azure-pipelines/build.yml — added scripts/** to path trigger; added Generate release notes step (runs gen_release_notes.py before az acr build)
v1.1.152026-03-19
Changed
frontend/index.html — version badge restyled as a pill (rounded border, surface background) to match the app's dark theme
v1.1.142026-03-19
Added
frontend/index.html — version badge (v1.1.14) in the top-right of the header, left of the Share button
v1.1.132026-03-19
Added
backend/routers/process.py — describe_route(): calls Claude Sonnet 4.6 after mesh build to generate a 2-sentence personalised description of the terrain model; returned as route_description in the /api/process response
backend/requirements.txt — added anthropic
frontend/index.html — #route-description element shown under route stats after model generation; description passed through in the order POST body
backend/routers/orders.py — route_description field added to OrderRequest and order record
backend/email_utils.py — route description injected into customer order confirmation email
v1.1.122026-03-18
Fixed
frontend/share.html — switched Three.js from legacy globals (0.158 examples/js/) to ESM import map (0.163 examples/jsm/) matching index.html; OrbitControls/STLLoader now use proven-working module imports instead of THREE.OrbitControls/THREE.STLLoader global shims; error text colour changed from undefined var(--danger) to #f87171; resize() falls back to 800×500 if clientWidth/Height is still 0; copyLink exposed on window for inline onclick
v1.1.112026-03-18
Fixed
frontend/share.html — #viewer given min-height: 400px so clientHeight is non-zero on desktop; loadSTL() deferred one animation frame after display:none → grid so the browser reflows before resize() runs; fixes Three.js model not rendering on the share page
v1.1.102026-03-18
Fixed
backend/blob.py — pass client_id to ManagedIdentityCredential so the user-assigned managed identity is used instead of the missing system-assigned one; AZURE_CLIENT_ID env var now set on the container app to 09120a55-4ba8-4c82-97bf-efb28240590c
v1.1.92026-03-18
Changed
frontend/index.html — Share button now copies the link to clipboard immediately and shows "✓ Link copied!" confirmation in the header button; the share link also still appears in the panel
v1.1.82026-03-18
Fixed
frontend/index.html — share flow no longer hangs: thumbnail upload now uses a 5 s AbortController timeout and is wrapped in its own try-catch so a slow or failing blob upload never blocks the share link from appearing
v1.1.72026-03-18
Added
frontend/index.html — Share button in the top-right header; appears after a model is generated; triggers the same share flow as the panel button
Carddexv0.4.6 · 20 versions
v0.4.62026-03-19latest
Fixed
frontend/index.html — "last updated" timestamp now shows the latest scraped_at for the active TCG, not allData[0].scraped_at (which was sorted by rec_score and had no relation to recency); switching TCG tabs updates the timestamp accordingly
Show 14 older versions
v0.4.52026-03-19
Fixed
scripts/gen_release_notes.py — wrap client.messages.create() in try/except Exception so any API error (auth, network, rate-limit) degrades gracefully to None instead of crashing the build
v0.4.42026-03-19
Fixed
azure-pipelines/build-frontend.yml — replaced AzureKeyVault@2 + bash (with $[variables['anthropic-api-key']]) with a single AzureCLI@2 step that reads the KV secret directly via az keyvault secret show; runtime expressions are not evaluated in env: blocks, so the literal string was passed as the API key causing a 401
v0.4.32026-03-19
Changed
azure-pipelines/build-frontend.yml, azure-pipelines/build-api.yml — added azure-pipelines/** to path triggers; pipeline YAML changes now trigger a build so fixes are validated on merge
v0.4.22026-03-19
Fixed
azure-pipelines/build-frontend.yml — use $[variables['anthropic-api-key']] instead of $(anthropic-api-key) when passing Key Vault secret to ANTHROPIC_API_KEY; ADO macro syntax does not resolve hyphenated variable names in env: blocks
v0.4.12026-03-19
Fixed
frontend/Dockerfile — added COPY whats-new.html so the release notes page is actually included in the image; was missing, causing /whats-new to return 404
v0.4.02026-03-19
Added
scripts/gen_release_notes.py — generates frontend/whats-new.html from CHANGELOG.md; rule-based cleanup by default; Claude API translation if ANTHROPIC_API_KEY is set
azure-pipelines/build-frontend.yml — added scripts/** to path trigger; added Generate release notes step before az acr build
v0.3.92026-03-19
Changed
frontend/index.html — replaced emoji logo with inline SVG Pokéball (matches favicon, uses accent orange #e8571a)
frontend/index.html — version badge styled as a monospace pill (bg: var(--bg), border: 1px solid var(--border), border-radius: 4px); wrapped with last-updated in .header-right flex group for correct spacing; hidden on mobile
v0.3.82026-03-19
Added
frontend/index.html — version badge (v0.3.8) in the top-right of the header, between the nav and the last-updated timestamp
v0.3.72026-03-18
Changed
azure-pipelines/deploy.yml — gate PRD stage on sourceBranch == refs/heads/master; non-master builds can no longer trigger a PRD deployment
v0.3.62026-03-18
Fixed
azure-pipelines/build-api.yml — use --no-deps --no-cache-dir when installing datacore from Azure Artifacts; pre-install transitive deps from PyPI to avoid pip resolving datacore from a conflicting public package
v0.3.52026-03-18
Fixed
azure-pipelines/build-api.yml — add --no-cache-dir and remove --extra-index-url from datacore pip install; avoids stale pip cache and prevents PyPI from shadowing the private feed version
v0.3.42026-03-18
Changed
api/main.py: corrected FastAPI title from "Cardmarket API" to "Carddex API"
scripts/smoke_test.py: replaced broad except Exception: with specific exception types
Removed
db.py — unused local copy; all database access goes through the datacore package
v0.3.32026-03-18
Changed
azure-pipelines/build-api.yml — added Run unit tests step before Docker build; installs datacore from Azure Artifacts feed using System.AccessToken; API pushes now gate on pytest passing
v0.3.22026-03-18
Added
tests/test_smoke_test.py — 15 characterisation tests covering _wait_for_url (immediate success, retry-then-succeed, exhausted retries, 200-but-wrong-body), wait_for_healthy, wait_for_frontend, _check_json_list (non-empty ok, empty fail, empty ok when not required, bad JSON), _check_product_history (ok, 404), and suite_api early-exit on empty products
Changed
scripts/smoke_test.py — extracted _wait_for_url() (shared polling loop), _check_json_list() (shared JSON-list check), _check_product_history() from suite_api() and wait_for_*; reduced suite_api CC 10 → ~3; eliminated duplication between wait_for_healthy and wait_for_frontend
Tradehubv0.3.17 · 30 versions
v0.3.172026-03-19latest
Fixed
scripts/gen_release_notes.py — wrap client.messages.create() in try/except Exception so any API error (auth, network, rate-limit) degrades gracefully to None instead of crashing the build
Show 14 older versions
v0.3.162026-03-19
Added
scripts/gen_release_notes.py — generates frontend/public/whats-new.json from CHANGELOG.md
frontend/src/pages/WhatsNew.jsx — What's New page fetches /whats-new.json and renders version cards
frontend/src/App.jsx — /whats-new route added; "What's New" link added to sidebar navigation
Changed
azure-pipelines/build-frontend.yml — added scripts/ to path trigger; added Generate release notes step in both DEV and PRD stages before npm run build
v0.3.152026-03-18
Changed
azure-pipelines/deploy.yml — gate PRD stage on sourceBranch == refs/heads/master; non-master builds can no longer trigger a PRD deployment
v0.3.142026-03-18
Fixed
migrations/003_import_pokemon_inventory.sql — all 34 inventory_items inserts now include NOT EXISTS guard to prevent duplicate rows if the migration is re-run
v0.3.132026-03-18
Added
App.jsx — browser tab title prefixed with [DEV] on dev environment
v0.3.122026-03-18
Added
App.jsx — amber DEV badge in nav logo when VITE_API_URL contains -dev-
v0.3.112026-03-18
Chore
.gitignore — added *.xlsx and frontend/package-lock.json
v0.3.102026-03-18
Changed
Inventory.jsx — show spinner with retry counter while API is starting up instead of immediately displaying "No items found"; retries every 3 seconds automatically until the API responds
v0.3.92026-03-18
Fixed
frontend/.env.production — VITE_API_URL was pointing at the DEV API; corrected to PRD so the production frontend calls the production backend
v0.3.82026-03-18
Fixed
db.py — init_schema() now applies migrations 001, 002, and 004 in order on every API startup; previously only migration 001 was applied, leaving inventory_transactions (004) and the ean column on products (002) absent on fresh containers, causing every GET /inventory call to 500 and the inventory page to show blank
v0.3.72026-03-18
Changed
azure-pipelines/build-api.yml — added Run unit tests step in Build_Dev before the ACR push; API changes now gate on pytest passing
v0.3.62026-03-18
Added
tests/test_inventory.py — 8 characterisation tests for _apply_floor_prices (price set, missing URL, None fp, zero qty, multiple items) and _enrich_with_carddex (no connection, no URLs, price applied)
tests/__init__.py — marks tests/ as a package
Changed
api/routers/inventory.py — extracted _fetch_floor_prices() and _apply_floor_prices() from _enrich_with_carddex() to reduce cyclomatic complexity (CC 5 → ~2) and improve testability
v0.3.52026-03-18
Fixed
azure-pipelines/build-api.yml — add --platform linux/amd64 to az acr build in both Dev and Prd stages; self-hosted pool runs on ARM so without this flag images were built as linux/arm64, causing Container App provisioning to fail
v0.3.42026-03-18
Fixed
api/routers/inventory.py — Carddex enrichment now catches exceptions instead of propagating them; a Carddex DB blip no longer causes GET /inventory to return 500 (which silently emptied the inventory page in the frontend)
v0.3.32026-03-18
Fixed
frontend/src/auth.js: hardcoded 578a5dbb-280c-496c-b066-b7f7e244cdbd as fallback for VITE_AAD_CLIENT_ID — same pattern as TENANT_ID; eliminates blank-app breakage when the env var is absent from a pipeline build
Cardmarketv1.3.4 · 30 versions
v1.3.42026-03-19latest
Changed
azure-pipelines/build-api.yml, build-frontend.yml, build-scraper.yml — added azure-pipelines/** to path triggers; pipeline YAML changes now trigger a build so fixes are validated on merge
Show 14 older versions
v1.3.32026-03-18
Fixed
scraper/browser.py — fix "Show more" click loop: dispatch full MouseEvent sequence (mouseover, mouseenter, mousedown, mouseup, click) instead of native Selenium click; wait for row count increase (15s) after each click rather than a fixed sleep; break when no new rows appear (all listings loaded)
scraper/browser.py — capture row count before the click (not after) to avoid race condition with fast-loading pages
Added
scraper/debug.py — SCRAPER_DEBUG=1 env-var-gated debug logging module; replaces ad-hoc ts() helpers in browser and parser
Changed
azure-pipelines/deploy.yml — gate PRD stage on sourceBranch == refs/heads/master; non-master builds can no longer trigger a PRD deployment
v1.3.22026-03-18
Fixed
api/Dockerfile — replace BuildKit --mount=type=secret,id=ado_pat with ARG ADO_PAT; consistent with scraper Dockerfile and required for az acr build --build-arg in the build pipeline
v1.3.12026-03-18
Fixed
azure-pipelines/build.yml — switch docker build from --secret id=ado_pat to --build-arg ADO_PAT for both scraper and API images; Dockerfiles now use ARG ADO_PAT so the secret mount no longer applies
v1.3.02026-03-18
Fixed
Dockerfile — replace BuildKit --mount=type=secret with ARG ADO_PAT; Container App Job agents don't have a Docker daemon so BuildKit secrets don't work
azure-pipelines/build-scraper.yml — switch from docker build + push back to az acr build --build-arg ADO_PAT; removes the Docker daemon dependency
v1.2.92026-03-18
Fixed
scraper/browser.py (_load_all_listings): ElementNotInteractableException on "Show more" button caused by a cookie consent banner appearing after wait_for_page() — now dismissed before the click loop and caught per-click with a JS fallback click that bypasses overlays
v1.2.82026-03-18
Fixed
azure-pipelines/build-scraper.yml — use --no-deps --no-cache-dir when installing datacore from Azure Artifacts; pre-install transitive deps from PyPI to avoid pip resolving datacore from a conflicting public package
v1.2.72026-03-18
Fixed
azure-pipelines/build-scraper.yml — install datacore from Azure Artifacts in unit-test step so tests/conftest.py can import datacore.db without ModuleNotFoundError; add --no-cache-dir and remove --extra-index-url to prevent stale cache and PyPI shadowing
v1.2.62026-03-18
Fixed
Dockerfile — added BuildKit secret mount so pip install can resolve datacore>=0.1.0 from the Azure Artifacts private feed (was falling back to public PyPI where only 0.0.1 exists)
azure-pipelines/build.yml — scraper build now uses DOCKER_BUILDKIT=1 with --secret id=ado_pat,env=SYSTEM_ACCESSTOKEN (was plain docker build, missing feed credentials)
azure-pipelines/build-scraper.yml — switched from az acr build to docker build + push with BuildKit secret so the private feed is accessible (same pattern as API pipeline)
v1.2.52026-03-18
Changed
All scraper modules (scraper/main.py, scraper/browser.py, scraper/classifier.py, scraper/sentiment.py, scraper/summary.py, scripts/db_summary.py, tests/conftest.py, tests/test_db.py) now import datacore.db instead of the local db.py
Added datacore>=0.1.0 to requirements.txt for scraper container
scripts/smoke_test.py: replaced broad except Exception: with specific (json.JSONDecodeError, AttributeError) / (urllib.error.URLError, OSError) / (json.JSONDecodeError, KeyError, IndexError) where error type is unambiguous
Removed
db.py — redundant local copy; canonical implementation lives in the datacore package
v1.2.42026-03-18
Changed
scraper/main.py (1,616 LOC → ~250 LOC) — split god file into focused modules:
Quality dashboard false positive corrected: db.py and api/main.py are not duplicates
v1.2.32026-03-18
Changed
azure-pipelines/build-api.yml — added Run unit tests step (pytest, skips test_sentiment.py) before Docker build; API changes now gate on the full test suite
scripts/recalculate_metrics.py — extracted _fetch_snapshots(), _fetch_listings(), _write_snapshot_metrics() from main() to reduce cyclomatic complexity (CC 10 → ~3)
scripts/reclassify.py — extracted _fetch_unclassified_snapshots(), _fetch_commented_listings(), _accumulate_result() from main(), and _update_flag_bulk() from _persist() to reduce cyclomatic complexity (CC 8 → ~3, CC 5 → ~2)
tests/test_classify.py — 10 tests for _parse_response (damaged, spam, all-clean, out-of-bounds index, bad JSON) and classify_snapshot (no comments, API error, parse error, happy path cost calculation, dry_run never persists)
azure-pipelines/build-scraper.yml — Run unit tests step runs pytest tests/ before Docker build; tests/** added to trigger paths
requirements.txt — added pytest
Terraform (IaC)v0.10.15 · 41 versions
v0.10.152026-03-19latest
Changed
modules/analysis/main.tf — replace Azure Front Door Standard with Azure Static Web Apps Free tier ($0/month); removes azurerm_storage_account_static_website and all AFD resources; adds azurerm_static_web_app, azurerm_static_web_app_custom_domain (dns-txt-token validation), and azurerm_key_vault_secret to persist the SWA deployment token in Key Vault
modules/analysis/outputs.tf — replace AFD outputs with swa_default_hostname and swa_validation_token
envs/prd/main.tf, envs/dev/main.tf — swap analysis_afd_* outputs for analysis_swa_* outputs
Show 14 older versions
v0.10.142026-03-19
Added
modules/analysis/main.tf — Azure Front Door Standard profile, endpoint, origin, route, custom domain, and domain-association resources; routes dashboard.kardz.eu (prd) and dashboard-dev.kardz.eu (dev) to the static website storage account with managed TLS (Azure CDN Classic is deprecated for new resources since Oct 2025)
modules/analysis/outputs.tf — afd_endpoint_fqdn and afd_validation_token outputs for DNS setup
envs/prd/main.tf, envs/dev/main.tf — pass custom_domain to the analysis module; update analysis_dashboard_url and add AFD outputs
v0.10.132026-03-19
Fixed
envs/dev/main.tf — import module.trails.azurerm_key_vault_secret.aad_client_id; secret already existed in Key Vault but was not in state, causing apply to fail
v0.10.122026-03-19
Fixed
modules/data/main.tf, modules/3dtrails/main.tf, modules/tradehub/main.tf, modules/cardmarket/main.tf — kv_secrets_officer role assignment: use var.cicd_spn_object_id instead of data.azurerm_client_config.current.object_id; the current caller changes between local runs (user) and pipeline runs (SPN), causing spurious replacements on every local plan
envs/dev/main.tf, envs/prd/main.tf — pass cicd_spn_object_id to the data module
v0.10.112026-03-19
Fixed
envs/ado/main.tf — add interpreter = ["/bin/bash", "-c"] to both null_resource provisioners; agent shell is dash (/bin/sh) which does not support set -o pipefail
v0.10.102026-03-19
Changed
azure-pipelines.yml — remove ADO stage; ADO config now has its own pipeline
azure-pipelines-ado.yml — new dedicated pipeline for envs/ado; triggers only on changes to envs/ado/**
v0.10.82026-03-19
Fixed
envs/ado/main.tf — convert ALL import blocks (branch policies, environments) to multi-line format; single-line format with alignment spaces caused HCL parser to drop the id argument for long resource addresses
envs/ado/main.tf — replace notification_subscriptions with notification_opt_outs; use userSettings.optedOut PATCH body (correct API for group/default subscriptions)
Added
envs/ado/main.tf — null_resource.subscribe_build_failed: creates a custom "Build failed (pipeline)" subscription using the ms.vss-build.build-fails-subscription-template filter; replaces the opted-out "Build completes" default
envs/ado/variables.tf — notification_opt_outs variable (replaces notification_subscriptions); defaults to opting out of ms.vss-build.build-requested-personal-subscription
v0.10.72026-03-19
Added
envs/ado/ — new Terraform environment for ADO config (replaces platform/ado/ shell scripts)
azure-pipelines.yml — added Ado stage (runs before Dev); applies envs/ado on every master push; uses ADO_PAT pipeline variable; auto-creates tfstate-ado container
Fixed
envs/ado/main.tf — analysis repo branch policy corrected from master to main (existing policies were targeting the wrong branch)
modules/analysis/main.tf — dynamic schedule_trigger_config / manual_trigger_config blocks; uses cron when set, falls back to manual trigger
envs/prd/main.tf — set analysis_cron = "*/10 * * * *" on analysis module
v0.10.52026-03-19
Changed
modules/analysis/main.tf — inject ANALYSIS_AI_REVIEW=0 env var into CAJ; disables the Claude AI review call in summary.py by default
v0.10.42026-03-19
Fixed
modules/analysis/main.tf — removed lifecycle { ignore_changes = [template] } from azurerm_container_app_job.analysis; the placeholder was needed only for bootstrapping (before analysis:latest existed in ACR); keeping it caused AZURE_CLIENT_ID env var (added in v0.10.2) to never be applied to the running CAJ
v0.10.32026-03-19
Fixed
modules/3dtrails/main.tf — restore azurerm_storage_account.blobs, azurerm_storage_container.stl, and azurerm_role_assignment.blob_contributor (removed accidentally in v0.10.1); restore AZURE_STORAGE_ACCOUNT_NAME and AZURE_STORAGE_CONTAINER_NAME env vars in null_resource.set_app_env; add storage_account trigger so env vars re-wire if storage account changes
v0.10.22026-03-19
Fixed
modules/analysis/main.tf — inject AZURE_CLIENT_ID env var into CAJ so az login --identity --username can target the user-assigned managed identity; fix image from placeholder to ${acr_login_server}/analysis:latest
envs/dev/main.tf + envs/prd/main.tf — pass module.platform.identity_client_id to analysis module
v0.10.12026-03-19
Added
modules/3dtrails/main.tf — azurerm_key_vault_secret.anthropic_api_key: PLACEHOLDER secret (anthropic-api-key) in the 3dtrails KV; secret block on the Container App; ANTHROPIC_API_KEY=secretref:anthropic-api-key wired via null_resource.set_app_env
modules/3dtrails/main.tf — secret block for aad-client-id re-added to Container App to prevent Terraform updates from dropping the existing MSAL secret reference
Fixed
modules/analysis/main.tf — use placeholder image on first apply + lifecycle { ignore_changes = [template] } so Terraform no longer fails when analysis:latest does not yet exist in ACR
v0.10.02026-03-19
Added
modules/analysis/main.tf — azurerm_container_app_job.analysis (caj-kardz-analysis-{env}-weu-01): manual trigger, 1 CPU / 2Gi, pulls image from ACR via managed identity, injects ENV and STORAGE_ACCOUNT
modules/analysis/main.tf — azurerm_role_assignment.identity_blob_contributor: Storage Blob Data Contributor on analysis storage account for the managed identity
modules/analysis/variables.tf — five new variables: container_app_environment_id, identity_id, identity_principal_id, acr_login_server, key_vault_name
modules/analysis/outputs.tf — job_name output (used by refresh pipeline to trigger a run)
Changed
envs/dev/main.tf + envs/prd/main.tf — pass new platform module outputs to analysis module
Platformv1.2.0 · 4 versions
v1.2.02026-03-19latest
Removed
ado/apply-branch-policies.sh, ado/setup-environments.sh, ado/config.json — migrated to Terraform (terraform repo envs/ado/); Terraform now manages branch policies, environments, approval checks, and branch control checks declaratively
ado/config.json — central config for all 9 repos (name, ID, defaultBranch) and 4 environments (dev, prd, tradehub-dev, tradehub-prd) with approval settings
ado/setup-environments.sh — idempotent script to create ADO Environments and apply Approval checks from config
Changed
ado/apply-branch-policies.sh — refactored to read repos and org/project from config.json; find_policy() extracted to top-level function for reliable idempotency
README.md — document both ADO scripts, environment table, and two-layer branch enforcement strategy