Part of the service-identity work, QRun-IO/qqq#1248. Draft: it needs the QQQ RC that contains qqq#1255 and #1256. Bump qqq.snapshot.version once the release captain cuts it.
Problem: under OAuth2, AlertRouter.knownVisibility / canReadRecord and AlertsAudienceResolver used createAutomatedSessionForUser. Those sessions are token-less and rejected, so the checks always fell to the conservative branch:
in-app sends only;
external sends only for alerts with no permission or subject;
followers dropped.
Fix:AlertsSecurity.recipientSession.
When the host declares the alerts principal (AlertsQBitConfig.servicePrincipal), the checks run on the recipient's behalf through it: the recipient's current access intersected with the principal's. Record locks still apply.
With no principal declared, the old path is kept.
Deliberate deviation from the design table (section 6.1): alert recording and routing bookkeeping (AlertsSecurity.systemSession for the sink, monitors and router) stay on the system session. If they ran as a principal, a failed or slow identity provider would also stop alerting, including the service_identity.unavailable alert itself. The bookkeeping touches only alerts tables. What reaches recipients is decided by the delegated sessions.
Tests:
AlertsServicePrincipalTest: recipient sessions before and after declaring the principal.
Full suite: 229, 0 failures, against a local install of qqq#1256.
Part of the service-identity work, QRun-IO/qqq#1248. **Draft:** it needs the QQQ RC that contains qqq#1255 and #1256. Bump `qqq.snapshot.version` once the release captain cuts it.
**Problem:** under OAuth2, `AlertRouter.knownVisibility` / `canReadRecord` and `AlertsAudienceResolver` used `createAutomatedSessionForUser`. Those sessions are token-less and rejected, so the checks always fell to the conservative branch:
- in-app sends only;
- external sends only for alerts with no permission or subject;
- followers dropped.
**Fix:** `AlertsSecurity.recipientSession`.
- When the host declares the `alerts` principal (`AlertsQBitConfig.servicePrincipal`), the checks run on the recipient's behalf through it: the recipient's current access intersected with the principal's. Record locks still apply.
- With no principal declared, the old path is kept.
**Deliberate deviation from the design table (section 6.1):** alert recording and routing bookkeeping (`AlertsSecurity.systemSession` for the sink, monitors and router) stay on the system session. If they ran as a principal, a failed or slow identity provider would also stop alerting, including the `service_identity.unavailable` alert itself. The bookkeeping touches only alerts tables. What reaches recipients is decided by the delegated sessions.
**Tests:**
- `AlertsServicePrincipalTest`: recipient sessions before and after declaring the principal.
- Full suite: 229, 0 failures, against a local install of qqq#1256.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Part of the service-identity work, QRun-IO/qqq#1248. Draft: it needs the QQQ RC that contains qqq#1255 and #1256. Bump
qqq.snapshot.versiononce the release captain cuts it.Problem: under OAuth2,
AlertRouter.knownVisibility/canReadRecordandAlertsAudienceResolverusedcreateAutomatedSessionForUser. Those sessions are token-less and rejected, so the checks always fell to the conservative branch:Fix:
AlertsSecurity.recipientSession.alertsprincipal (AlertsQBitConfig.servicePrincipal), the checks run on the recipient's behalf through it: the recipient's current access intersected with the principal's. Record locks still apply.Deliberate deviation from the design table (section 6.1): alert recording and routing bookkeeping (
AlertsSecurity.systemSessionfor the sink, monitors and router) stay on the system session. If they ran as a principal, a failed or slow identity provider would also stop alerting, including theservice_identity.unavailablealert itself. The bookkeeping touches only alerts tables. What reaches recipients is decided by the delegated sessions.Tests:
AlertsServicePrincipalTest: recipient sessions before and after declaring the principal.🤖 Generated with Claude Code