Appendix — every change in this release

Every change between the last alpha build and GA — 248 commits,
grouped by kind. The Bug fixes section above is a selection; this is the
complete record. Generated from v1.3.0-09..69e614a; the commit that writes
this appendix is necessarily not listed in it.

Features (60)

  • a692e82 feat(alerts): watch data caps, and fix an alert that could never fire (#35)
  • db09e49 feat(health): qualify "Connected" with how often it has dropped (#28 part 2)
  • 8766f0c feat(support): cumulative health counters — a flap was invisible (#28)
  • 6547841 feat(support): say whether the box is licensed, and why the cap disagrees
  • 159900e feat(events): AAA faults in the alert centre
  • a7d3d75 feat(controller): bound the retained config history (bng#41)
  • 6e66f4c feat(support): collect intent, not just running state; fix the capture
  • 1ddc2cb feat(support): consolidate the bundle and lead with a written summary
  • 6c998af feat(support): one-button diagnostic bundle for a support ticket
  • d27b574 feat(aaa): subscriber_id is an exact key everywhere (#25)
  • dd2ad55 feat(rates): A-06 in the subscriber drawer, with the cap consequence stated
  • dbf33ec feat(rates): A-06 — a raw per-subscriber rate, expressed as a plan
  • a93def0 feat(caps): wire the per-subscriber surfaces an operator could not reach
  • 6520bf5 feat(billing): customer_ref reaches exported CDRs — closes the G-11 gap
  • f350e5d feat(caps): data-cap panel on the subscriber drawer
  • e938fa5 feat(caps): Data Caps page and its client
  • 51768fa feat(caps): the operator API for data-cap policy
  • d490741 feat(caps): run the evaluator on the drain tick, publish bngcap*
  • 4c8c146 feat(aaa): converge enforcement overlays every reconcile pass
  • 52f51d9 feat(caps): declare the data-cap webhook events at registration
  • e12bee1 feat(caps): evaluate_once -- usage in, enforcement rows out
  • 5c33019 feat(caps): resolution and decision, as pure functions
  • 92c7914 feat(caps): sum usage over a cap cycle window
  • c807ca0 feat(caps): CapPolicyStore -- allowances, overrides, grants, cycle state
  • 442dd65 feat(caps): the cap cycle calculator
  • a2f89b5 feat(aaa): surface unmanaged subscribers with adopt and remove
  • fa36791 feat(aaa): run the reconciler and publish what it does
  • 2800a25 feat(aaa): write durably before pushing to the controller
  • 9dacdcd feat(aaa): detect a wiped controller and restore the base
  • 5a09424 feat(aaa): converge the controller onto our store
  • 8c1ba55 feat(aaa): one-time adoption of the controller's subscriber base
  • 5268a80 feat(aaa): durable subscriber store
  • a86eecf feat(accounting): the page becomes a view over the ledger
  • 303fc76 feat(accounting): publish drain lag, age and errors
  • b2673e8 feat(ledger): daily prune and scheduled export
  • cf5ca6a feat(accounting): read and export the ledger
  • 3c3544d feat(ledger): 13-month retention and historised identity
  • c6cf03e feat(accounting): drain the spool server-side, ack only after commit
  • 5e77571 feat(ledger): daily usage by differencing cumulative counters
  • dd94744 feat(ledger): durable accounting store
  • 7e5c82b feat(about): stamp the wheel with the commit it was built from
  • 1290760 feat(subscribers): show an account's sessions, and let an operator end them
  • 6be6c4d feat(static-ip): assign an address from the subscriber drawer
  • 39829b6 feat(static-ip): reject a conflicting address before it is written
  • 02aa0eb feat(static-ip): CSV columns, and rename the observed address
  • 1654ede feat(static-ip): reject an address the pool will later lease
  • 0caca48 feat(capacity): make a full box impossible to miss
  • da92855 feat(add-ons): close the update-checking half of the lifecycle
  • 90312bb feat(marketplace): brighter selector, and Check now shows its work
  • 92f2797 feat(marketplace): restore the page selector between Licensing and Add-ons
  • 605f411 feat(bundle): pin upstream v1.4.0 and core 0.10.17
  • 82cc22c feat(webui): two AAA controls, and delete the inert recovery-age knob
  • 079b383 feat(aaa): locators, subscriber_id keying, and the new bulk shape
  • e1e70d0 feat(aaa): source selector replaces the removed mode field
  • ac535aa feat(webui): Licensing leads with the fingerprint and the cap in force
  • 86d43d0 feat(webui): Marketplace section with the Add-ons page
  • c6a45af feat(addons): update checking that knows when to stay quiet
  • 5b2e3f2 feat(addons): both modules install from an uploaded tarball
  • 8086199 feat(addons): the catalogue, with a URL an offline mirror can own
  • e313512 feat(addons): retain one previous artifact, and roll back to it offline

Fixes (91)

  • 66c8283 fix(sessions): an unavailable session list must not render as an empty one
  • d05ed72 fix(webui): drop two false claims from the topology, and stop the session drawer opening blank
  • 5f31de2 fix(statseg): the sizing axis is threads, not subscribers
  • 6a47925 fix(install): the statseg fix wrote a key core never reads — bundle -10 is a no-op
  • ccc0c56 fix(docs): the stats segment IS measurable — I checked the wrong route
  • 21c5c10 fix(install): size VPP's stats segment — nothing in the product did (#42)
  • 72862b3 fix(health): two red RADIUS cards on every healthy 1.4.0 box were a false alarm (#39)
  • 00d05df fix(webui): the Topology page had no AAA element at all, and Pools read DNS from a key that does not exist (#39, #40)
  • c2e9128 fix(restore): verify an access-port write landed instead of trusting 200 (#30)
  • 1389fed fix(sessions): drop the Subscriber column for 1.4.0; restore it in 1.5 (#27)
  • c180ff6 fix(licensing): read grants, not a field the controller never sent (#32)
  • 4936c90 fix(snapshots): a restore would have disabled every access port (#30)
  • b2d734c fix(webui): the cap caption said "Community" on a licensed box
  • 991ab53 fix(sessions): draw the cap line at the cap actually in force
  • c1c9ed3 fix(licensing): activation works from the console
  • f116a40 fix(licensing): a trailing newline was invalidating valid licences
  • 8259ab9 fix(snapshots): make restore actually restore
  • 4f6d033 fix(captive-portal): stop the portal_ip save erasing the walled garden
  • af961cf fix(support): run the collection detached — an in-worker thread killed the dashboard
  • e0f8175 fix(support): parse BUNDLE_VERSION; bundle 1.4.0-05
  • 7de3579 fix(webui): an unprovisioned subscriber_id is a write key, not a join key (#25)
  • 3ad4709 fix(tests): stop the suite running production daemons (#21)
  • cb2468f fix(aaa): deleting a capped subscriber no longer strands its overlay
  • 012e639 fix(controller): importing as non-root must not die on the CA probe
  • 348244e fix(aaa): leave unmanaged subscribers' enforcement overlays alone
  • c2addbc fix(webui): data-caps client uses fetchWithAuth; input bounds match server
  • 6c8b8f6 fix(aaa): make post-reprovision overlay replay non-fatal
  • 6fa4654 fix(caps): hoist status() queries out of the per-subscriber loop
  • e7fa291 fix(caps): add grants_in_window; drop two dead helpers
  • b4f01ba fix(caps): disabling enforcement now clears every overlay
  • 5eb75a0 fix(caps): stop cross-subscriber leakage in the grant panel
  • 0434621 fix(caps): surface write failures, drop grant form, protect settings draft
  • fc1a2ad fix(caps): fix round 1 -- connection leak, coercion 500s, test gaps
  • 7947075 fix(aaa): guard enforcement convergence against non-controller failures
  • c87dac5 fix(caps): test coverage and boolean logic for NULL handling
  • 1524590 fix(tests): stop the suite running a live metrics sampler
  • 2bdae92 fix(api-keys): survive, and repair, a keys file still in the bare-list shape
  • 9ca5d80 fix(proxy): close the third door into the AAA subscriber base
  • de1c146 fix(aaa): drop a subscriber from the unmanaged list once it becomes ours
  • d52c944 fix(aaa): restore the merge base for a record we do not hold
  • 52f9e41 fix(webui): the wipe notice must name aaa_source among what was not restored
  • b415e3c fix(aaa): debounce the wipe guard, tell its conditions apart, and correct §5
  • eca818e fix(aaa): close the two proxy routes that write only the controller
  • b2b5c08 fix(aaa): merge over the record, not over the controller
  • 06475c5 fix(aaa): stop an orphan annotation poisoning the whole restore
  • 46e073d fix(aaa): say the switch may need re-registering before the plans
  • 678e419 fix(aaa): stop a refused restore wedging the reconciler, and say why
  • a4d6665 fix(aaa): let the circuit decide which line a mint may reuse
  • b72441b fix(aaa): roll back a rejected apply, and stop one bad row killing reconcile
  • c39b7e3 fix(aaa): record a bulk import before pushing it, closing the set
  • a5aff25 fix(aaa): close the delete and mint holes the inversion opened
  • 169b7a2 fix(aaa): surface reactivation_history through get_subscriber
  • 3ccbb2c fix(ledger): three residual ways the daily maintenance could destroy billing data
  • 31c7730 fix(accounting): a quarantined billing record must not be invisible
  • 2bc628c fix(accounting): a retained live population must not starve the drain forever
  • 8e33280 fix(ledger): export what is about to be pruned, not the whole ledger daily
  • 41f7a9b fix(accounting): filter CDRs in SQL so an old date range is reachable
  • 9afd934 fix(ledger): refuse an implausible retention_days instead of deleting a year
  • ebcc8c3 fix(accounting): distinguish a failed CDR fetch from an empty ledger
  • 4b8a749 fix(accounting): count a raised drain cycle as an error too
  • f0bf65f fix(ledger): drain thread's sqlite connection was unusable cross-thread
  • 863b36e fix(accounting): page forward within a cycle instead of re-fetching a static window
  • 53bede3 fix(accounting): review fix wave -- vacuous tests, reset heuristic, late-interim double-credit
  • 7cb61c2 fix(ledger): per-record SAVEPOINT so a DB error on delete can't split a record
  • 9257da3 fix(ledger): make write_records genuinely atomic
  • 8b4a2e0 fix(build): only tracked changes make a build dirty
  • ef6a848 fix(static-ip): narrow the unassign sentinel to framed_ip/subnet_mask
  • ecb0da7 fix(static-ip): check zero-padded addresses, and two tests that could not fail
  • 7084e34 fix(subscribers): a failed session fetch is not an empty account
  • 92c0810 fix(aaa): stop the raw subscriber PUT proxy erasing a static IP
  • b4838f2 fix(static-ip): tell "not mentioned" apart from "unassign me"
  • 1e42a42 fix(static-ip): wire framed_ip/subnet_mask into compute_diff
  • 2d27b9b fix(webui): restore the markup two descriptions lost to a narrow type
  • cc8aa10 fix(typecheck): clear the 16-error backlog exposed by the tsconfig rootDir fix
  • 3dadea1 fix(add-ons): the primary Install button never said Installing…
  • 75e652e fix(add-ons): restore the expander that described what the pack contains
  • 6a4062e fix: the eval appliance HAS a TPM — correcting a wrong premise
  • 9b694ef fix: two error states that lied, and the CPESIM pin
  • d52be84 fix(eval-appliance): find the bundle our own build script produces
  • 5b1d434 fix(aaa): merge subscriber PUT over stored record, not just match
  • 6061b2e fix(1.4.0): whole-branch defects — locator erasure, bulk crash, false alert
  • fa7e334 fix(webui): guard health.radius reads against the 1.4.0 shape
  • cd3e05e fix(health): stop fabricating a radius block in degraded fallbacks
  • 2958fee fix(portal): voucher redemption can finally activate a session
  • 35e8775 fix(aaa): carry locator columns through the upload pipeline, spec-validate the two rewritten bulk tests
  • fa03fd3 fix(aaa): rewrite the two route-level tests Task 3s rewrite broke
  • 9f75262 fix(aaa): delete the cascade planner that never fired
  • 131f376 fix(deps): declare jsonschema/referencing as dev extras
  • 0568042 fix(webui): API Keys page rendered blank on every box; replace two screenshots
  • 6a8b3f8 fix(appliance): clear intermittent first-boot hang with rcu_normal; ship 1.3.0-13
  • d89225f fix(licensing): the three controller paths were missing /v1 and 404d

Performance (2)

  • c29a377 perf(metrics): stop shelling out every 5s for counters we discard (#36)
  • b8c4d3c perf(metrics): stop fetching the whole controller config every tick (#14)

Documentation (57)

  • 84ae8d6 docs: point the dataplane known issue at its real issue number (#49)
  • 7aeebba docs: record the dataplane port-assignment issue and its workaround
  • 9a12835 docs(release): regenerate the appendix against 433b916 (243 commits)
  • 433b916 docs: roll the 1.4.0 doc set to bundle 1.4.0-13 / plugin 0.10.36
  • 75a7bcc docs(release): frame 1.4.0 as GA, with everything prior as one alpha bucket
  • 897c4bb docs(release): append the complete commit record
  • 9e7b755 docs(release): the commit count was stale — 229, not 204
  • 51ed4d4 docs(release): carry the controller and VPP side of 1.4.0 (#43)
  • 7d3dd4f docs(release): remove internal framing and the "shim" terminology
  • 84c7f4b docs(release): bundle 1.4.0-10, and say what the installer now does about statseg
  • efee8aa docs(aaa): correct a comment I generalised from one configuration
  • 236b0ee docs(release): say what the console actually shows for RADIUS and AAA
  • c7ace1e docs(release): 1.4.0 notes — known issues now cover the open set, and Upgrading no longer over-promises
  • d586aff docs(metrics): document all 36 families, and guard against the drift (#34)
  • 8f1e614 docs(lifecycle): mark §4 and §9.3 superseded by the state-envelope restore
  • 10eb38a docs(spec): record the #24 amendments
  • a998128 docs(spec): §5.2's enabled_ts floor is day-granular — state the limit
  • 2ec2311 docs(plan): sub-project E implementation plan
  • dcb9614 docs(spec): sub-project E — data-cap enforcement
  • 0e5682a docs(plan): AAA as system of record (sub-project F)
  • d7eb45c docs(spec): AAA as system of record (sub-project F)
  • 96aeea3 docs(lifecycle): QuantumTouch takes ownership of AAA
  • 8e1f111 docs: state ownership and lifecycle — what the controller must persist
  • 8a6be39 docs(spec): the binding spec described behaviour that was deliberately deleted
  • b186183 docs(plan): accounting ledger (sub-project D)
  • 1aab859 docs(spec): accounting ledger (sub-project D)
  • 3ff8da5 docs(plan): sub-project C — static IP and subscriber sessions
  • a939894 docs(spec): static IP and subscriber sessions (sub-project C)
  • bc4c816 docs: preserve the 1.4.0 port execution ledger; ignore vagrant state
  • 7c96972 docs(artifacts): the _test endpoints are NOT served in production — correction
  • d6b4baf docs(artifacts): correct the health.radius claim — twice wrong
  • 366f931 docs(plan): implementation plan for the controller 1.4.0 port
  • c818b2e docs(spec): the cascade has never fired, and sessions do carry subscriber_id
  • 2504d03 docs(spec): controller 1.4.0 port — design for sub-project A
  • e109e42 docs(artifacts): import the 1.4.0 controller API spec and evaluate it against our tree
  • 50c3bdb docs: direct upload for disconnected boxes; URL path is the orchestrator seam
  • 5163235 docs: rename About to System and reserve it for platform lifecycle
  • 12aeee9 docs: correct -- capacity licences are perpetual, not subscriptions
  • ca3fdbe docs: draw the licence expiry cliff, and free amber for it
  • 2bea687 docs: record the three capacity bands, and two consequences of replace
  • 978203b docs: scope the design to QuantumTouch; hand the store findings off
  • 99699d5 docs: session cap replaces rather than stacks
  • 845b417 docs: nav group is Marketplace, holding Licensing and Add-ons
  • 9e81489 docs: CPESIM need not stay pinned -- the blocker is an unversioned engine API
  • b7a1e27 docs: read-only operator gets an "ask an administrator" fingerprint card
  • 536dee1 docs: machine fingerprint leads the Licensing page
  • fc25bad docs: speed caps replace rather than stack; interface config is a prerequisite
  • 16bcc14 docs: design for the add-ons + entitlements console section
  • 3bbe2f4 docs: publishing instructions for the 1.3.0 docs web implementer
  • b627fa5 docs: state survey ahead of lifecycle management
  • d248b24 docs(grafana): customer guide for the dashboard pack; pack is free and unlicensed
  • bcbaf0c docs: capacity licensing is staged for 1.4.0, not a 1.3.0 capability
  • 19b9f6d docs: correct the licensing documentation — the console flow does not work
  • 2e437fc docs: response to the feature-query interface proposal (#33)
  • 7b9796a docs: re-shoot the console screenshots, and fix two things they caught
  • 68cbb67 docs: update the operator guides for 1.3.0
  • 3027512 docs: review the 19 published QuantumBNG docs against 1.3.0

Tests (14)

  • 56f8baa test(radius): tag lab-dependent tests so a release run can drop them
  • d4707f4 test(aaa): cover the branches that had none, and verify each catches its regression
  • a10af89 test(aaa): prove the reconciler is actually reachable from the drain thread
  • c0b397a test(aaa): pin remove_unmanaged's unreachable-controller ordering
  • dd5741a test(accounting): assert the test drain thread does not outlive its test
  • e4c55ad test(ledger): pin the INSERT OR IGNORE rule at the statement itself
  • d650317 test(accounting): pin the real lag computation, and ship spec 8's second alert
  • 3225513 test(subscribers): cover the session client directly, not through the drawer
  • 12140d1 test(subscribers): replace a vacuous role="alert" check with a real one
  • 17b91b7 test(static-ip): pin the conflict/generic-failure routing to the error code
  • 6fadfa6 test(health): update happy-path fixture to the 1.4.0 aaa shape
  • abbe19b test(aaa): fix stale mode fixture, cover radius rejection
  • 0e75d2a test: a controller double that enforces the real 1.4.0 contract
  • 5457c62 test(webui): repair two stale Dashboard tests and the pool card router context

Build and chores (7)

  • fe8dc75 chore(deps): lock @quantumtouch/core to the v0.10.23 commit
  • da25223 chore(deps): core 0.10.23 for plugin webhook event registration
  • a6ea37e chore(deps): lock @quantumtouch/core to the v0.10.22 commit
  • e63c9d9 chore(deps): core 0.10.22, and a guard so the two pins cannot drift
  • 4cbcab9 chore(deps): quantumtouch-core 0.10.21 — accessible Field labels
  • ab40ce3 chore(bundle): cut 1.4.0-02
  • 54acdd4 chore: ignore .worktrees/

Release (9)

  • 69e614a release: bundle 1.4.0-14, plugin 0.10.37, CPESIM 0.4.18
  • a47b639 release: bundle 1.4.0-13, plugin 0.10.36
  • a79fa2a release: cut installer bundle 1.4.0-12
  • 04ed60a release: bundle 1.4.0-11
  • 44a426a release: plugin 0.10.34 — the version never moved across 1.4.0
  • 2caaaf9 release: bundle 1.4.0-10
  • d4807b8 release: record the bundle 1.4.0-09 version bump that shipped to the rig
  • 1fcf348 release: bundle 1.4.0-04
  • 8673133 release: bundle 1.4.0-03

Other (8)

  • 915dc44 Merge release/1.4.0-13: sessions fetch-failure fix + 1.4.0 doc set
  • c5db7c5 Revert the Pools DNS change: #40 was not a bug, and my test disproved it
  • be425dd Merge support-bundle health counters, snapshot access-port fix, cap caption
  • cd0f367 Merge A-06: per-subscriber raw rate override
  • ae00fbf Merge #24 follow-ups: billing interop, wired cap surfaces, overlay ownership
  • d39660c Merge sub-project E: data-cap enforcement
  • 0f0fc5f Restore installedLinks, capability reload, and backstop poller on Add-ons
  • cc432d3 Merge feat/controller-1.4.0-port: port to controller 1.4.0