Public: anyone can read this; the crew can change it.

Every credential is a subscription — the platform token included — with a live spend breakdown by credential, app, agent and issue #539

Merged opened this in answer to

Check · Review · Land · Live done — Landed and live in production.

Merged

The forge's own token now has its own subscription row, `platform (env)`, so the board and the Subscriptions page count what the crew spends on it. Every subscription has a scope: the list of orgs and repos it may be used for. An account with an empty scope, like `trevato-espo`, is never given to the crew. Spend is split by credential, repo, agent, issue and run kind (build, plan, review, check) f…

shipped production is serving it deploy a4add02

opened this

The forge's own token now has its own subscription row, platform (env), so the board and the Subscriptions page count what the crew spends on it. Every subscription has a scope: the list of orgs and repos it may be used for. An account with an empty scope, like trevato-espo, is never given to the crew. Spend is split by credential, repo, agent, issue and run kind (build, plan, review, check) for the 5-hour window, today and the week, and a running session's spend is recorded as it is reported. The check command (tsc plus the 43 test files) passed 642 of 643 tests. The one failure was a flaky test, now fixed; I re-ran only that file afterwards, not the whole check.

  • Platform row and migration 41 (src/core/schema.ts, src/core/subscriptions.ts): the row is platform and holds no sealed token, because its credential comes from the forge's environment. It is listed first, can never be granted or removed, and is what a run gets when no grant reaches its repo. Existing ledger lines and agent runs that had no credential recorded become platform. The ledger gains a run kind and a running outcome. SQLite can't loosen that column constraint in place, so the migration copies the ledger into a new table — worth a look.
  • Scope: an account's grants are its allow-list (owner/name, @org, or one agent). Credential choice never picks an account whose scope doesn't include the run's repo. The board and the Subscriptions page list the crew's credentials first and show accounts with an empty scope in a separate group with their own window stats, so their numbers don't look like idle crew capacity.
  • Spend breakdown (src/actions/spend.ts, src/web/pages/spend.ts): tokens in and out, units and cost, plus the 10 costliest runs. It appears on the Subscriptions page, on the board, and through the MCP usage read.
  • Live updates (src/crew/claude.ts, src/crew/runner.ts): while a session runs, the runner rewrites a running line with the tokens and cost reported so far and pushes it over /events. The final line replaces it when the run ends.
  • Tests (test/credentials.test.ts):

- a run on the env token is counted under platform (env), and its totals move mid-run; - an account with an empty scope, or one scoped to another repo, is never picked; - the breakdown sums match a hand calculation; - the page groups the credentials as described.

Two existing tests were wrong, not the code, so I changed the tests:

  • checks ("newest queued check runs first"): this is the test that closed pull #472. The check holding the slot slept a fixed 2 seconds, which on a loaded machine ran out before the three newer pushes were queued. It now waits for a file the test writes once all three are queued.
  • apps-busy ("child still working survives the sweep"): the child process worked for 2 seconds but the test checked at 1.4 seconds, so under load the child had finished and the app was put to sleep. That was the one failure in the full check. The child now works 5 seconds, and the file passed on its own after the change.

I didn't add a separate "person only" flag: an empty scope does that job and is the rule the owner settled on in the issue. trevato-espo stays unscoped until someone grants it work repos.

To try it: open the preview's Subscriptions page and the board. platform (env) is first with its window and the breakdown, and trevato-espo is in its own group. Start a run and watch the numbers change while it works.

🤖 Generated with Claude Code

Closes #460

commented

The forge's own token now has its own subscription row, platform (env), so the board and the Subscriptions page count what the crew spends on it. Every subscription has a scope: the list of orgs and repos it may be used for. An account with an empty scope, like trevato-espo, is never given to the crew. Spend is split by credential, repo, agent, issue and run kind (build, plan, review, check) for the 5-hour window, today and the week, and a running session's spend is recorded as it is reported. With main merged in, the check passes: tsc plus 662 tests across 44 files, 0 failures. check.run in forge.json is 463 characters, under the forge's 1000-character limit.

  • Platform row and migration 42 (src/core/schema.ts, src/core/subscriptions.ts): the row is platform and holds no sealed token, because its credential comes from the forge's environment. It is listed first, can never be granted or removed, and is what a run gets when no grant reaches its repo. Existing ledger lines and agent runs that had no credential recorded become platform. The ledger gains a run kind and a running outcome. SQLite can't loosen that column constraint in place, so the migration copies the ledger into a new table — worth a look. It is numbered 42 because main's meter migration took 41.
  • Scope: an account's grants are its allow-list (owner/name, @org, or one agent). Credential choice never picks an account whose scope doesn't include the run's repo. The board and the Subscriptions page list the crew's credentials first and show accounts with an empty scope in a separate group with their own window stats, so their numbers don't look like idle crew capacity.
  • Spend breakdown (src/actions/spend.ts, src/web/pages/spend.ts): tokens in and out, units and cost, plus the 10 costliest runs. It appears on the Subscriptions page, on the board, and through the MCP usage read.
  • Live updates (src/crew/claude.ts, src/crew/runner.ts): while a session runs, the runner rewrites a running line with the tokens and cost reported so far and pushes it over /events. The final line replaces it when the run ends.
  • Tests (test/credentials.test.ts, now in the check as credentials):

- a run on the env token is counted under platform (env), and its totals move mid-run; - an account with an empty scope, or one scoped to another repo, is never picked; - the breakdown sums match a hand calculation; - the page groups the credentials as described.

  • apps-busy test was wrong, not the code: its child process worked 2 seconds but the test checked at 1.4 seconds, so under load the app was put to sleep first. The child now works 5 seconds.
  • checks test: main has its own fix for the queue-order test that closed pull #472, so this branch takes main's version.

I didn't add a separate "person only" flag: an empty scope does that job and is the rule the owner settled on in the issue. trevato-espo stays unscoped until someone grants it work repos.

To try it: open the preview's Subscriptions page and the board. platform (env) is first with its window and the breakdown, and trevato-espo is in its own group. Start a run and watch the numbers change while it works.

🤖 Generated with Claude Code

commented

The forge's own token now has its own subscription row, platform (env), so the board and the Subscriptions page count what the crew spends on it. Every subscription has a scope: the list of orgs and repos it may be used for. An account with an empty scope, like trevato-espo, is never given to the crew. Spend is split by credential, repo, agent, issue and run kind (build, plan, review, check) for the 5-hour window, today and the week, and a running session's spend is recorded as it is reported. With the latest main merged in, the check passes: tsc plus 668 tests across 45 files, 0 failures. The only conflict was the test list in forge.json: main added guard, this branch added credentials, and the list keeps both.

  • Platform row and migration 42 (src/core/schema.ts, src/core/subscriptions.ts): the row is platform and holds no sealed token, because its credential comes from the forge's environment. It is listed first, can never be granted or removed, and is what a run gets when no grant reaches its repo. Existing ledger lines and agent runs that had no credential recorded become platform. The ledger gains a run kind and a running outcome. SQLite can't loosen that column constraint in place, so the migration copies the ledger into a new table — worth a look. It comes after main's meter migration (41).
  • Scope: an account's grants are its allow-list (owner/name, @org, or one agent). Credential choice never picks an account whose scope doesn't include the run's repo. The board and the Subscriptions page list the crew's credentials first and show accounts with an empty scope in a separate group with their own window stats, so their numbers don't look like idle crew capacity.
  • Spend breakdown (src/actions/spend.ts, src/web/pages/spend.ts): tokens in and out, units and cost, plus the 10 costliest runs. It appears on the Subscriptions page, on the board, and through the MCP usage read.
  • Live updates (src/crew/claude.ts, src/crew/runner.ts): while a session runs, the runner rewrites a running line with the tokens and cost reported so far and pushes it over /events. The final line replaces it when the run ends.
  • Tests (test/credentials.test.ts, in the check as credentials):

- a run on the env token is counted under platform (env), and its totals move mid-run; - an account with an empty scope, or one scoped to another repo, is never picked; - the breakdown sums match a hand calculation; - the page groups the credentials as described.

  • apps-busy test was wrong, not the code: its child process worked 2 seconds but the test checked at 1.4 seconds, so under load the app was put to sleep first. The child now works 5 seconds.

I didn't add a separate "person only" flag: an empty scope does that job and is the rule the owner settled on in the issue. trevato-espo stays unscoped until someone grants it work repos.

To try it: open the preview's Subscriptions page and the board. platform (env) is first with its window and the breakdown, and trevato-espo is in its own group. Start a run and watch the numbers change while it works.

🤖 Generated with Claude Code

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs