Non-interactive (headless) service-token issuance
Summary
Lore lacks a non-interactive mechanism for backend services to issue tenant-scoped, read-only service tokens for CI/CD and machine-to-machine authentication. The only token issuance paths today are interactive browser flows or OAuth token exchanges.
Current State
What exists:
UrcAuthApi.StartAuthSession (lore-proto/proto/auth_api.proto) returns a login_url for interactive browser-based authentication
ExchangeAPIKeyForUserToken exchanges external credentials, but is URC-account-shaped, not a server-issued service grant
- JWT layer reads an
is_service_account claim (lore-credential/src/jwt.rs) but there's no lore-native way to mint such tokens
File citations (pinned to rev 6559841):
lore-server/src/auth/mod.rs - only has jwk, jwt, middleware modules (no service token issuance)
lore-transport/src/auth/ucs_auth.rs - StartAuthSession is interactive-only, returns login_url
lore-transport/src/auth/exchange.rs - exchanges existing tokens, doesn't issue new ones
lore-proto/proto/auth_api.proto - no headless/service-token issuance RPC
Requested API
Add a first-class non-interactive service-account / service-token issuance path on the lore server. Example shape (adjust to lore's conventions):
message IssueServiceTokenRequest {
string tenant_id = 1; // Tenant/service account identifier
repeated string scopes = 2; // Read-only scopes (e.g., ["read:repo", "read:blob"])
string resource_id = 3; // Optional resource constraint (e.g., specific repository)
int64 ttl_seconds = 4; // Time-to-live for issued token
}
message IssueServiceTokenRequest {
string service_token = 1; // The issued JWT
int64 expires_at = 2; // Expiration timestamp
}
And corresponding Rust API in lore-transport/src/auth/:
pub async fn issue_service_token(
auth_url: &str,
tenant_id: &str,
scopes: &[String],
resource_id: Option<&str>,
ttl_seconds: u64,
) -> Result<ServiceToken, AuthError>
Use Case
CI/CD pipelines and background services need to authenticate with lore repositories without interactive browser flows. Today, StudioBrain works around this by minting "LSG" (Lore Service Grant) tokens in its accounts service using its own keypair, which lore then verifies via JWKS. This works but couples authentication to StudioBrain's infrastructure rather than lore's.
A native lore service token issuance API would:
- Enable headless CI/CD authentication without custom workarounds
- Provide tenant-scoped, time-bounded, read-only tokens with proper revocation
- Allow multiple independent services to authenticate without sharing long-lived credentials
Impact
Once this API exists, StudioBrain can retire its accounts-minted LSG workaround (see E0.2/E2.2 in StudioBrain's ADR-0001) and use lore-native service tokens instead.
Related
- StudioBrain ticket: SBAI-4138
- Parent tracking: SBAI-4133 (E5.3 — File lore upstream gap tickets)
- StudioBrain ADR: docs/adr/0001-studiobrain-lore-federation.md §3.2 (LSG workaround)
Non-interactive (headless) service-token issuance
Summary
Lore lacks a non-interactive mechanism for backend services to issue tenant-scoped, read-only service tokens for CI/CD and machine-to-machine authentication. The only token issuance paths today are interactive browser flows or OAuth token exchanges.
Current State
What exists:
UrcAuthApi.StartAuthSession(lore-proto/proto/auth_api.proto) returns alogin_urlfor interactive browser-based authenticationExchangeAPIKeyForUserTokenexchanges external credentials, but is URC-account-shaped, not a server-issued service grantis_service_accountclaim (lore-credential/src/jwt.rs) but there's no lore-native way to mint such tokensFile citations (pinned to rev 6559841):
lore-server/src/auth/mod.rs- only has jwk, jwt, middleware modules (no service token issuance)lore-transport/src/auth/ucs_auth.rs-StartAuthSessionis interactive-only, returns login_urllore-transport/src/auth/exchange.rs- exchanges existing tokens, doesn't issue new oneslore-proto/proto/auth_api.proto- no headless/service-token issuance RPCRequested API
Add a first-class non-interactive service-account / service-token issuance path on the lore server. Example shape (adjust to lore's conventions):
And corresponding Rust API in
lore-transport/src/auth/:Use Case
CI/CD pipelines and background services need to authenticate with lore repositories without interactive browser flows. Today, StudioBrain works around this by minting "LSG" (Lore Service Grant) tokens in its accounts service using its own keypair, which lore then verifies via JWKS. This works but couples authentication to StudioBrain's infrastructure rather than lore's.
A native lore service token issuance API would:
Impact
Once this API exists, StudioBrain can retire its accounts-minted LSG workaround (see E0.2/E2.2 in StudioBrain's ADR-0001) and use lore-native service tokens instead.
Related