Releases: zndr88/LicenseTrack
Release list
v1.1.22
Running LicenseTrack in a production environment with real data has proven useful. The last few updates have been business-logic centric with a few surface level bug fixes along the way. This patch and the next few will be focussed on bug hunting and fixing without adding to the tool.
This particular release is a patch update focused on lifecycle correctness, procurement evidence,
CSV round trips, background jobs, and reliable session expiry and logout. Main focus for me now is to dive deeper in these corrections and dive deeper if required.
Fixed
- Fixed concurrent existing-successor linking allowing conflicting renewal links,
and protected pending-renewal lifecycle state from ordinary edits. - Validated established renewal terms when editing either side of a renewal chain
and when importing successors, including coterm predecessor relationships. - Fixed existing maintenance-successor linking to activate coverage for every
parent and require a maintenance successor. Unlinking now restores the previous
parent coverage, relationships, and history, with conflict checks when coverage
has changed since linking. - Protected maintenance creation from lifecycle-field overrides, allowed valid
edits to retired unlinked maintenance, and prevented unchanged parent selections
from reactivating maintenance. Date edits now normalize scheduled-retirement state. - Fixed repeated coterm merges losing earlier predecessor relationships and quote
evidence. Shared quotes remain available to unmerged sibling lines, while
line-specific evidence follows its merged line and failed copies are cleaned up. - Preserved support fallback fields during pending-order conversion and avoided
scheduling quote-evidence transfers for sourcing requests without quote documents. - Fixed purchase-order total matching and Registry CSV grouping to use normalized
procurement identity, keeping separate pending orders isolated even when they
reuse a PO number. Currency changes now clear incompatible standalone PO overrides. - Fixed CSV completeness checks omitting shared documents, preserved multiple
invoice identifiers without splitting identifiers containing commas, and kept
bundled support fields synchronized during CSV updates. - Fixed secondary-contact formatting to accept both stored lists and text values.
- Prevented deleted user IDs from being reused by newly created accounts.
- Fixed daily notification and backup jobs being skipped when background work
crossed their scheduled time, and released webhook database transactions between
deliveries to avoid holding them open during network requests. - Fixed session expiry, refresh coordination, and delayed logout or refresh responses
interfering with a later login. Each login now has an independently revocable
session with server-enforced sliding expiry; logout and inactivity expiry revoke
the current session while preserving other device sessions. - Coordinated protected requests with session refresh, shared activity across browser
tabs, counted panel scrolling as activity, and exposed the configured timeout to
non-admin users. Split deployments refresh from each tab's actual bearer-token expiry. - Cleared cached application data on logout and expanded regression coverage for
lifecycle, procurement, CSV, background-job, and authentication fixes.
Documentation
- Refreshed the public website and demo presentation, added an illustrated demo
walkthrough, and reorganized operator guidance for evaluation, prerequisites,
first login, CSV imports, and renewal workflows with focused reference pages.
v1.1.21
Added
- Added authenticated PDF previews to contract details, with a wide split layout,
independent document and preview areas, and responsive stacking on narrow screens. - Added an independent global renewal-action window. Administrators can decide how
many days before expiry initiation and existing-successor linking become available;
installations that do not configure it retain the existing expiry-alert-window
behavior. - Added explicit Shared or Single scope controls for Quote, Purchase Order, Invoice,
EULA, and Entitlement attachments throughout manual creation, maintenance creation,
sourcing, pending orders, and conversion.
Changed
- Expiring licenses with an actual linked Upcoming successor now show a steel
Renews in X days badge, or Renews today, based on successor coverage while
retaining the predecessor's expiration state and any coverage-gap warning. - Renewal bundles remain limited to eligible licenses with the same PO number and end
date, but the workbench now resolves membership from the complete candidate set
instead of only the currently visible rows. - Collapsing the shared Documents controls no longer closes or hides the selected
staged-file or stored-document preview. - Newly uploaded shared evidence for direct/manual licenses can be reused by licenses
with the same normalized PO number. Pending-order identity remains authoritative,
so unrelated pending orders never share evidence merely because their PO numbers
match. Existing document ownership is not migrated or backfilled.
Fixed
- Fixed overdue renewal views omitting expired licenses whose renewal procurement is
already in progress. - Fixed linked-renewal badges being omitted when normalized API records expose the
successor through renewal-chain fields other than the legacy lookup shape. - Fixed license details and Registry CSV exports dropping valid zero or negative
calculated totals. - Fixed sourcing quote evidence being unavailable from pending-order conversion.
- Fixed pending-order invoice uploads losing their pending-order scope when shared PO
metadata was also present, which could expose evidence to a different pending order
using the same PO number. - Fixed CSV updates defaulting omitted currencies, accepting invalid term dates,
retaining handled state for changed notice dates, and leaving maintenance mirrors stale. - Fixed PO totals and overrides crossing separate procurement groups that reuse a PO number,
including frontend cache, sorting, detail, overview, and Registry CSV behavior. - Fixed linked maintenance costs being displayed in the parent license's currency.
- Fixed purchase-line conversion dropping previously entered commercial and ownership data.
- Fixed Escape saving inline edits instead of cancelling them in Registry and procurement tables.
- Fixed successful documents remaining hidden after a later file in the same upload failed.
v1.1.20
This is a minor fix release for a database migration failure encountered when
upgrading from 1.1.17 to 1.1.19.
Fixed
- Fixed the scheduled-retirement migration attempting to reactivate retired
maintenance records without a parent license or the explicit legacy-unlinked
exception when their end date was today or later. Those records were valid
while retired, but reactivating them violated the
ck_license_maintenance_has_parentdatabase constraint and stopped the upgrade.
The migration now leaves these records retired while continuing to schedule
retirement for eligible records, preserving parent links and legacy flags. - Added regression coverage for the 1.1.17 upgrade path, date boundaries,
database integrity, and migration downgrade/re-upgrade behavior.
This release corrects an existing migration; it adds no new migration revision,
configuration requirement, or breaking public API change. Operators affected by
the failure should use 1.1.20 through the normal upgrade procedure. Installations
already running 1.1.19 can upgrade normally to 1.1.20.
v1.1.19
Added
- Added a deeper License Overview sidebar that separates current coverage,
planned changes, and historical records, including renewal-in-progress and
scheduled-retirement counts. - Added coverage urgency for pending renewals: records retain their Expiring or
Expired coverage status while also showing the Pending Renewal workflow state,
filters, counts, and urgency styling. - Added retirement-scheduled and renewal-notifications-off badges to license
details. - Added expand-all and collapse-all controls for sourcing and pending-order
tables, with clearer renewal context and previous-license descriptions in
expanded line items.
Changed
- Changed existing-successor matching to use the normalized publisher as the
required identity while allowing other entitlement details to differ, with
explicit successor term and license-type eligibility checks. - Kept pending renewals in current coverage and recurring reporting until their
current term ends, while preserving the separate renewal workflow state. - Streamlined sourcing and pending-order workspaces with clearer inline-edit
controls, conditional currency display, multi-row expansion, and an explicit
path to add a missing purchase-order number before conversion.
Fixed
- Made single and bundled renewal initiation reserve lifecycle transitions
atomically, preventing duplicate concurrent renewal workflows. - Coordinated scheduler and background database jobs with restore maintenance so
database replacement waits for active work to drain. - Allowed manual retry of escalated evidence transfers and repaired missing or
stale copied quote evidence during retry. - Restricted renewal initiation to records that are actually Expiring or
Expired, and kept pending-renewal alerts aligned with the underlying coverage
urgency.
v1.1.18
Added
- Added reusable contact suggestions for publisher contacts, budget owners,
secondary contacts, and other people fields across license, sourcing,
pending-order, and conversion forms, backed by an authenticated reference-data
endpoint and matching demo-mode behavior. - Added inline editing for sourcing line items and pending-order overview, line,
purchase-order, invoice, supplier, and date details, plus sourcing-quote preview
from the pending-order workspace. - Added an Upcoming count to license navigation and the ability to schedule an
active license for automatic retirement when its current term ends. - Added per-custom-field renewal behavior and sourcing-form visibility controls.
- Added categorized document staging during license creation and pending-order
conversion, including an explicit choice to share procurement evidence across
the created licenses or attach it to only one license.
Changed
- Unified license and procurement forms around shared defaults, standard field
sections, custom-field sections, secondary-contact normalization, sourcing
payload builders, and custom-field definition queries. - Consolidated staged and stored document preview metadata, attachment state,
category handling, and modal layout while preserving the existing storage and
evidence-transfer boundaries. - Suppressed renewal attention and notification alerts as soon as a successor is
secured, while retaining the predecessor's date-based coverage state.
Fixed
- Updated
fflateto 0.8.3 to prevent malformed ZIP64 archives from causing an
infinite parsing loop, and updated the ESLint@humanfs/nodedependency to
0.16.8 so recursive development-tool copies do not follow symlinked files
outside their source tree. - Normalized blank procurement milestone dates to null during license writes so
clearing a date no longer causes validation failures. - Kept sourcing supplier suggestions visible above editable rows and clarified
when sourcing inline-edit mode is active.
v1.1.17
Added
- Added complete license-field and section-aware custom-field capture throughout
sourcing and pending-order intake, conversion, and renewal workflows, including
optional custom-field carry-forward on renewal.
Changed
- Unified procurement intake and conversion forms around shared field sections
and a consistent document preview workspace for staged and stored files. - Made backend-provided lifecycle and expiration status authoritative across the
registry, license details, renewal actions, reports, and exports.
Fixed
- Renewed active sessions before expiry so users working in the application are
no longer logged out after a fixed interval; the configured inactivity timeout
still applies. - Preserved a renewed predecessor's own date-based coverage state until its term
ends, including overlapping and upcoming successor messaging. - Kept License Overview Attention-banner dismissals for the authenticated browser
session and cleared them on logout or session expiry. - Improved document preview compatibility while restricting rendered previews
to generated blob URLs, and replaced backtracking currency-affix parsing with
deterministic handling of untrusted values. - Hardened staged-field migrations, backup restore coverage, and targeted
sourcing-order reloads.
This release includes an Alembic migration that adds staged license fields and
custom-field values to sourcing items plus the custom-field renewal carry-forward
flag. Downgrade removes those additions. No configuration change or breaking
public API change is required.
v1.1.16
This release closes a series of intended refactors after a milestone stretch. Going forward, 1.1.16 will be the baseline.
Fixed
- Invalidated cached global settings after a successful database restore so
subsequent requests cannot continue using values from the replaced database.
Changed
- Removed three inert persisted settings fields while retaining all active
notification, manager-email, appearance, locale, security, backup, and
integration settings contracts. - Consolidated the shared prepared-item execution used by single and batch
pending-order conversion while preserving the early SQLite write lock,
transaction ordering, partial-failure behavior, audit events, response
contracts, and evidence-transfer recovery. - Split detailed-report construction into focused lifecycle-spend,
procurement, recurring-forecast, portfolio, renewal, and perpetual-
maintenance builders without changing response shape or currency semantics. - Aligned canonical and alias lookup and alias-addition validation for
organizations and cost centres while retaining their distinct merge,
synchronization, and access rules. - Shared native and mapped CSV row assembly while preserving localized
parsing, preview values, warnings, nested transactions, reference updates,
maintenance inference, and row-level errors. - Documented that license statistics and detailed reporting intentionally keep
separate recurring-cost ownership because their unpriced-value semantics
differ.
v1.1.15
This release introduces no database migration or configuration change. It is part of a series of refactors after the previous releases introduced new features and patched existing ones. Expected outcome: healthier codebase.
1.1.16 will be a refactor which will need .15 as a healthy baseline.
Changed
- Consolidated frontend routing, license creation, authenticated downloads,
query invalidation, CSV preview rules, and suggestion review around their
canonical hooks, API helpers, and components. - Moved duplicated backend route and workflow logic into the owning license,
sourcing, pending-order, import, document-processing, user, and plugin
services. - Unified internal storage, custom-field, reference-data, lifecycle,
reporting, and notification operations while preserving existing public
API and operator behavior. - Kept registry column defaults in the frontend while retaining persisted user
overrides and existing settings contracts.
v1.1.14
Added
- Added filtered detailed-report APIs and complete, formula-safe CSV and
paginated PDF exports with native-currency totals. - Added persistent notification-run status for successful, partial, blocked,
failed, skipped, and no-work outcomes. - Added stable OIDC identity binding and per-user session invalidation.
- Added optional atomic line-item creation to
POST /api/pending-orderswhile
preserving header-only requests. - Added sourcing-quote provenance and retired-license context to procurement
history.
Changed
- Unified report cards, forecasts, detailed views, CSV, and PDF around the same
filtered, currency-safe calculations. - Improved notification classification, delivery outcomes, loading errors, and
retry guidance across scheduled and manual runs. - Enforced backend session timeouts, rotated tokens after password changes, and
invalidated sessions after security-sensitive account changes. - Expanded audit coverage for downloads, exports, folders, mappings,
notifications, webhooks, backups, and restores. - Prefilled standard renewals with an editable one-year successor term and
required a budget owner before renewal initiation. - Aligned Renewal Workbench bundle eligibility with License Details and
restricted existing-successor links to matching entitlements with advancing
terms. - Preserved individual line values in coterm merges, including mixed unit
prices, while continuing to reject mixed currencies and license types.
Fixed
- Corrected reports for mixed currencies, shared procurement and maintenance
costs, invalid prices, and undated recurring records. - Strengthened notification recipient validation and prevented repeated
automatic retries after an unsuccessful daily attempt. - Enforced forced-password changes at the API boundary, rejected inactive local
logins, and tightened OIDC issuer, audience, email, and subject validation. - Made database restore maintenance-safe with archive and schema validation,
pre-swap migrations, recovery snapshots, and reliable outcome auditing. - Prevented department-scoped Viewers from accessing shared contracts or
procurement evidence connected to an unassigned department. - Improved contract authorization, validation, legacy matching, document error
handling, and synchronized document state. - Kept quote, purchase-order, and invoice evidence on the correct scope and
improved upload rollback, deletion cleanup, and missing-file handling. - Strengthened CSV import parsing, header and mapping validation, custom-field
handling, and duplicate detection. - Isolated purchase-order totals by PO number and currency and made exports
deterministic. - Enforced unique organization and cost-centre names and aliases, with an
upgrade check for existing conflicts. - Reduced reference-data query overhead and made custom-field reordering atomic.
- Prevented concurrent sourcing conversions from creating duplicate pending
orders or licenses. - Scoped renewal cancellation correctly and stopped upcoming licenses from
generating expiry notifications. - Corrected shared-maintenance renewal, coverage history access and refresh,
and maintenance-cost calculations. - Improved final-line pending-order deletion, partial document-upload handling,
and procurement-evidence transfer recovery. - Kept procurement history navigation and links usable for filtered, converted,
and retired records.
v1.1.13
Added
- Added Link existing successor to the renewal workflow so a pre-purchased
upcoming license under the same purchase order can become the next term
without creating a duplicate purchase. The adopted license follows the
standard renewal chain, procurement trail, lifecycle transition, reference
alias, and unlink behavior.
Changed
- Unified new managed document storage under an
attachments/hierarchy keyed
by immutable license, pending-order, procurement-bundle, sourcing-request,
and contract IDs instead of using purchase-order numbers as physical folder
names. Legacy stored paths remain readable and supported by backup, restore,
and portfolio reset workflows. - Classified Quote, Purchase Order, and Invoice uploads consistently as
procurement evidence even when the attached license does not yet have a PO
number.
Fixed
- Made the Docs column selectable from License Overview and per-user
settings, renamed Visible Categories to Column Categories, and kept
the selector within the viewport when the attention banner lowers the toolbar. - Required document categories now count toward completeness only when the
managed file is available. Missing or unavailable files retain their
metadata and availability counts but no longer make a license appear
complete in the Registry, reports, notifications, exports, or Renewal
Workbench. - Rejected newly created or edited terms whose end date precedes their start
date across manual entry, inline editing, CSV import, procurement conversion,
maintenance, and renewal workflows. Existing invalid historical records
remain readable and repairable instead of breaking the Registry response. - Stopped classifying recurring licenses without an end date as perpetual.
They remain active but incomplete until an end date is supplied, while true
non-expiring license types retain perpetual status. - Rejected explicit null values for required license fields and safely
normalized null values for clearable text fields, preventing database errors
during full and inline updates. - Scoped bulk selection to the displayed page, cleared hidden selections when
filters or pagination change, and identified the selected licenses in the
delete confirmation. - Reset and clamped Registry pagination after searches, filters, saved-view
changes, and page-size changes so a valid filtered result cannot appear as an
empty out-of-range page. - Aligned Registry status filters with portfolio counts: Active no longer
includes expiring licenses, and Incomplete no longer includes
completeness-exempt records. - Removed the redundant all-custom-field-values request from License Overview
and built the custom-field map from values already embedded in the license
registry response. - Kept core license loading independent from auxiliary statistics, sourcing,
pending-order, contract, and custom-field-definition failures. The Registry
retains last-known supporting data, shows unavailable pipeline counts as
unknown instead of zero, offers a focused retry, and applies stable license
ID ordering before offset pagination.