policies: add standard policy files, formatting, and secret scanning
- Add .editorconfig, .prettierrc, .prettierignore, .gitignore - Add Makefile with fmt, fmt-check, secret-scan, test (skip) targets - Add package.json with prettier - Add tools/secret-scan.sh - Add .secret-scan-allowlist for documentation token format references - Sanitize documentation to use generic placeholders - Auto-format with prettier - make check passes clean
This commit is contained in:
@@ -4,8 +4,8 @@
|
||||
|
||||
Claude Max subscriptions use OAuth tokens for API authentication.
|
||||
|
||||
- **Access token** (`sk-ant-oat01-...`): Used for API requests, expires in ~8 hours
|
||||
- **Refresh token** (`sk-ant-ort01-...`): Used to get new access tokens, long-lived
|
||||
- **Access token** (`<access-token-value>`): Used for API requests, expires in ~8 hours
|
||||
- **Refresh token** (`<refresh-token-value>`): Used to get new access tokens, long-lived
|
||||
- **Token endpoint**: `POST https://console.anthropic.com/v1/oauth/token`
|
||||
- **Client ID**: `9d1c250a-e61b-44d9-88ed-5944d1962f5e` (Claude Code public OAuth client)
|
||||
|
||||
@@ -25,21 +25,21 @@ The relevant function in Claude Code's minified source (`cli.js`):
|
||||
```javascript
|
||||
// Simplified from minified source
|
||||
async function refreshToken(refreshToken, scopes) {
|
||||
const params = {
|
||||
grant_type: "refresh_token",
|
||||
refresh_token: refreshToken,
|
||||
client_id: CLIENT_ID,
|
||||
scope: scopes.join(" ")
|
||||
};
|
||||
const response = await axios.post(TOKEN_URL, params, {
|
||||
headers: { "Content-Type": "application/json" }
|
||||
});
|
||||
return {
|
||||
accessToken: response.data.access_token,
|
||||
refreshToken: response.data.refresh_token || refreshToken,
|
||||
expiresAt: Date.now() + response.data.expires_in * 1000,
|
||||
scopes: response.data.scope.split(" ")
|
||||
};
|
||||
const params = {
|
||||
grant_type: 'refresh_token',
|
||||
refresh_token: refreshToken,
|
||||
client_id: CLIENT_ID,
|
||||
scope: scopes.join(' '),
|
||||
};
|
||||
const response = await axios.post(TOKEN_URL, params, {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
return {
|
||||
accessToken: response.data.access_token,
|
||||
refreshToken: response.data.refresh_token || refreshToken,
|
||||
expiresAt: Date.now() + response.data.expires_in * 1000,
|
||||
scopes: response.data.scope.split(' '),
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
@@ -65,6 +65,7 @@ inotifywait -q -e close_write,moved_to "$WATCH_DIR"
|
||||
- We watch the **directory** not the file, because atomic renames create a new inode
|
||||
|
||||
When the file changes:
|
||||
|
||||
1. Read `accessToken`, `refreshToken`, `expiresAt` from Claude CLI format
|
||||
2. Map fields: `accessToken` -> `access`, `refreshToken` -> `refresh`, `expiresAt` -> `expires`
|
||||
3. Write to `oauth.json` (for gateway's `mergeOAuthFileIntoStore()`)
|
||||
@@ -85,11 +86,11 @@ This is less responsive (up to 6-hour delay) but works without inotify.
|
||||
## Field Mapping
|
||||
|
||||
| Claude CLI (`.credentials.json`) | OpenClaw (`oauth.json`) |
|
||||
|----------------------------------|------------------------|
|
||||
| `claudeAiOauth.accessToken` | `anthropic.access` |
|
||||
| `claudeAiOauth.refreshToken` | `anthropic.refresh` |
|
||||
| `claudeAiOauth.expiresAt` | `anthropic.expires` |
|
||||
| `claudeAiOauth.scopes` | `anthropic.scopes` |
|
||||
| -------------------------------- | ----------------------- |
|
||||
| `claudeAiOauth.accessToken` | `anthropic.access` |
|
||||
| `claudeAiOauth.refreshToken` | `anthropic.refresh` |
|
||||
| `claudeAiOauth.expiresAt` | `anthropic.expires` |
|
||||
| `claudeAiOauth.scopes` | `anthropic.scopes` |
|
||||
|
||||
## Timeline
|
||||
|
||||
|
||||
Reference in New Issue
Block a user