Skip to content

Releases: sudoitir/rahdar

2026.10.53

2026.10.53 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 14 Oct 14:39
8095202

Fixed

  • Apply a sooner schedule as soon as its setting changes (3f203acd)

    Changing a job's schedule took effect only after the run already planned under
    the old one: moving the audit purge from its daily 03:30 UTC run to hourly still
    waited for 03:30. Every replica now re-arms its waiting jobs when a setting
    changes, so a schedule that comes due sooner applies at once. A schedule moved
    later takes over after the next run, and a job that has not run yet keeps its
    planned time when an unrelated setting changes.

2026.10.52

2026.10.52 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 14 Oct 13:42
277aa01

Fixed

  • Describe each flow node with a supported ARIA attribute (7c9b030b)

    A flow node carried its sentence (role, health, rates) in aria-description, an
    ARIA 1.3 attribute that not every screen reader announces. The sentence now sits
    in a hidden element the node references with aria-describedby, so it is read as
    the node's description everywhere, while the node's name stays its visible lines.

2026.10.51

2026.10.51 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 14 Oct 13:21
dc42ea9

Fixed

  • Make every control's accessible name include its visible text (27e7054f)

    WCAG 2.5.3 (Label in Name): an operator who drives the console by speech says
    what they see on a control, so the control's accessible name must contain its
    visible text. axe's label-content-name-mismatch rule now checks this and
    failed the browser accessibility tests.

    Changed controls (visible text -> accessible name):

    • Sort buttons of columns with a short label ("Cons.", "Deliv.", "Sched."):
      "Consumers" -> "Cons. (Consumers)", in the shared header cell.
    • "Close consumers" on an address row: "Close every consumer on "
      -> "Close consumers on ".
    • "Apply this" on a declared item: "Apply " -> "Apply this ".
    • The apply-mode button: the name is now its visible text followed by
      ". Change apply mode".
    • "Reset to default" in a setting row: "Reset to its default, "
      -> "Reset to default: , ".
    • Topology boxes: the box is named by its own lines (name, version, liveness,
      role, address); the sentence stays as its description.
    • Flow nodes: same, named by their lines with the sentence as description.
    • The collapsed cluster switcher: the name starts with the monogram the rail
      shows ("PR, Switch cluster, now ...").

    Tests that query these controls by name are updated to the new names.

2026.10.50

2026.10.50 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 14 Oct 11:24
04fb901
Release 2026.10.50

2026.10.49

2026.10.49 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 14 Oct 11:06
c8d1587

Breaking

  • Rename the product to Rahdar (4b484955)

    The product is now Rahdar (Persian راهدار, "road-keeper": rah, route, + dar,
    keeper). The name no longer names one broker, and "Artemis" now means only the
    broker Rahdar manages. Every published name changes with it, and nothing keeps
    the old ones working (ADR-0201).

Added

  • Give Rahdar its own mark (770b7f15)

    The crescent bow named Artemis; Rahdar's mark is Kept Road: one road cut
    through a tile as a lowercase r that runs on past two edges, the way kept open.
    It is pixel-exact at 16 and 32 px, so one favicon.svg serves the browser tab,
    the app header, the README and the docs. The app and the site also get a
    favicon.ico fallback and an Apple touch icon, and the site's social card is a
    new image with the mark and the wordmark.

    brand/ holds the lockups, the constructed wordmark, the icon set and the usage
    guide (clear space, minimum sizes, colours).

  • Rename the product to Rahdar (4b484955)

    The product is now Rahdar (Persian راهدار, "road-keeper": rah, route, + dar,
    keeper). The name no longer names one broker, and "Artemis" now means only the
    broker Rahdar manages. Every published name changes with it, and nothing keeps
    the old ones working (ADR-0201).

2026.10.48

2026.10.48 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 14 Oct 05:37
73e3b43

Breaking

  • Performance hardening — UUIDv7 keys, partitioned history, bounded jobs, connections and streams, external PostgreSQL, load test (#236) (73e3b437)

    • docs(openspec): design and tasks for 19-performance-hardening

    • docs(openspec): external PostgreSQL support in 19-performance-hardening

    • perf(ui): scan a table's rows for column widths once per page of data

    Sizing a table's columns read every row of the page for its longest values on each
    change of columns. The longest values are now kept per page of data and per column,
    so a change of density or of shown columns no longer costs more as the list grows.

    • feat(ui): find in large tables

    The browser's find cannot see the rows a large table has not drawn. Ctrl+F (Cmd+F on a
    Mac) in a table now opens its own find, which searches every row, says how many
    matches there are, and moves between them with Enter and Shift+Enter, scrolling to and
    marking the row. Escape closes it and returns focus to the matched row.

    • perf(ui): list a user's sessions in the table

    An account's sessions are not limited and were drawn as a plain list, so a very long
    list drew every row. They are now a table that draws only the rows in view.

    • perf(db): bound database connections in count and time

    The connection pool now has 16 connections per replica (ARTEMIS_STUDIO_DB_POOL_SIZE) and a request
    that waits more than 5 s for one fails instead of queueing. Every connection starts with a 30 s
    statement timeout, a 5 s lock timeout and a 60 s idle-in-transaction timeout, and the driver sets a
    5 s connect timeout, a 15 min socket timeout and TCP keep-alive, so a stuck query or a partitioned
    network no longer holds a thread without end. The limits are set per connection, not on the server,
    so they hold on any PostgreSQL and through a session-mode pooler. Plugin pools take the same limits.
    The plugin connection budget counts Studio's 16 connections instead of 10.

    The unused spring.task.scheduling setting is removed.

    • perf(db): raise the statement timeout for long work inside its own transaction

    The audit export, the lifecycle preview and the partition maintenance of the metric and message
    index tables run with a statement timeout of up to ten minutes (SET LOCAL), in a transaction of their
    own, so the 30 s limit on every other connection stays. The message index purge now detaches and
    drops a partition in one transaction.

    • perf(db)!: ship one PostgreSQL configuration for the bundled database

    The production, HA and development compose files mount deploy/postgres/postgresql.conf read-only
    instead of each carrying its own list of server flags. It adds statement statistics
    (pg_stat_statements with compute_query_id, created on first start), lock-wait logging, an explicit
    io_method=worker, autovacuum logging, max_connections=150 and a five-minute idle-in-transaction
    backstop to the earlier tuning. deploy/postgres/postgresql.tuning.conf is removed.

Changed

  • Performance hardening — UUIDv7 keys, partitioned history, bounded jobs, connections and streams, external PostgreSQL, load test (#236) (73e3b437)

    • docs(openspec): design and tasks for 19-performance-hardening

    • docs(openspec): external PostgreSQL support in 19-performance-hardening

    • perf(ui): scan a table's rows for column widths once per page of data

    Sizing a table's columns read every row of the page for its longest values on each
    change of columns. The longest values are now kept per page of data and per column,
    so a change of density or of shown columns no longer costs more as the list grows.

    • feat(ui): find in large tables

    The browser's find cannot see the rows a large table has not drawn. Ctrl+F (Cmd+F on a
    Mac) in a table now opens its own find, which searches every row, says how many
    matches there are, and moves between them with Enter and Shift+Enter, scrolling to and
    marking the row. Escape closes it and returns focus to the matched row.

    • perf(ui): list a user's sessions in the table

    An account's sessions are not limited and were drawn as a plain list, so a very long
    list drew every row. They are now a table that draws only the rows in view.

    • perf(db): bound database connections in count and time

    The connection pool now has 16 connections per replica (ARTEMIS_STUDIO_DB_POOL_SIZE) and a request
    that waits more than 5 s for one fails instead of queueing. Every connection starts with a 30 s
    statement timeout, a 5 s lock timeout and a 60 s idle-in-transaction timeout, and the driver sets a
    5 s connect timeout, a 15 min socket timeout and TCP keep-alive, so a stuck query or a partitioned
    network no longer holds a thread without end. The limits are set per connection, not on the server,
    so they hold on any PostgreSQL and through a session-mode pooler. Plugin pools take the same limits.
    The plugin connection budget counts Studio's 16 connections instead of 10.

    The unused spring.task.scheduling setting is removed.

    • perf(db): raise the statement timeout for long work inside its own transaction

    The audit export, the lifecycle preview and the partition maintenance of the metric and message
    index tables run with a statement timeout of up to ten minutes (SET LOCAL), in a transaction of their
    own, so the 30 s limit on every other connection stays. The message index purge now detaches and
    drops a partition in one transaction.

    • perf(db)!: ship one PostgreSQL configuration for the bundled database

    The production, HA and development compose files mount deploy/postgres/postgresql.conf read-only
    instead of each carrying its own list of server flags. It adds statement statistics
    (pg_stat_statements with compute_query_id, created on first start), lock-wait logging, an explicit
    io_method=worker, autovacuum logging, max_connections=150 and a five-minute idle-in-transaction
    backstop to the earlier tuning. deploy/postgres/postgresql.tuning.conf is removed.

2026.10.47

2026.10.47 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 13 Oct 16:41
c088fc4

Fixed

  • Register a plugin's settings before its jobs start (0b173563)

    A plugin whose scheduled job reads one of its own settings when it is
    scheduled (for example in its interval supplier) no longer fails to
    activate with "Unknown setting key". Plugin bridges now attach in
    Spring's @order, with the settings bridge first, and detach in the
    reverse order.

2026.10.46

2026.10.46 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 13 Oct 14:46
97c0dc2

Added

  • Say how many events an export will hold (38a51082)

    The Export menu names the number of matching events before a format is chosen.

  • Alert when an audit receiver is behind or lost records (623de17a)

    A new installation alert condition, AUDIT_DELIVERY, is active for each audit
    receiver that has a gap it has not been told about, or whose oldest
    unacknowledged record is older than audit.delivery.alert-after. The subject is
    the receiver's plugin id and the value is the age of that record. A default
    Audit delivery rule is created, enabled and bound to no channel, like the
    storage rules, and the condition is offered when editing an installation rule.

  • Retention waits for receivers and leaves held records alone (1bb820e2)

    The audit purge no longer deletes a record a receiver has not acknowledged until
    it is older than audit.delivery.max-unacknowledged-age. When it does delete such
    records, the receiver is told with an AuditGap, an AUDIT_GAP audit event records
    it, and AuditFeed.retainedFrom reports the time the trail is complete from.

    A plugin that declares audit.retentionHold provides one AuditRetentionHold
    naming time ranges, optionally narrowed by cluster, user, action and target. The
    purge leaves every record a hold covers, whatever the retention. It asks before
    every batch; a hold that throws, takes longer than audit.delivery.timeout, names
    more than 200 entries or belongs to a plugin that is not running on the purging
    replica makes the run purge nothing, and the purge status says why. A plugin that
    provides an AuditRetentionHold without declaring audit.retentionHold is not
    activated.

  • Deliver the audit trail to receiver plugins in commit order (4434d00d)

    A plugin that declares audit.receive in its manifest provides one AuditReceiver.
    Studio calls it with batches of up to 500 records after its cursor, in commit
    order, from a job that runs once per installation every two seconds. Returning
    from the call acknowledges the batch; throwing or taking longer than
    audit.delivery.timeout delivers the same batch again later, after a delay that
    doubles from 2 seconds to 5 minutes. Delivery is at least once, so a receiver
    identifies a record by its id and position. A receiver never holds up the
    audited operation.

    A new receiver starts at the beginning of the retained trail. Its cursor is
    removed when the plugin is uninstalled, not when it is disabled. A plugin that
    provides an AuditReceiver without declaring audit.receive is not activated.
    When retention removes records a receiver has not acknowledged, the receiver is
    told with an AuditGap and an AUDIT_GAP audit event records it.

    New settings: audit.delivery.max-unacknowledged-age (30d),
    audit.delivery.timeout (30s) and audit.delivery.alert-after (1h).

  • Add an Export menu to the audit log (8c5bfdb9)

    CSV, JSON and NDJSON are plain download links carrying the current filters,
    so the browser streams the file to disk and the download can be cancelled.
    The button is disabled with its reason without audit:export.

  • Export the audit trail as CSV, JSON or NDJSON (a58b48ed)

    GET /clusters/{clusterId}/audit/export streams the trail under the same
    filters as the list, oldest first, as a file. It needs the new cluster
    permission audit:export and holds only what the caller could read in the
    list, redacted the same way. CSV cells a spreadsheet would run as a formula
    get a leading quote. Each export is itself audited as EXPORT_AUDIT with its
    format and filters, and records how far it got if the client cancels.

  • Plugins declare audit access in their manifest (de54fa7d)

    A plugin.json may carry an audit block with receive and retentionHold flags,
    both false by default. The install review lists each flag, the diff shows
    flags an update adds or removes, and a plugin that newly declares one is
    activated only after the audit-access-added acknowledgement.

  • Give every audit record a commit-order position and a feed API (7e46bcb3)

    Each audit record now carries a position, the writing transaction's id and a
    sequence value stamped by the database. AuditFeed.after returns records in that
    order and only once every earlier transaction has ended, so a reader following
    the trail never skips a record that commits late. A record whose outcome is
    filled in takes a later position, so a reader that already passed it sees the
    final state. AuditFeed, AuditRecord and AuditPosition are part of the plugin API.

    A database guard now keeps the trail honest: only a record's outcome, error,
    count and outcome detail can change, only while it is pending (a refusal's count
    may keep rising), and nothing else is ever rewritten.

Fixed

  • Delete settled gap rows and fix the tests the audit delivery broke (30474c29)

    A gap row is deleted once it is audited and delivered, so the table holds only
    open gaps. Tests: the module slices that pull in the data lifecycle mock the
    retention guard, the schema baseline and store coverage lists name the new
    tables, the audit-access plugin fixture provides the beans it declares, and the
    alert rules test no longer depends on the seeded rule order.

  • Record a completed second-factor sign-in as a new event (b9f30d2e)

    A sign-in finished by its second factor is now a new successful login event
    whose parent is the attempt, instead of changing the attempt's outcome. The
    attempt's own record stays as it was written.

  • Keep gap counts, in-flight calls and export outcomes honest (24e0468a)

    A purge writes a new gap row each time instead of adding to one a delivery may
    have read, so an acknowledgement cannot mark an unseen count delivered. The
    AUDIT_GAP claim reads the row in the same statement, and the claim is given
    back only when the event could not be started. A receiver or hold that ignores
    its timeout is not called again until it has returned. An export records its
    outcome after the sink is flushed and closed.

  • Record an audit outcome once and ignore a second one (71dfb2d0)

    A row that already has its outcome is no longer overwritten by a later success or
    failure for the same operation. The first outcome stands and the second is logged
    as a warning, now that the database refuses rewriting a finished audit record.

2026.10.45

2026.10.45 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 13 Oct 08:03
ec896f1

Fixed

  • Let a plugin inject the ApproverPool (5dd05aaa)

    ApproverPool is plugin API, and an approval provider asks it whether there are enough approvers before it starts
    holding, but its implementation was never handed to plugin contexts: Studio exposes only beans whose own class is
    marked @PluginApi. A provider plugin that injected it failed to activate with "No qualifying bean of type
    ApproverPool". It is now exposed like the other plugin-facing services.

2026.10.44

2026.10.44 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 13 Oct 05:07
40ebed9
Release 2026.10.44