swarm-ui: set the review classifier's keys from the classifier settings
The classifier's Anthropic and ACP provider keys were written by hand in the
secret store's UI. The controller now stores them: GET
/api/review-classifier/keys says whether each is set and when it changed, and
PUT /api/review-classifier/keys/{runtime} writes one. No route answers a key.
The controller's store policy gains create and update on the two leaves with
no read of their values, and a metadata read for the set state. The swarm UI's
classifier settings card gets a key form beside the settings, saved apart
because it goes to the secret store.
This commit is contained in:
parent
c5d601e3a2
commit
6875a4f0f8
3 changed files with 628 additions and 20 deletions
|
|
@ -638,7 +638,7 @@ in
|
|||
description = ''
|
||||
Run the review classifier in a `swarm-review-classifier` container on
|
||||
this host. It answers the swarm UI's review try-outs with `claude` on
|
||||
the Anthropic API key the operator writes to the secret store at
|
||||
the Anthropic API key the operator sets in the swarm UI, or writes to the secret store at
|
||||
`secret/swarm/services/review-classifier/anthropic-api-key`, field
|
||||
`api_key`.
|
||||
|
||||
|
|
|
|||
|
|
@ -562,6 +562,22 @@ let
|
|||
capabilities = ["create", "read", "update"]
|
||||
}
|
||||
|
||||
path "${credentialMountPath}/data/${classifierApiKeyLeaf}" {
|
||||
capabilities = ["create", "update"]
|
||||
}
|
||||
|
||||
path "${credentialMountPath}/metadata/${classifierApiKeyLeaf}" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
|
||||
path "${credentialMountPath}/data/${classifierAcpKeyLeaf}" {
|
||||
capabilities = ["create", "update"]
|
||||
}
|
||||
|
||||
path "${credentialMountPath}/metadata/${classifierAcpKeyLeaf}" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
|
||||
path "${credentialMountPath}/data/${builderForgeTokenLeaf}" {
|
||||
capabilities = ["create", "read", "update"]
|
||||
}
|
||||
|
|
@ -775,7 +791,10 @@ let
|
|||
classifierForgeTokenLeaf = "swarm/services/review-classifier/forge/token";
|
||||
|
||||
# The review classifier's Anthropic API key. The operator writes it through
|
||||
# the UI's OIDC login; the classifier reads it on every run.
|
||||
# the UI's OIDC login, or the swarm UI's classifier settings, which the
|
||||
# controller writes for them: `create` and `update` with no `read`, and a
|
||||
# metadata `read` for whether one is set and when it changed. The classifier
|
||||
# reads it on every run.
|
||||
classifierApiKeyLeaf = "swarm/services/review-classifier/anthropic-api-key";
|
||||
|
||||
# The swarm builder's forge token, the nix half of
|
||||
|
|
|
|||
|
|
@ -1934,15 +1934,18 @@ let
|
|||
# `forge::classifier_account` mints the review classifier's forge token
|
||||
# and reads it back to decide on a re-mint and to post reviews. Pinned
|
||||
# as the whole stanza, and spelled to the leaf, for the reason above.
|
||||
name = "the controller's grant on the review classifier is its forge token alone";
|
||||
name = "the controller's grant on the review classifier is its forge token, and a write-only inference key each";
|
||||
ok =
|
||||
let
|
||||
s = baoGrantHere.systemd.services.swarm-bao-controller-policy.script;
|
||||
writeOnly = leaf: [
|
||||
"path \"secret/data/swarm/services/review-classifier/${leaf}\" {\n capabilities = [\"create\", \"update\"]\n}"
|
||||
"path \"secret/metadata/swarm/services/review-classifier/${leaf}\" {\n capabilities = [\"read\"]\n}"
|
||||
];
|
||||
in
|
||||
lib.hasInfix "path \"secret/data/swarm/services/review-classifier/forge/token\" {\n capabilities = [\"create\", \"read\", \"update\"]\n}" s
|
||||
&& !(lib.hasInfix "secret/data/swarm/services/review-classifier/*" s)
|
||||
&& !(lib.hasInfix "secret/data/swarm/services/review-classifier/anthropic-api-key" s)
|
||||
&& !(lib.hasInfix "secret/data/swarm/services/review-classifier/acp-provider" s);
|
||||
&& lib.all (p: lib.hasInfix p s) (writeOnly "anthropic-api-key" ++ writeOnly "acp-provider")
|
||||
&& !(lib.hasInfix "secret/data/swarm/services/review-classifier/*" s);
|
||||
}
|
||||
{
|
||||
# The runner's role is the token's only reader. Its policy is that leaf
|
||||
|
|
|
|||
Loading…
Reference in a new issue