recess-cli 3.0.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -77,13 +77,19 @@ Create an approved `OAuthClient` row in each Recess environment. This remains a
77
77
 
78
78
  The production row ID (`c7e34138-18f9-45b1-a2fb-26a4e3a6d739`) is the CLI's built-in default, so production login needs no client-ID setup. `--client-id`, `RECESS_CLI_OAUTH_CLIENT_ID`, and a stored client ID remain overrides for local/staging clients. The web-server decodes the assertion audience, loads that exact `OAuthClient`, and requires both `approved` and `adminCliEnabled`; there is no separate server environment allowlist. Production redirect validation is exact, so a different callback port must also be explicitly registered.
79
79
 
80
- The browser SSO assertion is exchanged once and discarded. The CLI stores a separate 12-hour signed Recess session at `~/.recess-cli/config.json` with mode `0600`. A guardian must hold the live `access:ai` permission; removing it immediately invalidates session checks. Guardian sessions cannot call `/admin` routes and every target is independently restricted to their family. A KID session has `village_home` scope: application-level and shared-auth fences permit only session inspection and Village assertion minting, denying every other backend route.
80
+ The browser SSO assertion is exchanged once and discarded. The CLI stores a separate signed Recess session (12 hours by default) at `~/.recess-cli/config.json` with mode `0600`. A guardian must hold the live `access:ai` permission; removing it immediately invalidates session checks. Guardian sessions cannot call `/admin` routes and every target is independently restricted to their family. A KID session has `village_home` scope: application-level and shared-auth fences permit only session inspection and Village assertion minting, denying every other backend route.
81
81
 
82
82
  ```bash
83
83
  recess --json auth login
84
84
  recess --json doctor --reason "Verify CLI connectivity, identity, and scope"
85
85
  ```
86
86
 
87
+ Sessions default to 12 hours. Admins can request 30 days locally with
88
+ `recess --json auth login --duration 30d`, or remotely with
89
+ `recess --json auth request --duration 30d --label "remote agent"`, approve the link as an
90
+ admin, then run `recess --json auth poll`. The approval page shows the requested duration;
91
+ the link still expires after 10 minutes. Non-admins cannot authorize 30-day sessions.
92
+
87
93
  ## Testing against a local server
88
94
 
89
95
  `auth login` opens production SSO, so local iteration uses the env-cookie hatch instead:
package/dist/args.js CHANGED
@@ -6,6 +6,7 @@ import { CliError } from "./errors.js";
6
6
  */
7
7
  export const REPEATABLE_FLAGS = new Set(["kid", "unassign"]);
8
8
  const BOOLEAN_FLAGS = new Set([
9
+ "allow-assigned-edits",
9
10
  "all-references",
10
11
  "allow-strand",
11
12
  "cancel-subscriptions",
package/dist/auth.js CHANGED
@@ -77,7 +77,11 @@ export async function login(config, options) {
77
77
  const assertion = await callback;
78
78
  const response = await fetch(new URL("/auth/admin-cli/exchange/", config.apiOrigin), {
79
79
  method: "POST",
80
- headers: cliRequestHeaders({ authorization: `Bearer ${assertion}` }),
80
+ headers: cliRequestHeaders({
81
+ authorization: `Bearer ${assertion}`,
82
+ "content-type": "application/json",
83
+ }),
84
+ body: JSON.stringify({ sessionDuration: options.sessionDuration }),
81
85
  });
82
86
  const body = (await response.json());
83
87
  if (!response.ok)
@@ -109,7 +113,7 @@ export async function requestDeviceAuth(config, options) {
109
113
  const response = await fetch(new URL("/auth/admin-cli/device/authorize/", config.apiOrigin), {
110
114
  method: "POST",
111
115
  headers: cliRequestHeaders({ "content-type": "application/json" }),
112
- body: JSON.stringify(options.label ? { label: options.label } : {}),
116
+ body: JSON.stringify(options),
113
117
  });
114
118
  const body = (await response.json());
115
119
  if (!response.ok)
@@ -128,7 +132,8 @@ export async function requestDeviceAuth(config, options) {
128
132
  userCode: authorize.userCode,
129
133
  expiresAt: authorize.expiresAt,
130
134
  interval: authorize.interval,
131
- instructions: `Open ${authorize.approvalUrl} in a browser and approve it while signed in to Recess as the person this agent should act as — the session takes on THAT account's scope, so a guardian grants family-only access. Then run \`recess auth poll\`.`,
135
+ sessionDuration: options.sessionDuration ?? "12h",
136
+ instructions: `Open ${authorize.approvalUrl} in a browser and approve it while signed in to Recess ${options.sessionDuration === "30d" ? "as an admin to authorize 30 days of access" : "as the person this agent should act as"} — the session takes on THAT account's scope, so a guardian grants family-only access. Then run \`recess auth poll\`.`,
132
137
  };
133
138
  }
134
139
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));