mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-24 18:19:05 +02:00
feat(connections): one Advanced disclosure, ranked default, armed write gate
Completes PAP-659 plan steps C0/C1/C2 and C6/C7 on this worktree. - Fold the key step's own Advanced settings into the same disclosure that holds the access controls, so every connector has exactly one Advanced in the same place rather than two on one screen. - Keep the disclosure open when what is inside it is load-bearing: a non-default method in use, or a selection the connector still needs. - Restore first-attempt vs retry semantics on the single primary action: the first press creates or resumes, and only a retry pays for the defensive re-read that recovers a create whose response was lost. - Show the resolved default on the one-time Cloud enrolment screen too, and state every reason the default cannot apply rather than only the first. - Show a loading state when a deep link arrives before the gallery resolves its definition; the deleted Access step used to carry that wait. - C6a: recommendedDefaultsForApp now returns askFirstRiskLevels ["write","destructive","high","critical"] instead of [], arming the approval gate that was already built but had nothing behind it. - C6b/C7: the Permissions tab gains a per-group bulk control and shows each action's risk level, so a tool the classifier misfiled is visible. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c2205a88b4
commit
b63aef204c
6 files changed
+220
-133
No files matched your search
@@ -617,12 +617,12 @@ describe("AppDefinition catalog", () => {
|
||||
APP_DEFINITIONS.find((app) => app.slug === "hugging-face")?.methods[0]
|
||||
?.defaults?.scopesHint,
|
||||
).toEqual(["read-mcp"]));
|
||||
it("defaults every new connection action to allowed", () => {
|
||||
it("defaults reads to allowed and state-changing actions to ask first", () => {
|
||||
for (const app of APP_DEFINITIONS)
|
||||
for (const method of app.methods)
|
||||
expect(recommendedDefaultsForApp(app, method.key)).toEqual({
|
||||
access: "all_agents",
|
||||
askFirstRiskLevels: [],
|
||||
askFirstRiskLevels: ["write", "destructive", "high", "critical"],
|
||||
});
|
||||
});
|
||||
it("defaults explicit read/write capability groups to their write-capable method", () => {
|
||||
|
||||
@@ -246,16 +246,33 @@ export function resolveConnectionMethodServerUrl(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Risk levels a fresh connection gates behind human approval (PAP-659 C6a).
|
||||
*
|
||||
* The runtime gate and its approval card already exist; what was missing was a
|
||||
* default with anything behind it. Reads stay Allowed so the constant read
|
||||
* traffic an agent does is never interrupted; anything that changes the
|
||||
* provider's state asks first, and one click on the Permissions tab turns that
|
||||
* off per connection.
|
||||
*
|
||||
* Two risk vocabularies are in use — `read|write|destructive` from the tool
|
||||
* classifier and `low|medium|high|critical` from curated catalogs — so both
|
||||
* are named rather than assuming callers normalise them.
|
||||
*/
|
||||
export const DEFAULT_ASK_FIRST_RISK_LEVELS = [
|
||||
"write",
|
||||
"destructive",
|
||||
"high",
|
||||
"critical",
|
||||
] as const;
|
||||
|
||||
export function recommendedDefaultsForApp(app: AppDefinition, methodKey?: string | null): Record<string, unknown> {
|
||||
// Keep the parameters in the public contract: callers resolve defaults for a
|
||||
// concrete app/method even though the initial policy is now uniform. This is
|
||||
// an open default, not an approval bypass: connection finalization remains a
|
||||
// configure-authorized, audited operation, and Ask first stays available as
|
||||
// an operator-selected policy for any action after the connection is made.
|
||||
// concrete app/method even though the initial policy is uniform.
|
||||
void app;
|
||||
void methodKey;
|
||||
return {
|
||||
access: "all_agents",
|
||||
askFirstRiskLevels: [],
|
||||
askFirstRiskLevels: [...DEFAULT_ASK_FIRST_RISK_LEVELS],
|
||||
};
|
||||
}
|
||||
@@ -329,6 +329,7 @@ export {
|
||||
getRecommendedConnectionMethod,
|
||||
isConnectableAppSlug,
|
||||
isAppStoreVisibleSlug,
|
||||
DEFAULT_ASK_FIRST_RISK_LEVELS,
|
||||
recommendedDefaultsForApp,
|
||||
resolveConnectionMethodServerUrl,
|
||||
} from "./app-definitions.js";
|
||||
|
||||
Reference in new issue
Block a user