Make the policy decision point pluggable (the rules are injectable, the evaluator is not)
Maintainer antworten meist innerhalb von 1 Tag
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 5/5
- Geschätzter Aufwand
- Über eine Woche
- Anfängerfreundlichkeit
- 35/100
- Issue-Typ
- Feature
- Klarheit
- Größtenteils klar
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- typescript
- Bereich
- authorization, security
Rechercherichtung
Beginne mit server/src/computer/gateway.ts ungefähr bei den Zeilen 469-535 sowie mit server/src/computer/policy.ts ungefähr bei den Zeilen 4-12, 38-42, 44-153 und 210-243. Bestätige, ob das Enterprise-Gateway bereits einen steckbaren Entscheidungspunkt besitzt, und definiere und dokumentiere anschließend den decider-Vertrag unter Beibehaltung der Snapshot-Auflösung, der dry-run-Verarbeitung, der Audit-Reihenfolge und des fail-closed-Verhaltens; abgeschlossen ist die Aufgabe, wenn der Standardpfad und ein ausgearbeitetes Beispiel für einen decider enthalten sind.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
What I see today
The policy data is already fully injectable. options.policy() is a getter
(server/src/computer/gateway.ts:523), backed by createPolicyStore with
ACTION_POLICY_TOPIC for live reload (server/src/computer/policy-store.ts).
The evaluator is not. evaluateActionPolicy is a direct import from ./policy,
called synchronously:
const decision = evaluateActionPolicy(options.policy(), context);
So a deployment can change the rules, but not who answers.
Why that's worth a seam
Three cases the current shape can't serve:
-
A deployment that already owns a policy engine. OPA/Rego, Cedar, an internal
service. Today they have to transcribe their rules into CEL and keep two sources in
sync, which is exactly the setup where the two drift and nobody notices. -
Decisions that need state the gateway doesn't hold. "This bot has already
submitted three orders today." "This action is above the amount this actor may
approve alone." "A human granted this, twenty minutes ago, and the grant expires."
CEL over a statelessPolicyContextcan't express any of those — not a flaw in the
expression language, just a different question. -
Decisions that take time. Anything involving a human in the loop is async by
nature, and the current call site is synchronous.
The good news is that most of the work is already done: PolicyContext
(server/src/computer/policy.ts:44-153) is a clean, serialisable, effect-level
object — intent, mcp.effect, file.extension, command, resolved element. That
is a better PDP boundary than most systems that set out to build one.
Concrete shape
export type PolicyDecider = (
context: PolicyContext,
) => PolicyDecision | Promise<PolicyDecision>;
Default stays exactly what happens now:
const decide: PolicyDecider = options.decide
?? ((ctx) => evaluateActionPolicy(options.policy(), ctx));
// ...
const decision = await decide(context);
Line 523 is already inside an async method that awaits write(...) on the next
line, so the await costs nothing structurally.
Two things I'd want written into the contract, not left to the implementer:
- A decider that throws, or exceeds its timeout, is a refusal. Same discipline as
matches()and itsonErrorargument (policy.ts:210-243). A remote PDP that is
merely unreachable must not be a way to get an action through, and the timeout should
be required rather than optional. dry-runstays in the gateway, not in the decider. Otherwise an external decider
can silently disable enforcement for the whole deployment, which is the one thing this
seam must not make possible.
What I would not touch
- Snapshot resolution stays server-side (
gateway.ts:469-471). A decider receives the
element the server resolved, never what the caller claimed. The comment at
policy.ts:38-42is the reason the whole thing works and an external decider must not
get a chance to weaken it. - The gateway still writes the audit row before forwarding (
gateway.ts:524-535),
whoever decided. The trail records the decision, not the decider's opinion of it.
One question before any of this
policy.ts:4-12 says this mirrors the policy engine in CopilotKit's enterprise agent
gateway, deliberately, so a rule means the same thing in both. Does that engine already
have a pluggable decision point — and if not, is divergence here something you'd rather
avoid? If so, say and I'll drop it; that's a good reason.
Otherwise I'm happy to send the PR: default path byte-for-byte unchanged, the type, the
fail-closed timeout, and one worked example decider.
Disclosure: I build an authorization service for agents, so an external PDP is
obviously useful to me. I've tried to write this as it would stand without that —
push back if it reads otherwise.
- Vorherrschende Sprache
- TypeScript
- Sterne
- 6.6k
- Forks
- 914
- Ø Merge
- 22 Std. 44 Min.
- Gemergte PRs (30 T.)
- 137
Entwicklungsumgebung
- Enthält ein Dockerfile oder eine Docker-Compose-Datei
- Hat eine Pull-Request-Vorlage
- Kein Beitragsleitfaden
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus CopilotKit/OpenBot
-
Telemetry scrubber: case-insensitive mysql rule redacts an attached port (-P3306) and lets a real password survive in the same commandEvtl. vergeben Ein verknüpfter Pull Request ist offen oder bereits gemergt. Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
CopilotKit/OpenBot#815 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Wrong key location at startupEvtl. vergeben @charan-rathore hat das vor 4 Tagen übernommen. Offen
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 68/100
CopilotKit/OpenBot#800 ·
Maintainer antworten meist innerhalb von 1 Tag
-
setup-learning.ts fails on Windows with "spawn npx.cmd EINVAL"Evtl. vergeben @Caldas hat das vor 7 Tagen übernommen. Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 80/100
CopilotKit/OpenBot#792 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Remote AG-UI Bots can't use the browser in chat: `computer_*` calls refused as "unavailable for this headless turn"Evtl. vergeben @charan-rathore hat das vor 3 Tagen übernommen. Offen
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 68/100
CopilotKit/OpenBot#804 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 4/5 Über eine Woche Anfängerfreundlichkeit 22/100
CopilotKit/OpenBot#786 ·
Maintainer antworten meist innerhalb von 1 Tag
Alle Issues in CopilotKit/OpenBot
Ähnliche Issues
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 83/100
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 1/5 1-3 Stunden Anfängerfreundlichkeit 72/100
zts212653/clowder-ai#1678 ·
Maintainer antworten meist innerhalb von 1 Tag
-
good first issue
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 64/100
Progressive-Victory/the-website#680 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
Maintainer antworten meist innerhalb von 1 Tag
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 68/100