Releases: devicechain-io/devicechain
Release list
v0.16.0
Warning
Pre-1.0 release. Until v1.0.0, any release — including a patch — may change
APIs, schemas, or behavior without a compatibility shim.
See Pre-1.0 stability.
What's in v0.16.0
Important
This release contains breaking changes. They are described in the first
bullets below and in full in the upgrade notes.
- A plain helm upgrade from v0.15.x. One migration runs itself as command-delivery starts, adding a column with a default and backfilling existing rows in the same statement — there is nothing to recreate and no data to move by hand. The breaking change in this release is on the device side, not in the upgrade and not in the API.
- Any device that answers a command must now echo the dispatch nonce it was sent. The same command can legitimately be published more than once, and without the nonce an answer to a superseded dispatch was settling the newer one with the older one's outcome. An answer that omits it is refused and kept as a dead letter rather than settling the command — so nothing the device reported is lost. The population this affects is devices built outside the platform, which nothing can enumerate, so watch devicechain_commanddelivery_command_delivery_responses_without_nonce_total after upgrading: it should be zero on a fleet that is fully updated. Devices on the .NET/Unity SDK are fixed by upgrading the SDK.
- Do one thing before you upgrade: check your event-source listener ports for a collision. Two listeners on one port used to kill an ingest transport silently, inside a goroutine, with nothing logged. Binds are now synchronous and fatal, so a collision that has been quietly broken for months will crash-loop the deployment instead of hiding.
- Services now refuse to start on configuration they used to accept and ignore: a misspelled key, an instance root key that is wrong rather than malformed, a shutdown drain window longer than half the pod's grace period, two listeners on one port, and a listener port already in use. Each is safer than the silence it replaces, and each can stop a pod that has been running for months. Two chart details go with them: infrastructure.metrics.httpPort is retired, and infrastructure.shutdown is now written by the chart rather than by hand.
- If you alert on lwm2m-ingest's is_leader, it changes meaning: it is now raised when a replica acquires the lease rather than after it finishes building its term, so the false-leaderless window of up to 30 seconds per bound tenant after a failover disappears. A new is_serving gauge distinguishes a leader still building from a leader actually serving. Eleven metric series are added across the platform and none are renamed or removed.
- A command the platform cannot publish now fails and says so, instead of cycling between queued and sent for days and then recording a timeout that blamed the device. Dead letters for a blocked connector destination now read unprocessable rather than exhausted — update any alert keyed on the old value. Alarm state changes that could not be published are now dead-lettered and counted rather than lost.
- The .NET/Unity SDK carries the command-nonce change; upgrading it is how a device built on it keeps answering commands. The npm packages — @devicechain/client, @devicechain/dashboards, @devicechain/widgets and @devicechain/brand — have no source changes, though @devicechain/widgets moves its maplibre-gl peer range from ^6.6.0 to ^6.7.0, which matters if you pin that dependency yourself.
Full upgrade notes for v0.16.0 →
Changelog
- 760c482: Answer a device replacement's device honestly, or not at all (#992) (@derekadams)
- afadb0c: Answer replaceDevice's replacement.device with the device, not an empty one (#976) (@derekadams)
- f53cb2e: Assert an oversized frame's close code on both paths, not just the lucky one (#1026) (@derekadams)
- 516bc10: Bound how long shutdown can take, and honour the contexts inside it (#1029) (@derekadams)
- c01c7af: Bound the governance refresh rate, not only its concurrency (#988) (@derekadams)
- c071af2: Build a geofence ring once, in core/geo, rather than once on each side (#1004) (@derekadams)
- a947395: Build a service's Prometheus metrics once, not on every start (#1014) (@derekadams)
- db804d5: Build sparkplug-ingest's leader gauge in initialize, not on the start path (#984) (@derekadams)
- 08fba68: Build the secret store from one core constructor that fails closed on an unbuilt backend (#985) (@derekadams)
- 058873f: Capture logs through a shared sink instead of swapping the global logger (#967) (@derekadams)
- e6a4351: Carry the settle-or-not axis in the dead-letter vocabulary (#961) (@derekadams)
- 9cd695b: Check the instance root key against stored secrets when the store is built (#1005) (@derekadams)
- fb1a079: Count the Sparkplug rebirth queue's accepted and dropped requests (#1044) (@derekadams)
- 5e1be26: Decode the instance configuration document strictly, as every other config is (#1033) (@derekadams)
- 3a88ef2: Drop the labels argument NewCounter and NewGauge never read (#1036) (@derekadams)
- 8f95e70: Drop the presented device credential once resolution is done with it (#1006) (@derekadams)
- 8bf4b52: End GraphQL subscription connections at shutdown, and bound an inbound frame (#1008) (@derekadams)
- 4a32615: Fail the HTTP event source's start when it cannot bind, and let it restart (#1003) (@derekadams)
- b8e283f: Freeze the partial-unique-index statement an applied migration builds (#963) (@derekadams)
- a7c1af1: Gate the website's checkable claims (#930) (@derekadams)
- 768dad6: Gate the wiring lines these services could lose silently, and correct four mechanism comments (#1050) (@derekadams)
- 76c12fe: Give a microservice an HTTP mux, a probe registrar and a server it owns (#978) (@derekadams)
- 0d3feb4: Give each microservice its own metrics registry, and serve /metrics from it (#964) (@derekadams)
- f16609e: Infer a blob Content-Type from a closed table, not the host MIME database (#959) (@derekadams)
- cf8447b: Join the Sparkplug lease renewer before releasing the lease (#932) (@derekadams)
- 1f23d60: Let a Microservice built as a struct literal shut down and report its outcome (#989) (@derekadams)
- d0b76e6: Let the schema scanner read a release that spelled its schemas .gql (#1025) (@derekadams)
- 8a51506: Locate an undecodable inbound message instead of archiving it (#1035) (@derekadams)
- e838e05: Make a message reader's one-goroutine contract a checked precondition (#987) (@derekadams)
- 56c31ea: Make the restore drill's negative control fail for the reason it names (#1049) (@derekadams)
- 7fa3d3d: Move the website-claims check out of the public tree (#931) (@derekadams)
- 7c44762: Name every GraphQL schema .graphql, and resolve its endpoint by name (#1022) (@derekadams)
- fc82c18: Pace a consumer read loop's retries instead of retrying at full speed (#1009) (@derekadams)
- 85817ce: Pin a userclient HTTP client's bearer to one host (#986) (@derekadams)
- 1be61c8: Pin every container image a script pulls by digest (#1007) (@derekadams)
- 89b5493: Pin that a mutation whose audit-journal write fails reports that failure (#993) (@derekadams)
- 7d385e6: Prepare the v0.16.0 release notes and upgrade guidance (#1051) (@derekadams)
- 95b9a50: Read the guard's verdict when a device answers a command (#934) (@derekadams)
- 6060b7d: Record an alarm state-change event that could not be published (#1017) (@derekadams)
- 44bf8bb: Refuse a metric name that cannot appear in a Prometheus metric name (#1032) (@derekadams)
- 8d7fa61: Refuse a start after a stop instead of admitting one that cannot work (#1040) (@derekadams)
- fbc1f63: Refuse a statement the tenant-scope callback cannot classify (#965) (@derekadams)
- 4a04a45: Refuse an alerting rule that can never return nothing (#1021) (@derekadams)
- 5edc61d: Refuse any registration on net/http's package-global mux (#999) (@derekadams)
- 6310481: Refuse colliding listener ports in config, and let ingest set its own timeouts (#1020) (@derekadams)
- 15d3030: Refuse out-of-range degrees in a ring, and drop the fail-open crossing wrapper (#960) (@derekadams)
- 8ed21b0: Refuse work constructed in the wrong ...
v0.16.0-rc.1
Warning
Pre-1.0 release. Until v1.0.0, any release — including a patch — may change
APIs, schemas, or behavior without a compatibility shim.
See Pre-1.0 stability.
What's in v0.16.0
Important
This release contains breaking changes. They are described in the first
bullets below and in full in the upgrade notes.
- A plain helm upgrade from v0.15.x. One migration runs itself as command-delivery starts, adding a column with a default and backfilling existing rows in the same statement — there is nothing to recreate and no data to move by hand. The breaking change in this release is on the device side, not in the upgrade and not in the API.
- Any device that answers a command must now echo the dispatch nonce it was sent. The same command can legitimately be published more than once, and without the nonce an answer to a superseded dispatch was settling the newer one with the older one's outcome. An answer that omits it is refused and kept as a dead letter rather than settling the command — so nothing the device reported is lost. The population this affects is devices built outside the platform, which nothing can enumerate, so watch devicechain_commanddelivery_command_delivery_responses_without_nonce_total after upgrading: it should be zero on a fleet that is fully updated. Devices on the .NET/Unity SDK are fixed by upgrading the SDK.
- Do one thing before you upgrade: check your event-source listener ports for a collision. Two listeners on one port used to kill an ingest transport silently, inside a goroutine, with nothing logged. Binds are now synchronous and fatal, so a collision that has been quietly broken for months will crash-loop the deployment instead of hiding.
- Services now refuse to start on configuration they used to accept and ignore: a misspelled key, an instance root key that is wrong rather than malformed, a shutdown drain window longer than half the pod's grace period, two listeners on one port, and a listener port already in use. Each is safer than the silence it replaces, and each can stop a pod that has been running for months. Two chart details go with them: infrastructure.metrics.httpPort is retired, and infrastructure.shutdown is now written by the chart rather than by hand.
- If you alert on lwm2m-ingest's is_leader, it changes meaning: it is now raised when a replica acquires the lease rather than after it finishes building its term, so the false-leaderless window of up to 30 seconds per bound tenant after a failover disappears. A new is_serving gauge distinguishes a leader still building from a leader actually serving. Eleven metric series are added across the platform and none are renamed or removed.
- A command the platform cannot publish now fails and says so, instead of cycling between queued and sent for days and then recording a timeout that blamed the device. Dead letters for a blocked connector destination now read unprocessable rather than exhausted — update any alert keyed on the old value. Alarm state changes that could not be published are now dead-lettered and counted rather than lost.
- The .NET/Unity SDK carries the command-nonce change; upgrading it is how a device built on it keeps answering commands. The npm packages — @devicechain/client, @devicechain/dashboards, @devicechain/widgets and @devicechain/brand — have no source changes, though @devicechain/widgets moves its maplibre-gl peer range from ^6.6.0 to ^6.7.0, which matters if you pin that dependency yourself.
Full upgrade notes for v0.16.0 →
Changelog
- 760c482: Answer a device replacement's device honestly, or not at all (#992) (@derekadams)
- afadb0c: Answer replaceDevice's replacement.device with the device, not an empty one (#976) (@derekadams)
- f53cb2e: Assert an oversized frame's close code on both paths, not just the lucky one (#1026) (@derekadams)
- 516bc10: Bound how long shutdown can take, and honour the contexts inside it (#1029) (@derekadams)
- c01c7af: Bound the governance refresh rate, not only its concurrency (#988) (@derekadams)
- c071af2: Build a geofence ring once, in core/geo, rather than once on each side (#1004) (@derekadams)
- a947395: Build a service's Prometheus metrics once, not on every start (#1014) (@derekadams)
- db804d5: Build sparkplug-ingest's leader gauge in initialize, not on the start path (#984) (@derekadams)
- 08fba68: Build the secret store from one core constructor that fails closed on an unbuilt backend (#985) (@derekadams)
- 058873f: Capture logs through a shared sink instead of swapping the global logger (#967) (@derekadams)
- e6a4351: Carry the settle-or-not axis in the dead-letter vocabulary (#961) (@derekadams)
- 9cd695b: Check the instance root key against stored secrets when the store is built (#1005) (@derekadams)
- fb1a079: Count the Sparkplug rebirth queue's accepted and dropped requests (#1044) (@derekadams)
- 5e1be26: Decode the instance configuration document strictly, as every other config is (#1033) (@derekadams)
- 3a88ef2: Drop the labels argument NewCounter and NewGauge never read (#1036) (@derekadams)
- 8f95e70: Drop the presented device credential once resolution is done with it (#1006) (@derekadams)
- 8bf4b52: End GraphQL subscription connections at shutdown, and bound an inbound frame (#1008) (@derekadams)
- 4a32615: Fail the HTTP event source's start when it cannot bind, and let it restart (#1003) (@derekadams)
- b8e283f: Freeze the partial-unique-index statement an applied migration builds (#963) (@derekadams)
- a7c1af1: Gate the website's checkable claims (#930) (@derekadams)
- 768dad6: Gate the wiring lines these services could lose silently, and correct four mechanism comments (#1050) (@derekadams)
- 76c12fe: Give a microservice an HTTP mux, a probe registrar and a server it owns (#978) (@derekadams)
- 0d3feb4: Give each microservice its own metrics registry, and serve /metrics from it (#964) (@derekadams)
- f16609e: Infer a blob Content-Type from a closed table, not the host MIME database (#959) (@derekadams)
- cf8447b: Join the Sparkplug lease renewer before releasing the lease (#932) (@derekadams)
- 1f23d60: Let a Microservice built as a struct literal shut down and report its outcome (#989) (@derekadams)
- d0b76e6: Let the schema scanner read a release that spelled its schemas .gql (#1025) (@derekadams)
- 8a51506: Locate an undecodable inbound message instead of archiving it (#1035) (@derekadams)
- e838e05: Make a message reader's one-goroutine contract a checked precondition (#987) (@derekadams)
- 56c31ea: Make the restore drill's negative control fail for the reason it names (#1049) (@derekadams)
- 7fa3d3d: Move the website-claims check out of the public tree (#931) (@derekadams)
- 7c44762: Name every GraphQL schema .graphql, and resolve its endpoint by name (#1022) (@derekadams)
- fc82c18: Pace a consumer read loop's retries instead of retrying at full speed (#1009) (@derekadams)
- 85817ce: Pin a userclient HTTP client's bearer to one host (#986) (@derekadams)
- 1be61c8: Pin every container image a script pulls by digest (#1007) (@derekadams)
- 89b5493: Pin that a mutation whose audit-journal write fails reports that failure (#993) (@derekadams)
- 7d385e6: Prepare the v0.16.0 release notes and upgrade guidance (#1051) (@derekadams)
- 95b9a50: Read the guard's verdict when a device answers a command (#934) (@derekadams)
- 6060b7d: Record an alarm state-change event that could not be published (#1017) (@derekadams)
- 44bf8bb: Refuse a metric name that cannot appear in a Prometheus metric name (#1032) (@derekadams)
- 8d7fa61: Refuse a start after a stop instead of admitting one that cannot work (#1040) (@derekadams)
- fbc1f63: Refuse a statement the tenant-scope callback cannot classify (#965) (@derekadams)
- 4a04a45: Refuse an alerting rule that can never return nothing (#1021) (@derekadams)
- 5edc61d: Refuse any registration on net/http's package-global mux (#999) (@derekadams)
- 6310481: Refuse colliding listener ports in config, and let ingest set its own timeouts (#1020) (@derekadams)
- 15d3030: Refuse out-of-range degrees in a ring, and drop the fail-open crossing wrapper (#960) (@derekadams)
- 8ed21b0: Refuse work constructed in the wrong ...
v0.15.0
Warning
Pre-1.0 release. Until v1.0.0, any release — including a patch — may change
APIs, schemas, or behavior without a compatibility shim.
See Pre-1.0 stability.
What's in v0.15.0
Important
This release contains breaking changes. They are described in the first
bullets below and in full in the upgrade notes.
- A plain helm upgrade from v0.14.x — nothing to recreate, no data to migrate by hand, and the new migrations run themselves as the services start. The breaking changes in this release are in the API and in outbound network access, not in the upgrade: if you run the platform and call it only through the console, there is nothing you need to do.
- Update operations no longer replace the whole record. Previously a field you left out of an update was erased; now a field you do not mention is left exactly as it was, and clearing a value takes an explicit null. The request is a new shape that no longer carries the record's own name, so applications calling the API directly must drop that name and regenerate their client code — a request in the old shape is refused outright rather than half-applied. The one case that changes quietly is an application that cleared a value by leaving the field out: it will now keep the old value instead.
- Outbound connections to private addresses are now refused, and this one can surprise you. Notification webhooks, SMTP relays and connector HTTP calls are blocked from reaching loopback, private, carrier-NAT, link-local and cloud metadata addresses, and a blocked destination is treated as final rather than retried. If your alarm mail goes through a relay inside the cluster, it will stop being delivered until you list that address under the new egress allow-list. Destinations on the public internet are unaffected.
- The id on a stored event is now the event's own identifier rather than a value assembled from the device, type and timestamp, so ids saved from an earlier release no longer match anything. The previous form was not unique — two readings taken at the same instant produced the same id — so a client that treated it as a key was silently merging rows.
- If you run the MCP server, two things need your attention: a resource URL with a trailing slash is now refused at startup rather than quietly mismatching, and the protected-resource metadata has moved to the location the specification actually defines. If you terminate ingress yourself, that path needs a route. Separately, two configuration keys are gone from event-sources: a
debugkey inside aneventSourcesentry must be removed before the service will start, andinboundEventBatchingis retired more gently — stripped at load with a warning. - Commands now go out the moment they are enqueued instead of waiting for the next sweep, and how often that sweep runs is yours to set. Also new: dead letters you can actually read and query, a reporting view for pointing a BI tool at your telemetry, parent/child hierarchy for assets and a way to replace a device, bulk alarm acknowledgement, and a per-tenant console language.
- The published packages are unchanged. @devicechain/client, @devicechain/dashboards, @devicechain/widgets, @devicechain/brand and the DeviceChain.Sdk package for .NET and Unity carry no source changes in this release — but if your own code sends update mutations through them, that is your code to regenerate.
Full upgrade notes for v0.15.0 →
Changelog
- 47ced59: Bound the notification dispatch instead of describing it as bounded (#899) (@derekadams)
- ccd5f98: Check that a migration can survive being run twice, because one cannot (#869) (@derekadams)
- d6acb7f: Derive the widget config panel's FIELDS from the option schema, and gate that it writes them (#889) (@derekadams)
- cc679b6: Dispatch a command when it is enqueued, not on the next sweep tick (#919) (@derekadams)
- 905f7ed: Gate device positions on the SQL surface, and give an event an id that is one (#902) (@derekadams)
- 596799a: Give a declared facet somewhere to put its value (#888) (@derekadams)
- abe20f2: Give a profile, a connector and a provider their rename, and convert the last three full-replace updates (#907) (@derekadams)
- 4875a14: Give an asset a place in a hierarchy, and a device a way to be replaced (#894) (@derekadams)
- b496334: Give dcctl's image build the network mode the script beside it already had (#909) (@derekadams)
- a58e503: Give every area the erasure fence its ack already claimed (#876) (@derekadams)
- a790e23: Give the telemetry store a read surface a BI tool can be pointed at (#893) (@derekadams)
- 9c2fe5d: Give the three consumers that gave up silently somewhere to put it (#878) (@derekadams)
- 93dd392: Give the three unguardable egress paths a boundary, and say what it cannot do (#872) (@derekadams)
- 89305fc: Keep the audit journal through a purge, and destroy the people in it (#877) (@derekadams)
- 4e714d8: Let DETECT stand by, and say which replica actually did the eviction (#892) (@derekadams)
- c0ad506: Let a dashboard be renamed without resending its whole definition (#905) (@derekadams)
- ca1d762: Let a tenant say which language its console opens in (#891) (@derekadams)
- 8a27a11: Let an asset type say what its assets carry, and version that statement (#895) (@derekadams)
- 460a8a6: Let an operator choose the delivery sweep's cadence (#917) (@derekadams)
- f9f602b: Let an ordinary member open a dashboard, which the read-only baseline never allowed (#873) (@derekadams)
- ca0cf71: Let eight more updates leave alone what the caller did not mention (#896) (@derekadams)
- 35a2986: Let seven more updates leave alone what the caller did not mention (#890) (@derekadams)
- 4ad63f9: Let the pull-request gate be the bumper's notification (#886) (@derekadams)
- 73efffa: Let user-management's five updates change one field without erasing the rest (#906) (@derekadams)
- d25a72a: Localize the viewer nobody localized, and enrol it in the gate that missed it (#887) (@derekadams)
- 8d18f30: Make DETECT consult the lease it has been holding all along (#875) (@derekadams)
- bf52342: Make the dead letters readable, so the record is one somebody can consult (#879) (@derekadams)
- 02f36bf: Name v0.15.0, and fix the two things the cut found (#920) (@derekadams)
- aeaf637: Notice when the presence tap never connected, and stop reporting ready with no validator (#901) (@derekadams)
- 8ef7801: Prove the callout ACCEPTS a credential, not only that it refuses one (#916) (@derekadams)
- 7ff8fb7: Put the release's highlights in the release notes, not just its commits (#922) (@derekadams)
- 55b4a4b: Re-cut the baseline that could not survive its own replay, before GA makes that permanent (#874) (@derekadams)
- 6ca1deb: Refuse a tenant destination at the dial, where DNS cannot get a second answer (#870) (@derekadams)
- f0ab53d: Rendered alarm keys, bulk acknowledge, and the nil-variant class (#881) (@derekadams)
- 658df91: Route the whole OAuth discovery walk, not just its first hop (#900) (@derekadams)
- 4e50f3f: Run the commands the docs tell a reader to run (#897) (@derekadams)
- 2f10773: Say that provenance is attached, now that it is (#868) (@derekadams)
- 091f7f4: Say the page's language, and stop blaming the password for an outage (#898) (@derekadams)
- 94a500a: Segment by the column that is read, derive the CI matrix, gate the license (#885) (@derekadams)
- b11a061: Settle a lost answer, add the openai-compatible kind, and ratchet MCP tool risk (#884) (@derekadams)
- ca562f2: Share the partial-update harness, so the next seven conversions cannot each rewrite it (#903) (@derekadams)
- 887e580: Stop a notification edit from erasing the fields it did not mention (#904) (@derekadams)
- bb64075: Stop promising two things the code does not do (#871) (@derekadams)
- b4ec013: The quickstart, the transport matrix, and a gate that makes docs:version safe (#882) (@derekadams)
- 4b9f910: Unfreeze the base-image pin, and scan the frontend (#880) (@derekadams)
- 195f838: Wire the SDL-default guard everywhere, and retire the rule the conversion made unreachable (#908) (@derekadams)
- 53b92a3: Write the release-notes header outside the checkout, whe...
v0.15.0-rc.2
Warning
Pre-1.0 release. Until v1.0.0, any release — including a patch — may change
APIs, schemas, or behavior without a compatibility shim.
See Pre-1.0 stability.
What's in v0.15.0
Important
This release contains breaking changes. They are described in the first
bullets below and in full in the upgrade notes.
- A plain helm upgrade from v0.14.x — nothing to recreate, no data to migrate by hand, and the new migrations run themselves as the services start. The breaking changes in this release are in the API and in outbound network access, not in the upgrade: if you run the platform and call it only through the console, there is nothing you need to do.
- Update operations no longer replace the whole record. Previously a field you left out of an update was erased; now a field you do not mention is left exactly as it was, and clearing a value takes an explicit null. The request is a new shape that no longer carries the record's own name, so applications calling the API directly must drop that name and regenerate their client code — a request in the old shape is refused outright rather than half-applied. The one case that changes quietly is an application that cleared a value by leaving the field out: it will now keep the old value instead.
- Outbound connections to private addresses are now refused, and this one can surprise you. Notification webhooks, SMTP relays and connector HTTP calls are blocked from reaching loopback, private, carrier-NAT, link-local and cloud metadata addresses, and a blocked destination is treated as final rather than retried. If your alarm mail goes through a relay inside the cluster, it will stop being delivered until you list that address under the new egress allow-list. Destinations on the public internet are unaffected.
- The id on a stored event is now the event's own identifier rather than a value assembled from the device, type and timestamp, so ids saved from an earlier release no longer match anything. The previous form was not unique — two readings taken at the same instant produced the same id — so a client that treated it as a key was silently merging rows.
- If you run the MCP server, two things need your attention: a resource URL with a trailing slash is now refused at startup rather than quietly mismatching, and the protected-resource metadata has moved to the location the specification actually defines. If you terminate ingress yourself, that path needs a route. Separately, two configuration keys are gone from event-sources: a
debugkey inside aneventSourcesentry must be removed before the service will start, andinboundEventBatchingis retired more gently — stripped at load with a warning. - Commands now go out the moment they are enqueued instead of waiting for the next sweep, and how often that sweep runs is yours to set. Also new: dead letters you can actually read and query, a reporting view for pointing a BI tool at your telemetry, parent/child hierarchy for assets and a way to replace a device, bulk alarm acknowledgement, and a per-tenant console language.
- The published packages are unchanged. @devicechain/client, @devicechain/dashboards, @devicechain/widgets, @devicechain/brand and the DeviceChain.Sdk package for .NET and Unity carry no source changes in this release — but if your own code sends update mutations through them, that is your code to regenerate.
Full upgrade notes for v0.15.0 →
Changelog
- 47ced59: Bound the notification dispatch instead of describing it as bounded (#899) (@derekadams)
- ccd5f98: Check that a migration can survive being run twice, because one cannot (#869) (@derekadams)
- d6acb7f: Derive the widget config panel's FIELDS from the option schema, and gate that it writes them (#889) (@derekadams)
- cc679b6: Dispatch a command when it is enqueued, not on the next sweep tick (#919) (@derekadams)
- 905f7ed: Gate device positions on the SQL surface, and give an event an id that is one (#902) (@derekadams)
- 596799a: Give a declared facet somewhere to put its value (#888) (@derekadams)
- abe20f2: Give a profile, a connector and a provider their rename, and convert the last three full-replace updates (#907) (@derekadams)
- 4875a14: Give an asset a place in a hierarchy, and a device a way to be replaced (#894) (@derekadams)
- b496334: Give dcctl's image build the network mode the script beside it already had (#909) (@derekadams)
- a58e503: Give every area the erasure fence its ack already claimed (#876) (@derekadams)
- a790e23: Give the telemetry store a read surface a BI tool can be pointed at (#893) (@derekadams)
- 9c2fe5d: Give the three consumers that gave up silently somewhere to put it (#878) (@derekadams)
- 93dd392: Give the three unguardable egress paths a boundary, and say what it cannot do (#872) (@derekadams)
- 89305fc: Keep the audit journal through a purge, and destroy the people in it (#877) (@derekadams)
- 4e714d8: Let DETECT stand by, and say which replica actually did the eviction (#892) (@derekadams)
- c0ad506: Let a dashboard be renamed without resending its whole definition (#905) (@derekadams)
- ca1d762: Let a tenant say which language its console opens in (#891) (@derekadams)
- 8a27a11: Let an asset type say what its assets carry, and version that statement (#895) (@derekadams)
- 460a8a6: Let an operator choose the delivery sweep's cadence (#917) (@derekadams)
- f9f602b: Let an ordinary member open a dashboard, which the read-only baseline never allowed (#873) (@derekadams)
- ca0cf71: Let eight more updates leave alone what the caller did not mention (#896) (@derekadams)
- 35a2986: Let seven more updates leave alone what the caller did not mention (#890) (@derekadams)
- 4ad63f9: Let the pull-request gate be the bumper's notification (#886) (@derekadams)
- 73efffa: Let user-management's five updates change one field without erasing the rest (#906) (@derekadams)
- d25a72a: Localize the viewer nobody localized, and enrol it in the gate that missed it (#887) (@derekadams)
- 8d18f30: Make DETECT consult the lease it has been holding all along (#875) (@derekadams)
- bf52342: Make the dead letters readable, so the record is one somebody can consult (#879) (@derekadams)
- 02f36bf: Name v0.15.0, and fix the two things the cut found (#920) (@derekadams)
- aeaf637: Notice when the presence tap never connected, and stop reporting ready with no validator (#901) (@derekadams)
- 8ef7801: Prove the callout ACCEPTS a credential, not only that it refuses one (#916) (@derekadams)
- 7ff8fb7: Put the release's highlights in the release notes, not just its commits (#922) (@derekadams)
- 55b4a4b: Re-cut the baseline that could not survive its own replay, before GA makes that permanent (#874) (@derekadams)
- 6ca1deb: Refuse a tenant destination at the dial, where DNS cannot get a second answer (#870) (@derekadams)
- f0ab53d: Rendered alarm keys, bulk acknowledge, and the nil-variant class (#881) (@derekadams)
- 658df91: Route the whole OAuth discovery walk, not just its first hop (#900) (@derekadams)
- 4e50f3f: Run the commands the docs tell a reader to run (#897) (@derekadams)
- 2f10773: Say that provenance is attached, now that it is (#868) (@derekadams)
- 091f7f4: Say the page's language, and stop blaming the password for an outage (#898) (@derekadams)
- 94a500a: Segment by the column that is read, derive the CI matrix, gate the license (#885) (@derekadams)
- b11a061: Settle a lost answer, add the openai-compatible kind, and ratchet MCP tool risk (#884) (@derekadams)
- ca562f2: Share the partial-update harness, so the next seven conversions cannot each rewrite it (#903) (@derekadams)
- 887e580: Stop a notification edit from erasing the fields it did not mention (#904) (@derekadams)
- bb64075: Stop promising two things the code does not do (#871) (@derekadams)
- b4ec013: The quickstart, the transport matrix, and a gate that makes docs:version safe (#882) (@derekadams)
- 4b9f910: Unfreeze the base-image pin, and scan the frontend (#880) (@derekadams)
- 195f838: Wire the SDL-default guard everywhere, and retire the rule the conversion made unreachable (#908) (@derekadams)
- 53b92a3: Write the release-notes header outside the checkout, whe...
v0.14.0
Warning
Pre-1.0 release. Until v1.0.0, any release — including a patch — may change
APIs, schemas, or behavior without a compatibility shim. Check for a
"Breaking changes" section below before upgrading.
See Pre-1.0 stability.
Changelog
- c895a7e: Ask every door the platform serves, and make the drill fail when they stop answering (#840) (@derekadams)
- c1a0245: Build the packages, and make our own apps eat what we would publish (#858) (@derekadams)
- 0fef3c1: Bump the go-minor-patch group, and carry the workspace sum with it (#854) (@derekadams)
- c4f18ae: Check the packages as tarballs, and tell people how to install them (#861) (@derekadams)
- 5964122: Count "one of every entity" instead of claiming it (#845) (@derekadams)
- 7d6bb47: Derive the baseline the drill upgrades from, instead of naming one (#842) (@derekadams)
- 1a88d62: Give the NuGet package an identity before it can be published (#852) (@derekadams)
- c924ce1: Give the package an icon, and make CI open the package it builds (#853) (@derekadams)
- 2dd4376: Grant the upgrade gate the permission its own nested job declares (#865) (@derekadams)
- cb6f6d1: Let the release tag publish the packages, and make it prove it did (#860) (@derekadams)
- 1cd05bd: Let the upgrade drill install a baseline that predates the chart move (#867) (@derekadams)
- 8f647a1: Make the upgrade drill a check that can actually block a merge (#844) (@derekadams)
- 634bd5d: Pin the one stored document that is spelled in live models (#839) (@derekadams)
- 4c08ba4: Prove the packages work for somebody who is not us, and fix what that found (#859) (@derekadams)
- a2bc09f: Publish the SDK with OIDC too, because the API-key path just closed (#863) (@derekadams)
- 1a47521: Record which cluster an instance lives in, and stop guessing at it (#862) (@derekadams)
- 751c5b0: Retry the govulncheck install, since one blip reds twenty-one jobs (#843) (@derekadams)
- 2c5cca3: Run the upgrade drill when the risk appears, not once per release (#841) (@derekadams)
- a365bf6: Say what v0.14.0 is for, and stop fetching CNPG charts through a dead domain (#864) (@derekadams)
- 718c696: Stop the operator Dockerfile contradicting itself about what it builds (#855) (@derekadams)
- e4ce047: Take the bundler's dialect out of the map widget, before it ships (#856) (@derekadams)
- b189bc3: chore(ci): bump actions/setup-java from 5.7.0 to 6.0.0 (#850) (@dependabot[bot])
- cfed916: chore(ci): bump the actions group with 3 updates (#849) (@dependabot[bot])
- 7e581ad: chore(deps): bump golang (#846) (@dependabot[bot])
- 680e754: chore(deps): bump nginxinc/nginx-unprivileged in /frontend (#847) (@dependabot[bot])
- ef1d5c9: chore(deps): bump the npm-minor-patch group across 1 directory with 9 updates (#848) (@dependabot[bot])
v0.14.0-rc.1
Warning
Pre-1.0 release. Until v1.0.0, any release — including a patch — may change
APIs, schemas, or behavior without a compatibility shim. Check for a
"Breaking changes" section below before upgrading.
See Pre-1.0 stability.
Changelog
- c895a7e: Ask every door the platform serves, and make the drill fail when they stop answering (#840) (@derekadams)
- c1a0245: Build the packages, and make our own apps eat what we would publish (#858) (@derekadams)
- 0fef3c1: Bump the go-minor-patch group, and carry the workspace sum with it (#854) (@derekadams)
- c4f18ae: Check the packages as tarballs, and tell people how to install them (#861) (@derekadams)
- 5964122: Count "one of every entity" instead of claiming it (#845) (@derekadams)
- 7d6bb47: Derive the baseline the drill upgrades from, instead of naming one (#842) (@derekadams)
- 1a88d62: Give the NuGet package an identity before it can be published (#852) (@derekadams)
- c924ce1: Give the package an icon, and make CI open the package it builds (#853) (@derekadams)
- 2dd4376: Grant the upgrade gate the permission its own nested job declares (#865) (@derekadams)
- cb6f6d1: Let the release tag publish the packages, and make it prove it did (#860) (@derekadams)
- 1cd05bd: Let the upgrade drill install a baseline that predates the chart move (#867) (@derekadams)
- 8f647a1: Make the upgrade drill a check that can actually block a merge (#844) (@derekadams)
- 634bd5d: Pin the one stored document that is spelled in live models (#839) (@derekadams)
- 4c08ba4: Prove the packages work for somebody who is not us, and fix what that found (#859) (@derekadams)
- a2bc09f: Publish the SDK with OIDC too, because the API-key path just closed (#863) (@derekadams)
- 1a47521: Record which cluster an instance lives in, and stop guessing at it (#862) (@derekadams)
- 751c5b0: Retry the govulncheck install, since one blip reds twenty-one jobs (#843) (@derekadams)
- 2c5cca3: Run the upgrade drill when the risk appears, not once per release (#841) (@derekadams)
- a365bf6: Say what v0.14.0 is for, and stop fetching CNPG charts through a dead domain (#864) (@derekadams)
- 718c696: Stop the operator Dockerfile contradicting itself about what it builds (#855) (@derekadams)
- e4ce047: Take the bundler's dialect out of the map widget, before it ships (#856) (@derekadams)
- b189bc3: chore(ci): bump actions/setup-java from 5.7.0 to 6.0.0 (#850) (@dependabot[bot])
- cfed916: chore(ci): bump the actions group with 3 updates (#849) (@dependabot[bot])
- 7e581ad: chore(deps): bump golang (#846) (@dependabot[bot])
- 680e754: chore(deps): bump nginxinc/nginx-unprivileged in /frontend (#847) (@dependabot[bot])
- ef1d5c9: chore(deps): bump the npm-minor-patch group across 1 directory with 9 updates (#848) (@dependabot[bot])
v0.13.0
Warning
Pre-1.0 release. Until v1.0.0, any release — including a patch — may change
APIs, schemas, or behavior without a compatibility shim. Check for a
"Breaking changes" section below before upgrading.
See Pre-1.0 stability.
Changelog
- 4504c9f: Answer a containment question in bounded time, and say what the geofence caps actually bound (#830) (@derekadams)
- 5ffdffe: Delete an encoder nothing used, and bound delivery by a set a tenant can hold (#834) (@derekadams)
- 681d292: Deliver fence geometry by content address, so a fence set cannot outgrow the wire (#828) (@derekadams)
- 0857d78: Give a control's boundary the contrast a control's boundary needs (#816) (#816) (@derekadams)
- eefa467: Ignore the maintainer scratch directory, so
git add -Acannot publish it (#833) (@derekadams) - c86811c: Make a fence's size a function of its shape, not of how its numbers were typed (#817) (@derekadams)
- 16e44db: Make the geofence caps a tier setting, with maxima that are platform properties (#831) (@derekadams)
- 6ee3ec3: Measure the changelog from the last release, not from the last attempt (#815) (@derekadams)
- 53b8ccd: Meter a tenant's geofences against its plan, refusing only what makes things worse (#832) (@derekadams)
- b7205af: Mint a fence-set version only when the fence set changed, and measure what never shrinks (#829) (@derekadams)
- 9d8b42c: Move the whole workspace off a protobuf pseudo-version onto the release (#826) (@derekadams)
- 699a212: Name v0.13.0, and say what the geofence limits now do (#837) (@derekadams)
- fb35ad3: Repair the geofence history an upgrade left pointing nowhere (#838) (@derekadams)
- c0c351a: Run the integration tests instead of only compiling them (#836) (@derekadams)
- b291db1: Say why the inactivity sweep cannot be indexed, having measured it (#835) (@derekadams)
- da91053: Store fence geometry once, addressed by content, not once per version (#827) (@derekadams)
- c3de5fb: chore(ci): bump the actions group with 3 updates (#821) (@dependabot[bot])
- 2080b8f: chore(deps): bump distroless/static in /backend/k8s (#819) (@dependabot[bot])
- 0f70fe7: chore(deps): bump the go-minor-patch group across 9 directories with 14 updates (#822) (@dependabot[bot])
- 1e16716: chore(deps): bump the npm-minor-patch group across 1 directory with 4 updates (#820) (@dependabot[bot])
v0.13.0-rc.1
Warning
Pre-1.0 release. Until v1.0.0, any release — including a patch — may change
APIs, schemas, or behavior without a compatibility shim. Check for a
"Breaking changes" section below before upgrading.
See Pre-1.0 stability.
Changelog
- 4504c9f: Answer a containment question in bounded time, and say what the geofence caps actually bound (#830) (@derekadams)
- 5ffdffe: Delete an encoder nothing used, and bound delivery by a set a tenant can hold (#834) (@derekadams)
- 681d292: Deliver fence geometry by content address, so a fence set cannot outgrow the wire (#828) (@derekadams)
- 0857d78: Give a control's boundary the contrast a control's boundary needs (#816) (#816) (@derekadams)
- eefa467: Ignore the maintainer scratch directory, so
git add -Acannot publish it (#833) (@derekadams) - c86811c: Make a fence's size a function of its shape, not of how its numbers were typed (#817) (@derekadams)
- 16e44db: Make the geofence caps a tier setting, with maxima that are platform properties (#831) (@derekadams)
- 6ee3ec3: Measure the changelog from the last release, not from the last attempt (#815) (@derekadams)
- 53b8ccd: Meter a tenant's geofences against its plan, refusing only what makes things worse (#832) (@derekadams)
- b7205af: Mint a fence-set version only when the fence set changed, and measure what never shrinks (#829) (@derekadams)
- 9d8b42c: Move the whole workspace off a protobuf pseudo-version onto the release (#826) (@derekadams)
- 699a212: Name v0.13.0, and say what the geofence limits now do (#837) (@derekadams)
- fb35ad3: Repair the geofence history an upgrade left pointing nowhere (#838) (@derekadams)
- c0c351a: Run the integration tests instead of only compiling them (#836) (@derekadams)
- b291db1: Say why the inactivity sweep cannot be indexed, having measured it (#835) (@derekadams)
- da91053: Store fence geometry once, addressed by content, not once per version (#827) (@derekadams)
- c3de5fb: chore(ci): bump the actions group with 3 updates (#821) (@dependabot[bot])
- 2080b8f: chore(deps): bump distroless/static in /backend/k8s (#819) (@dependabot[bot])
- 0f70fe7: chore(deps): bump the go-minor-patch group across 9 directories with 14 updates (#822) (@dependabot[bot])
- 1e16716: chore(deps): bump the npm-minor-patch group across 1 directory with 4 updates (#820) (@dependabot[bot])
v0.12.1
Warning
Pre-1.0 release. Until v1.0.0, any release — including a patch — may change
APIs, schemas, or behavior without a compatibility shim. Check for a
"Breaking changes" section below before upgrading.
See Pre-1.0 stability.
Changelog
- 695c468: Stop emulating a JavaScript build that emits the same bytes on every architecture (#806) (@derekadams)
- c48ce6c: chore(ci): bump the actions group across 1 directory with 4 updates (#808) (@derekadams)
- 220bbea: chore(deps): bump the npm-minor-patch group across 1 directory with 10 updates (#807) (@derekadams)
- c5b7267: Bump the go-minor-patch group, and regenerate the go.sum files Dependabot cannot reach (#809) (@derekadams)
- aeaef10: Stop the Unity package citing a repo its readers cannot open (#810) (@derekadams)
- 34bdf8c: Sweep the fleet in one statement instead of one query per device (#811) (@derekadams)
- e4f5685: Give each status colour an ink and a fill, because one value cannot be both (#812) (@derekadams)
- 208c92c: Name v0.12.1, and say plainly that there is nothing to do (#813) (@derekadams)
- 8325f27: Complete the workspace sum, and fail a PR for it instead of a release (#814) (@derekadams)
The generated changelog covered only the final commit: goreleaser walks back from the tag's parent, and v0.12.1-rc.1 sits there because the first candidate failed and was re-cut. Replaced by hand with the full v0.12.0..v0.12.1 range.
v0.12.1-rc.2
Warning
Pre-1.0 release. Until v1.0.0, any release — including a patch — may change
APIs, schemas, or behavior without a compatibility shim. Check for a
"Breaking changes" section below before upgrading.
See Pre-1.0 stability.
Changelog
- 8325f27: Complete the workspace sum, and fail a PR for it instead of a release (#814) (@derekadams)