Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions engine/app/models/coplan/api_token.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ module CoPlan
class ApiToken < ApplicationRecord
HOLDER_TYPE = "local_agent"

DEFAULT_SESSION_TTL = 12.hours
MAX_SESSION_TTL = 7.days
DEFAULT_SESSION_TTL = 7.days
Comment thread
HamptonMakes marked this conversation as resolved.
MAX_SESSION_TTL = 30.days
MIN_SESSION_TTL = 1.minute

# Matches the comment agent_name cap so a token's name can always be
Expand Down
4 changes: 2 additions & 2 deletions engine/app/views/coplan/agent_instructions/show.text.erb
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ Mint one as your first call (this is the only endpoint that works on request aut
```bash
<%= @curl %> -X POST \
-H "Content-Type: application/json" \
-d '{"agent_name": "Claude", "name": "claude run", "ttl_seconds": 43200, "metadata": {"harness": "claude-code", "harness_version": "2.1.3", "model": "claude-fable-5"}}' \
-d '{"agent_name": "Claude", "name": "claude run", "metadata": {"harness": "claude-code", "harness_version": "2.1.3", "model": "claude-fable-5"}}' \
"<%= @base %>/api/v1/tokens" | jq .
```

- `agent_name`: who you are ("Claude", "Amp") — stamped on every version, event, and comment you write. Truncated past 20 characters.
- `metadata`: optional JSON object of identity facts about this run — schemaless, like a User-Agent string. Suggested keys: `harness`, `harness_version`, `model`. Recorded on the token, and everything you write links back to it, so include whatever would help a human reading the history later understand what produced the edit. Capped at 4 KB.
- `ttl_seconds`: optional, default 12 hours, max 7 days.
- `ttl_seconds`: optional, default 7 days, max 30 days.
- The response's `token` is shown once. Send it as `Authorization: Bearer <token>` on every subsequent call.
- Mint once at the start of your run and reuse it — minting per call would give you a new identity every time.
- When you finish, `DELETE <%= @base %>/api/v1/tokens/current` (authenticated with the token itself) so the credential dies with the run instead of waiting out its TTL.
Expand Down
6 changes: 3 additions & 3 deletions spec/models/api_token_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
expect(child.user_id).to eq(user.id)
expect(child.parent_id).to eq(parent.id)
expect(child.agent_name).to eq("Claude refactor")
expect(child.expires_at).to be_within(1.minute).of(12.hours.from_now)
expect(child.expires_at).to be_within(1.minute).of(described_class::DEFAULT_SESSION_TTL.from_now)
expect(CoPlan::ApiToken.authenticate(raw)).to eq(child)
end

Expand All @@ -82,7 +82,7 @@
end

it "clamps the ttl to the maximum" do
child, = parent.mint_session_token!(ttl: 30.days)
child, = parent.mint_session_token!(ttl: 60.days)
expect(child.expires_at).to be_within(1.minute).of(described_class::MAX_SESSION_TTL.from_now)
end

Expand Down Expand Up @@ -156,7 +156,7 @@
expect(token.user_id).to eq(user.id)
expect(token.parent_id).to be_nil
expect(token.agent_name).to eq("Claude")
expect(token.expires_at).to be_within(1.minute).of(12.hours.from_now)
expect(token.expires_at).to be_within(1.minute).of(CoPlan::ApiToken::DEFAULT_SESSION_TTL.from_now)
expect(CoPlan::ApiToken.authenticate(raw)).to eq(token)
end

Expand Down
Loading