Skip to content

Release: promote releases/r10.0-develop to releases/r10.0 (first production deploy) - #375

Closed
MusaMisto wants to merge 201 commits into
releases/r10.0from
releases/r10.0-develop
Closed

MusaMisto wants to merge 201 commits into
releases/r10.0from
releases/r10.0-develop

Conversation

@MusaMisto

Copy link
Copy Markdown
Member

Promotes develop to production: 187 commits. This is the first r10.0 push since the CI split, and the first one to deploy.

What merging does (the publish-release job of bitween-api-cicd-gateway.yml):

  • Builds and tests, then publishes the simplify9/bitween image and the bitween chart (charts.sf9.io and GHCR).
  • Publishes the NuGet packages, the CLI and the SDKs.
  • Tags the release.
  • Deploys to the production cluster: namespace bitween, app.bitween.io on s9-prod-edge's https-wildcard-bitween-io listener. The repository variable BITWEEN_PROD_DEPLOY is now true.

Production prerequisites (all in place)

Still untested before the first deploy: the database login. The first startup runs the migrations, and if they fail the log names the host and database. The bitween user needs CREATE on the bitween database.

Highlights since r10.0

  • Exchanges list rebuilt for triage.
  • Service accounts and tokens.
  • CLI plan, apply and export.
  • Metrics and the dashboard.
  • Expected traffic and quiet-subscription notifications.
  • Data source providers as packages.
  • Many UI improvements: command palette, page registry, Monaco adapter editor.
  • CI split into develop and release pipelines.

MusaMisto and others added 30 commits October 7, 2026 16:47
Clients install bitween from ChartMuseum. Since the deploy gate moved to
releases/r10.0-staging (d5cb0ce), every chart there has been a staging
build (10.0.47-10.0.51), and r10.0 pushes are skipped.

- Staging publishes its chart to GHCR OCI only. Its playground deploy
  already pulls from OCI, so nothing changes there.
- New publish-release job on push to releases/r10.0: builds, tests and
  publishes the image, the SDK and the chart to ChartMuseum. deploy is
  left false, so nothing is applied to the cluster.
- One concurrency group for both branches. They share the 10.0.x patch
  counter and image tag, and a patch is only claimed when the run tags
  at the end, so overlapping runs would publish the same version.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
ci: publish releases/r10.0 to ChartMuseum without deploying
…DK and samples MIT

Versions released before this change stay under MIT. NOTICE carries the
Section 7 terms (attribution, renamed forks, trademarks), a clarification
that internal use doesn't trigger Section 13, and the commercial license
offer. Contributors now grant Simplify9 the right to relicense.
Security
- SYSTEM partner key: random on new installs, Bitween:SystemPartnerKey to rotate,
  critical warning while the published key is in place
- Permission check and secret masking on the mapping preview; must-change-password
  lock enforced centrally (POST /api/xchanges left as is pending review)
- Grant only what you hold: roles, passwords, disable and remove limited to the
  caller's own permissions
- Secret masking in subscription search, notifier settings and the legacy preview;
  partner credential headers no longer stored in exchange payloads
- HTTP adapters: auth set per request instead of on the shared client; URL templates
  can't move a request to another host; link-local/metadata addresses refused,
  private ranges opt-in (Bitween:BlockPrivateNetworkAddresses)
- Credential columns encrypted at rest with SettingsEncryptionKey; partner API keys
  stored as SHA-256 hashes
- Sessions: disabled accounts lose access at once, refresh tokens expire after 30
  idle days, UI token kept in memory instead of localStorage
- Sign-in: forwarded headers configured, lockout per address with an account-wide
  backstop, no account enumeration
- Hardening: Oracle DDL not parsed on save, SFTP host-key pinning, safe upload file
  names, Scriban time limit, POP3 local file write removed, react-router 8.4
- Sensitive EF logging only in Development; Helm defaults to Production; container
  runs as non-root

Reliability
- Transactional outbox with a background dispatcher
- Repeat deliveries of a processed exchange ignored; responses published only with
  the result; failed attempts no longer crash on a duplicate result key
- External RabbitMQ: backoff before requeue, poison handling, publisher confirms;
  SQS returns with growing visibility timeout
- Rules mapper refuses misplaced thousands separators; Scriban trailing-comma fix
- Run flags claimed atomically on every provider and taken over when abandoned;
  data source leases released after repeated start failures

Operations
- /health/live and /health/ready; OpenTelemetry metrics and traces when an OTLP
  endpoint is configured
- Batched unpause, cached global values, indexable gateway lookup, ordered aggregation
- RabbitMQ adapter on RabbitMQ.Client 7.2.2
- PR check: .NET build and unit tests

Migrations (additive, all providers): Subscription.RunningSince, OutboxMessages,
PartnerApiCredential.KeyPrefix; empty PostgreSQL migration to re-baseline the snapshot.
- Sign-in with credentials ignores a leftover refresh cookie. A sign-out whose
  request never completed left the cookie behind, and the next sign-in in that
  browser restored the previous user's session instead of the one asked for.
- Refresh tokens are marked superseded with one conditional update instead of
  being loaded and deleted, so two requests with the same token no longer end in
  a concurrency error (a 500 from the sign-in endpoint). A superseded token stays
  usable for 30 seconds, so a browser that lost the response carrying its new
  token is not signed out.
- A signed-in caller who is refused gets 403 instead of 401, so the admin UI no
  longer spends a token refresh on every permission denial.
- End-to-end specs assert 403 for refusals.

Migration (additive, all providers): RefreshToken.SupersededOn.
The sync API gateway and the legacy waitresponse path compared their polling step,
capped at eight seconds, with the requested wait, so any wait of eight seconds or
more never ended and held a request and a database context for the life of the
process. Waits are now measured in elapsed time, end when the caller disconnects,
and are capped at Bitween:MaxResponseWaitSeconds (default 300).
…heir identity

Microsoft ID tokens were accepted with no audience or issuer check, from the
common endpoint, and matched to an account by preferred_username, so a token
issued to any app in any tenant signed in. Tokens must now be issued to
MsalClientId, by the token's own tenant, and by MsalTenantId when it is a tenant
id. Each account is bound to its Microsoft object and tenant id on first sign-in
and refuses any other identity afterwards. Microsoft sign-in is refused when no
client id is configured; token claims are no longer logged; the metadata is
cached instead of fetched on every sign-in.

Migration (additive, all providers): Account.MicrosoftIdentity.
…okens

- 408 and 429 fail the delivery, with the partner's Retry-After in the error, so
  a retry policy can retry them; they were recorded as bad responses.
- TimeoutSeconds on the HTTP handler and receiver (default 100, as before). The
  client is shared per origin, so the timeout is set per request.
- OAuth2 client-credentials tokens are cached until a minute before they expire
  instead of being fetched per message; a failed fetch is an error instead of a
  request sent with 'Bearer null'.
- Header values may contain a colon; PATCH is sent as PATCH.
A masked secret sent back meant 'keep what is stored' whatever else changed, so
someone able to edit an integration but not to see its password could point it
at their own server and receive it. The stored value is now kept only while the
adapter is the same and no destination property (url, host, server, endpoint,
address, domain, port, connection string) has changed; otherwise it has to be
entered again. Applies to subscriptions, notifiers, data sources, partners,
global values and retry alerts.
…quiet notifications

- A scheduled retry whose run throws is moved later with backoff instead of being
  deleted, and dropped only after five failures (DelayedRetry.RunFailures).
- Scheduled retry times get +/-10% jitter so an outage's failures don't return at
  the same instant.
- Bitween:MaxRetryChainDepth (default 100) caps every chain whatever its policy.
- Notifiers: a repeat of the result event no longer notifies twice; within
  Bitween:NotifierQuietMinutes (default 5) of a send for the same subscription and
  outcome, notifications are recorded as suppressed and counted into the next one
  sent (XchangeResultNotification.SuppressedSinceLast); a failed send is retried
  twice before it is recorded as failed.

Migration (additive, all providers): DelayedRetry.RunFailures,
XchangeNotification.Suppressed, index on XchangeNotifications(NotifierId, FinishedOn).
… settle

- Each listed item is received on its own. One that can't be read or submitted
  is left at the source and reported, and the rest go through; it used to end
  the run, and every run after it. The run is recorded as failed with each
  item's reason, and the exchanges it did create are kept.
- Finalize always runs, so POP3 commits the deletes of the messages it took and
  connections are closed.
- FTP/SFTP receiver: MinimumFileAgeSeconds (default 0) leaves files modified too
  recently for the next run, so a file still being uploaded isn't taken half-written.
- FTP and POP3 receivers close a connection a failed run left open when they are
  disposed.
…, requests, PDB, optional HPA

- The container port is 8080, the port the app listens on; it said 80, so probes
  could never pass.
- Probes are on by default: startup and liveness on /health/live, readiness on
  /health/ready; the startup probe allows five minutes for migrations.
- The RabbitMQ management password comes from the chart's Secret instead of a
  plain value in the pod spec; it is still set through
  environmentVariables.Bitween__RabbitMqManagementPassword.
- Default resource requests (250m CPU, 512Mi); no default limits.
- A PodDisruptionBudget whenever there is more than one replica, and an optional
  HorizontalPodAutoscaler (autoscaling.enabled, off by default).
A partner whose call timed out can send it again with the same Idempotency-Key and gets the
exchange the first call made (Idempotent-Replay: true) instead of a second one. Keys are scoped
to gateway and partner, kept 24 hours, and committed with the exchange so concurrent repeats
settle on one. The older POST /api/xchanges/{type} honours the key too. Without the header
nothing changes.
Auto-pause after failures
- A subscription can be set to pause itself after N failed deliveries in a row
  (AutoPauseAfterFailures, 1-1000; null, the default, never pauses). Counted and
  compared in the database so parallel exchanges can't lose counts or pause twice.
- What arrives while paused is held, as with a manual pause. Resuming starts the
  count again. The pause is logged, counted (bitween.subscriptions.auto_paused) and
  sent to the alert handler of the subscription's retry policy, on its own queue.
- Edit page: an Auto-pause field, and the paused banner says when it paused itself.

JSON Schema / XSD on information types
- A JSON or XML information type can carry a schema (ValidationSchema). A gateway
  call that doesn't match is refused with 400 and what's wrong; so is the older
  POST /api/xchanges/{type}. Any other exchange whose input doesn't match fails
  with DocumentSchemaException listing the errors.
- Schemas may not refer outside themselves ($ref to a URL or file, XSD include or
  import): the server would fetch whatever an editor typed. NJsonSchema (MIT) for
  JSON Schema; System.Xml for XSD.
- A save that doesn't mention the schema keeps it; an empty one removes it.
- Information type page: a Schema panel.

Dead letters
- GET /ops/deadlettermessages reads a dead-letter queue without taking anything
  off (needs monitoring.view and exchanges.view: the bodies are the messages).
- POST /ops/requeuedeadletters moves them, oldest first, back onto the queue they
  failed on, straight to that queue (not its exchange, which would redeliver to
  every consumer), with the retry headers cleared. Each leaves the dead-letter
  queue only once the broker confirms it; a missing main queue moves nothing.
  Needs monitoring.operate. Only queues the bus lists as dead letters are touched.
- Queue health: Show messages and Send back on each dead-letter row.

Nothing changes for a deployment until a schema or an auto-pause limit is set.
The database and bus adapters (and the resident sample) targeted net8.0 on SDK 8.1.23, on the
grounds that they had to stay runnable on hosts older than r10. They can't be: a resident adapter
only runs under the r10 resident host. Meanwhile the image ships only the net10.0 runtime (and a
copied net6.0 for legacy classic adapters), so a net8.0 adapter had no runtime to start on.

SDK 10.0.0 is 8.1.24 rebuilt for net10.0, so adapter behaviour is unchanged. Driver pins (Npgsql
8.x, SqlClient 5.x) are left as they are. The integration suites for these adapters no longer need
a .NET 8 runtime on the test machine.

Deployments need the eight resident adapter packages republished to their buckets.
Classic adapters were bounded by Bitween:ServerlessCommandTimeout while resident ones always got the
framework's own 300 seconds, so changing the setting changed only half the adapters. Both default to
300, so nothing changes unless a deployment has set it.
Host: safe package installs, correct resident supervision (no duplicate consumers after a stop or
start during crash backoff, re-resolve on restart, drain deadline, state off the heartbeat path),
pooled instances retire after 10 minutes idle, health shows setting names only.
SDK, for the eight resident adapters and the samples: cancellation, drain delivers running results,
oversize results fail one call, protocol range negotiation.

The resident adapter packages need republishing to each deployment's bucket.
…0.0.2)

Catalog: the adapter lists read SW.Serverless's catalog (adapters-catalog/{id}.json) when an
adapter has one — current version, version history with release notes, and the manifest's display
name, summary, description, publisher, icon and tags. Adapters published before the catalog list
exactly as before; the old `versions` field also carries the catalog's pinnable versions.

Properties: an adapter whose manifest lists its properties is described from them, for the pinned
version when there is one; otherwise it is asked, as before.

Pinning: Subscription.{Receiver,Validator,Mapper,Handler}Version (nullable; null follows the
current version, as every existing subscription does). Exchanges carry {id}/{version}, so retries
run the same package. Refused: a pin on a built-in adapter, an unpublished or withdrawn version, and
choosing an adapter whose manifest needs a newer Bitween (Bitween:Version, else BitweenInfo's
baseline) — a slot left unchanged is never re-checked. Migrations (additive, all providers): four
nullable columns on subscriptions. Edit page: a version picker per adapter slot; create pages follow
the current version.

Native adapters: each carries an embedded adapter.json; a unit test keeps its properties in line
with the adapter's startup-values type.

Tests: AdapterCatalogTests (legacy adapters unchanged, catalog never listed as an adapter, manifest
listing and properties, pinning, refusals, old-layout versions), NativeAdapterManifestTests,
AdapterVersion UI tests.
… and usage

A new Configuration page, /adapters (subscriptions.view, as the catalog it reads), with two tabs:
Installed, and Marketplace (a placeholder until the marketplace exists).

Installed lists every adapter once — gathered from the four per-kind catalogs, so one serving two
kinds shows both — in a Built-in section and a Custom section, with search (name, id, summary,
publisher, tags) and a kind filter. Each shows its icon, name, id, kinds, summary and publisher,
current version, how many versions can be pinned, and how many subscriptions use it. Opened: the
description and tags, every version newest first with Current/Withdrawn, publish date and
publisher, release notes and how many subscriptions pin it, the settings it takes, and links to the
subscriptions using it. Packages published before manifests list by id with their version numbers.

Subscriptions in the shared cache now carry their adapters per slot with any pinned version
(adapterUses), which is what usage is counted from. No backend change.
The request validator checks an adapter's required settings before the applier checks the version,
and describing {id}/{version} for a version that doesn't exist tried to install it and threw. Found
running the app end to end: POST /subscriptions with HandlerVersion 9.9.9 answered 500. The settings
check now skips a version that can't be pinned, and EnsureRunnable refuses it with its reason (400).
The page draws nothing until four catalog requests and the subscriptions list answer, which can take
longer than findBy's default second on a loaded machine; all six tests failed together once when the
suite ran straight after the integration tests. The first wait in each now allows five seconds.
SW.Bitween.HttpTests runs the web app in-process against real PostgreSQL and
RabbitMQ and checks, over HTTP: which handlers are open without a session,
that every resource and named operation refuses a caller without a token, that
a signed-in token is honoured and a forged one is not, the sign-in rate limit
per address, security headers, health endpoints, partner keys issued, used and
revoked against a gateway, detaching a partner, and sign-out ending the
session's refresh token.
…e2e.sh

The suite needed a hand-prepared dev database: a partner, two information types and
failed exchanges it never created, the old published admin password in a dozen places,
and a queue prefix from one particular machine. A fresh install refuses that password,
so the suite could not run against one at all.

- e2e/env.ts reads the base URL and admin credentials from E2E_* variables, defaulting
  to what an existing team dev database still has.
- globalSetup becomes a seed setup project: prerequisite checks with messages that say
  what is missing, the existing purge, then idempotent find-or-create of the rows in
  e2e/seed-data.ts, including a subscription that delivers to an unreachable address so
  there are always un-retried failed exchanges.
- tools/e2e.sh starts throwaway Postgres and RabbitMQ, builds and starts the app with a
  generated initial admin password, runs the suite and tears everything down.
- Specs: one sign-in helper instead of copied beforeEach blocks, seeded names instead of
  literals, queue prefix read from the API, adapter display names from the manifests,
  the bus gateway test now really adds and edits a route filter, and the retention
  tests that need a temp30/ bucket rule skip with a reason where storage has none.
…them once

On a freshly started app the consumers attach, and the management API reports them,
a few seconds after /health answers, so a single read failed the seed for nothing.
TryIncrement and ClaimExhaustionAlert set their times inside ExecuteUpdate,
where EF translates DateTime.UtcNow to the database server's clock.
ReleaseExhaustedBudgets compares LastAttemptOn with an exchange's StartedOn
from the application's clock, so a few milliseconds of skew let a success
that followed an exhausting failure look older than it and leave the budget
spent. Found as an intermittent failure of
A_success_gives_the_group_its_spent_budget_back.
samerzughul and others added 21 commits October 12, 2026 13:19
The docs and several comments said Quartz was not clustered, so every
replica ran every scheduled job. That stopped being true when
SimplyWorks.Scheduler 8.1.7 made clustering unconditional on all three
persistent stores (SchedulerId AUTO, UseClustering); 10.0.0 is pinned now.

These tests start two real schedulers registered as Startup registers
them, against one migrated PostgreSQL, and record every fire through a
Quartz job listener: the store is clustered with distinct instance ids,
no fire runs on two nodes, the survivor carries on when the node running
the jobs stops (21 to 30 s, Quartz's idle wait), and a single node runs
every fire.
Quartz runs clustered, so each fire already runs on one replica only.
The replica section of architecture.md, the scheduling and caveats docs,
the Startup comment and the aggregation comments still said otherwise,
and caveats still listed aggregations as having no running flag.

The run flags stay and their reason is now the real one: each schedule
of a subscription and each Receive now or Aggregate now is a Quartz job
of its own, so two runs of one subscription can overlap.
A delivery to a partner that has stopped answering holds its place in the
processing queue for its whole timeout. In the lab an ERP answering in 30 s
against a 20 s timeout filled every slot of the shared queue, and orders to a
healthy warehouse went late; hung SFTP uploads once stopped processing
altogether. Work groups isolate queues, but only when someone sets them up.

The built-in HTTP, SMTP, SFTP and FTP upload handlers now share a circuit
breaker per destination (scheme, host and port), per process. Timeouts,
refused or dropped connections, 429 and any 5xx but 501 count; 4xx business
rejections and failures before anything is sent do not. After
Bitween:CircuitBreakerFailures (5) such failures in a row within
Bitween:CircuitBreakerWindowSeconds (60), calls to that destination fail at
once for Bitween:CircuitBreakerOpenSeconds (60) with
"503: ServiceUnavailable: circuit open for {destination} (...)", so retry
policies that retry a 503 retry them. One trial call then goes through:
success closes the circuit, failure opens it again. Opening is logged as a
warning and counted as bitween.circuits.opened; closing is logged.

CircuitBreakerFailures = 0 switches it off. The handlers take the registry
as an optional constructor argument, so code that builds them directly keeps
working without one. With the defaults nothing changes until a destination
keeps failing.
NotifyResult held the call to a notifier's handler, with its quick
retries, inline. Alerts that have no exchange behind them need the same
call, so it moves to NotifierDelivery and NotifyResult uses it. Nothing
changes for exchange results: same payload, same xchangeid property,
same file name, same three attempts.
When a partner's system breaks, a carrier moves its folder or a table
stops filling, no exchange is created, so nothing fails and nobody is
told. Every entry point creates exchanges on a subscription, so that is
where the expectation goes.

ExpectTraffic is optional and stored as one JSON column: at least one
exchange every N minutes (5 or more), on chosen days, between From and
To, in an IANA time zone (UTC when empty). TrafficWindow checks it on
save with messages that say what to change, stores it in one spelling,
and answers when silence counts: only inside the window, and only once
the window has been open a whole gap, so last evening's order doesn't
make a subscription quiet at 08:01. QuietSince records when it was
found quiet; Get and the search return it and an update can't set it.

The field is replaced on update like its neighbours
(AutoPauseAfterFailures, CustomRetryPolicy), so an update without it
removes it, and removing it clears QuietSince. bitween apply manages
expectTraffic and compares it whole, ignoring the nulls the API
answers, so a plan doesn't show a difference that isn't there.

Migration ExpectTraffic adds two nullable columns on all three
providers; no subscription changes behaviour until it is given one.
A subscription that expects traffic and gets none still fails nothing.
QuietSubscriptionsJob runs every five minutes (QuietSubscriptionsCron)
over active, unpaused subscriptions with an expectation. Inside the
window, when no exchange started within the expected gap, it sets
QuietSince and tells the notifiers that watch the subscription for
failed results. When an exchange starts after QuietSince, inside the
window or not, it clears it and tells them it is back. Both changes are
conditional updates, so each is sent once.

The notifiers get the XchangeResultNotification an exchange result
sends, through the same helper and retries, with a new optional Event:
"gone-quiet" (Success false) or "back" (Success true), and a plain
sentence in Exception. It is null for exchange results, so existing
handlers see nothing new. There is no exchange, so the id is one made
for the alert and the send is logged rather than written as an
XchangeNotification.

Each question asked of the exchanges is bounded to the recent past, so
it stays cheap on an instance that keeps years of them. Quiet
subscriptions are also listed in the dashboard insights and the job on
the background jobs page.
The overview gets an Expect traffic panel: every N minutes, days, From
and To, and a time zone with the browser's list as suggestions. It is
part of the page's draft, so it saves with the rest. A subscription the
server found quiet shows "Quiet since ..." beside the pause notice.

A save sends the whole subscription and the server replaces the
expectation like its other fields, so every save carries the stored one
over unless the page changed it, as it does for auto-pause.
How a subscription is found quiet and back, what the notifiers receive,
the API fields and their rules, QuietSubscriptionsCron, and how
bitween apply compares expectTraffic.
rename-chart (simplify9/.github#189) publishes charts/default as bitween-develop, so develop and production ship from one Chart.yaml, one set of templates and one values.yaml and cannot drift. It replaces the symlinked charts/develop, whose own Chart.yaml could drift and whose values.yaml symlink let an edit meant for develop change production. The tests now run inside the shared pipeline (run-tests without nuget-projects, same PR), so develop-tests goes.
ci: publish develop from the production chart directory
SW.Bitween.HttpTests referenced the web project with
<Properties>SkipClientBuild=true</Properties>. MSBuild builds a project once
per set of global properties, so a solution build without that property (the
shared dotnet-build action) built SW.Bitween.Web twice, in parallel, into the
same obj folder. The two runs of DefineStaticWebAssets then collided on
rpswa.dswa.cache.json ("being used by another process"), failing the build
now and then since the HTTP tests landed: runs #118, #136, #140 and #149.

The property skipped nothing: BuildClientApp runs after
ComputeFilesToPublish, which a project reference never runs. The PR checks
pass -p:SkipClientBuild=true to every project, so there the two builds were
one and the race never showed.
Work groups are told apart by name in the pickers and in bitween apply, but the API let two share one. Two applies running at once in the lab each made "Acme ERP", split its subscriptions between them, and every apply after stopped until one was removed by hand. Create, and a rename in Update, now refuse a name another work group has, ignoring case and surrounding spaces. Existing duplicates are left alone. The new test fails without the change.
ci: deploy develop to bitween-dev and releases to production
fix(build): build SW.Bitween.Web once per solution build
ci: wildcard listeners for develop and production, and the S3 checksum setting for production
Brings Hamza's six commits that went straight to r10.0 (#352, #354, #356,
#367, #369) into develop, so develop can be promoted to r10.0 without
dropping them.

Conflicts, resolved keeping both sides:
- XchangeFilters.cs: develop's retry, scheduled-retry, aggregated and
  error-text filters, then r10.0's PromotedPropertyKey filter, which has to
  come before the value loop that searches inside that key's value.
- exchanges.ts: r10.0's key-apart property terms, then develop's four new
  filters.
- ExchangesPage.tsx: develop's redesigned page. r10.0's Refresh button and
  loading state are ported into it: Refresh sits in the Live control and
  reloads the list, counts and chart at once; a filter or page change, or
  Refresh, dims the list under a loading bar, while the background live ticks
  don't.
- SW.Bitween.Web.csproj: develop's OpenTelemetry packages with r10.0's
  SimplyWorks.Bus 10.0.3. The other three projects took 10.0.3 without
  conflict.
- docs/configuration.md: both new sections.
- docs/deployment.md: develop's probe text, which describes the chart this
  branch ships.

Two component tests added: Refresh asks again for the list and the counts
while paused, and a picked property is sent apart from its value.
Merge releases/r10.0 into develop (Hamza's r10.0 changes, ahead of the production release)
@coderabbitai

coderabbitai Bot commented Oct 12, 2026

Copy link
Copy Markdown

Walkthrough

Warning

Review details and warnings were omitted to fit the comment limit.

@MusaMisto MusaMisto self-assigned this Oct 12, 2026
@MusaMisto MusaMisto added documentation Improvements or additions to documentation enhancement New feature or request dependencies Pull requests that update a dependency file labels Oct 12, 2026
@gitguardian

gitguardian Bot commented Oct 12, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 14 secrets following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secrets in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
38036913 Triggered Generic Password 5c95b98 SW.Bitween.HttpTests/AccountAndRoleTests.cs View secret
38036914 Triggered Generic Password 5c95b98 SW.Bitween.HttpTests/AccountAndRoleTests.cs View secret
38006165 Triggered Generic Password 77c6eb3 SW.Bitween.IntegrationTests/Tests/LoginTests.cs View secret
3998894 Triggered Generic Password cd8f115 SW.Bitween.Web/ClientApp/src/pages/auth/tests/ChangePassword.test.tsx View secret
38036915 Triggered Username Password fe36b7d SW.Bitween.TransportTests/HttpTests.cs View secret
38078904 Triggered Generic Password f4d7fb5 SW.Bitween.Web/ClientApp/src/pages/data-sources/tests/DataSourceNewPage.test.tsx View secret
38067233 Triggered Generic Password 4707f84 SW.Bitween.HttpTests/BitweenCliTests.cs View secret
38006166 Triggered Generic Password fd3f83f SW.Bitween.IntegrationTests/Tests/LoginTests.cs View secret
38036916 Triggered Generic Password 5c95b98 SW.Bitween.HttpTests/AccountAndRoleTests.cs View secret
38036917 Triggered Generic Password 5c95b98 SW.Bitween.HttpTests/AccountAndRoleTests.cs View secret
38006167 Triggered Generic Password fd3f83f SW.Bitween.IntegrationTests/Tests/LoginTests.cs View secret
20562020 Triggered Generic Password d2c20c2 tools/e2e.sh View secret
38036918 Triggered Generic Password 6a2e58f tools/e2e.sh View secret
37997817 Triggered Generic Password cd8f115 SW.Bitween.Web/ClientApp/src/pages/auth/tests/ChangePassword.test.tsx View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secrets safely. Learn here the best practices.
  3. Revoke and rotate these secrets.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@MusaMisto

Copy link
Copy Markdown
Member Author

Closing: the full develop → r10.0 promotion happens later. Only the CI and production-deploy changes go to r10.0 for now, in a separate PR.

@MusaMisto MusaMisto closed this Oct 12, 2026
@MusaMisto
MusaMisto deployed to Development October 12, 2026 16:14 — with GitHub Actions Active

This branch was successfully deployed

1 active deployment
Development — 736f6122 Deployed Oct 12, 2026 by MusaMisto via build-publish-deploy / deploy #155
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants