Arch Forum 2026-11-13¶
Participants: Backend Devs, Magnus, Victor
Agenda¶
- Platform news
- .NET 11
- Renovate of GH Actions
- Main and master branches
- Keep PR Feedback in GH if possible
- The HSE environment
- Dev secrets and DB migration in platform
- Merge of API and Service layers
- Config as deploy
- Risk based PR approvals (Magnus)
Summary¶
Platform news¶
Highlights:
- [SX-2886] Add a shared X-App-Version parser and app version gate / Vitaly
- [BCP-3682] Make RandomNumbers produce the digit 9 / Shakib
- [BCP-3683] RabbitMQ publisher: declare each exchange and binding once instead of on every publish / Shakib
- [PT-361] Move legacy log fields into their own namespace / Victor
- [MIB-14383] Avoid late scope resolution in messaging wrappers / Victor
Full list:
- [SX-2886] Add a shared X-App-Version parser and app version gate / Vitaly
- [MIB-14362] Add a Timestamp constructor that builds the key from its number / Vitaly
- [SX-2921] Give each data row its own service mocks when rows differ only by null, false or 0 / Vitaly
- [BCP-3681] Message outbox: postpone a message that fails to publish instead of blocking the outbox / Shakib
- [BCP-3682] Make RandomNumbers produce the digit 9 / Shakib
- [BCP-3683] RabbitMQ publisher: declare each exchange and binding once instead of on every publish / Shakib
- [BCP-3680] Recurring scheduling: keep the lease heartbeat alive and fence run completion by lease owner / Shakib
- [PT-359] Serialize sanitized audit bodies as strings / Victor
- [PT-361] Move legacy log fields into their own namespace / Victor
- [MIB-14383] Avoid late scope resolution in messaging wrappers / Victor
- [MIB-14363] Add shared RabbitMQ subscription supervisor
- [MIB-14363] Share typed RabbitMQ recovery lifecycle / Victor
- [MIB-14363] Recover raw consumers using shared supervisor / Victor
- [MIB-14370] Reject conflicting user-type authorization requirements / Victor
- [MIB-14367] Truncate existing files when downloading blobs / Victor
- [MIB-14369] Remove unused legacy timeout and availability providers / Victor
- [MIB-14368] Preserve RabbitMQ identity across publisher retries / Victor
- [MIB-14375] Align Swagger user types with authorization requirements / Victor
- [MIB-14374] Add self-service DbUp CLI and rename shared package / Victor
- [MIB-14376] Resolve RabbitMQ handlers from the delivery scope / Victor
- [MIB-14378] Remove self-resolving authentication credentials registration / Victor
- [MIB-14265] Retire EventStream configuration switch / Victor
- [MIB-14374] Preserve Initialize-Db empty timeout placeholders / Victor
- [MIB-14382] Automatically cache development Key Vault secrets / Victor
.NET 11¶
.NET 11 is out, Announcing .NET 11.
Do we want to upgrade? And if so, any volonteers for doing the work?
Earlier we have done 2.0 → 2.1 → 2.2 → .NET 6 → .NET 8 → .NET 10, skipping the non-LTS version.
Meeting note: No big discussion followed, and no volonteers. If you are interseted, ping Victor to coordinate.
Renovate of GH Actions¶
With all the security and AI going around we need to keep out GH Actions both updated and safe.
- Pin a hash of the action used (for external actions. Internal we keep master as today)
- Use renovate to keep it up to date.
For now we have renovate bot running in the be-cicd repo. If it works well we will use everywhere we have actions.
Main and master branches¶
- Rebtel uses main as the default branch.
- Majority uses master.
- Github defaults to main.
To simplify and unify I want to change to main everywhere.
Meeting notes:
- Alex raised that he has master in his muscle memory and prefers master. But at the same time he already have the pain of working in repositories with main.
- We will move forward with this.
Keep PR Feedback in GH if possible¶
Message in slack:
Please leave PR feedback on the PR in Github, rather than only in Slack, DMs, or in person, where its harder to track.
We want AI to be able to work better in our code repos. One very important way we can improve AI, is from human pr comments. This will help us identify useful context and improve AGENTS.md files etc.
Of course, some discussions are better on Slack or face 2 face. Such discussions are great, and we should continue to have them! In such cases, leave a comment on the PR with a short note about the concern/question, and then have the slack/face2face discussion.
And remember that comments don’t need to be perfect. Do not feel bad for commenting about something you dont understand or are unsure about!
The HSE environment¶
HSE stands for "High Security Environment", and is a new classification like CDE (Card Data Environment), that we will use for services that are extra sensitive, but do not manage card data. The prime example is be-crypto. Work in progress, HSE in ArgoCD on Stage
flowchart LR
subgraph HSE["HSE · High Security Environment"]
direction TB
hse_crypto["be-crypto"]
hse_ledger["be-ledger"]
hse_reporting["be-reporting"]
hse_config["be-hse-configuration"]
hse_crypto ~~~ hse_ledger ~~~ hse_reporting ~~~ hse_config
end
subgraph CDE["CDE · Card Data Environment"]
direction TB
cde_carddata["be-cde-carddata"]
cde_externalcarddata["be-cde-externalcarddata"]
cde_cashdeposit["be-cde-cashdepositproxy"]
cde_config["be-cde-configuration"]
cde_carddata ~~~ cde_externalcarddata ~~~ cde_cashdeposit ~~~ cde_config
end
subgraph Minority["Minority · Everything else"]
direction TB
min_user["be-user"]
min_transactions["be-transactions"]
min_config["be-configuration"]
min_more["… and all other services"]
min_user ~~~ min_transactions ~~~ min_config ~~~ min_more
end
HSE ~~~ CDE ~~~ Minority
classDef default fill:#ffffff,stroke:#94a3b8,color:#0f172a,rx:6,ry:6
style HSE fill:#f5f3ff,stroke:#8b5cf6,color:#5b21b6,stroke-width:2px
style CDE fill:#fff7ed,stroke:#f97316,color:#9a3412,stroke-width:2px
style Minority fill:#eff6ff,stroke:#3b82f6,color:#1e40af,stroke-width:2px
Meeting note: The HSE repos will be renamed to include the hse prefix, similar to the cde repos today.
Dev secrets and DB migration in platform¶
- The DB migration code is updated to make it easier to run. If you just run it directly, like
dotnet run --project Minority/Minority.Remittance/Minority.Remittance.Db/Minority.Remittance.Db.csprojthen it will migrate local db. Its still backwards compatible with Initialize-DB ps script. (It does however require a “manual” renovate to get, I will make PRs everywhere) - The local secrets loader is updated to make it easier to run. The services & tests will now load secrets from KeyVault on startup, but with a local cache. So the first time you run it will be a bit slow (and require you are authed with az login), but after that it will be cached for 7 days. Its still possible to force a refresh like you could do with the powershell script, by setting env var
DEV_SECRETS_FORCE_REFRESH=true, like thisDEV_SECRETS_FORCE_REFRESH=true dotnet run --project Minority/Majority.Platform/Majority.Platform.Test.Api/Majority.Platform.Test.Api.csproj
Merge of API and Service layers¶
Today we have Area.Service which expose internal http endpoints for other backend services to call. Then we have Area.Api that contains the public api. These two projects are deployed as separate services.
I want to merge these two layers to simplify our architecture.
- Reduced logging: The ROUTRQ/ROUTRP/RINRQ/RINRP logs when Api calls Service can be skipped
- No backwards compatibilty issues between Api and Service (Which of them deploys first etc)
- Easier rollbacks
- Less resource usage in the cluster. (Especially memory usage)
- One less network hop (often Api and Service are not even located on the same k8s node!)
- Easier to run locally since its only one project to start
- In some cases security will actually improve, since a service endpoint only used by API can be removed!
A POC exists in Risk. See Risk.Rules.Service/External and Risk.Rules.Api.Contract/Decision/IDecisionController.cs
Meeting notes:
- Mesut had a good question about why not just import the Service into the Api (to skip the network call between Api and Service)? The reason is that that only gives part of the benefits. I.e. the Api would then need to have all the access that the Service gives, and the separation between them would not really matter anmore. It would likely be easier, but in the age of AI it shouldnt be too much work to go all the way and merge them into one.
- There might be some endpoint somewhere using /external already. Need to investigate.
- In some special cases we might need to keep Api and Service separation. I.e. for the CDE services.
- Migration wont be a easy renovate, instead it will be done on a service-by-service basis to make sure nothing breaks and the important settings are kept (i.e automatic auth on external endpoints vs no auth on internal ones)
Config as deploy¶
Treat configuration changes like a standard deployment with a review, validation, versioning, application, observation, and rollback loop.
Meeting notes:
- In general this should be an improvement for backend configuration handling.
- Sometimes today we syncronize the deployment of configuration with the deployment of service. E.g. merge a config change first, but not restart the service, and then deploy service and the new service version will load the new config. This process will not work with the proprosed plan. Since this is a edge case, that can be worked around (make config change backwards compatible with old code), we will move forward anyway.
Risk based PR approvals¶
We want to trial self approvals of low risk PRs, e.g. the developer can approve their own PRs. To do this there is a step in the pipeline that can evaluate the PR and give a REVIEW or SELF recommendation.
As of 2026-11-13 its in shadow mode in all of backend. It will give a recommendation as a PR comment, but not act on it. Once we have trialed it for a while we will evaluate, how many PRs could be SELF approved, how many did it classify wrongly?
The code and rules for the risk based approvals is available in the group-policies repo.