Skip to content

[2/n] wire up the usage data to in-memory types#11111

Merged
IsaiahWitzke merged 13 commits into
masterfrom
iw/usage-visibility-model
May 17, 2026
Merged

[2/n] wire up the usage data to in-memory types#11111
IsaiahWitzke merged 13 commits into
masterfrom
iw/usage-visibility-model

Conversation

@IsaiahWitzke
Copy link
Copy Markdown
Contributor

@IsaiahWitzke IsaiahWitzke commented May 16, 2026

the global Workspace gets a Option<BillingCycleUsageData> now

IsaiahWitzke and others added 7 commits May 16, 2026 14:12
Adds freeAvailableModels back to the client query allowlist in
crates/warp_graphql_schema/api/client-schema.ts so it survives the
filtered codegen pass, then regenerates crates/warp_graphql_schema/api/schema.graphql
against staging. The regeneration also pulls in unrelated staging drift
that's been accumulating, including:

- New UsageVisibilityGranularity enum, UsageVisibilityPolicy type, and
  Tier.usageVisibilityPolicy field
- New AGGREGATE sentinel values on AICreditsUsageAndCostType,
  AICreditsUsageBucket, and AICreditsUsageSource
- Workspace.billingCycleUsageHistory and friends
- Harness*, AgentHarnessesPolicy, AgentVisibility, and harness settings
- enterpriseAnalyticsPolicy, enterpriseSpendingLimitsPolicy,
  enterpriseUsageThresholdsPolicy
- VOYAGE_4_512 EmbeddingConfig variant

Follow-up commits will resolve the resulting cynic compile errors in
crates/graphql.

Co-Authored-By: Oz <oz-agent@warp.dev>
After regenerating crates/warp_graphql_schema/api/schema.graphql against
staging, the warp_graphql crate failed to compile due to two
schema-drift issues that were unrelated to the freeAvailableModels
restoration:

- harnessAuthSecrets was missing from clientQueries in
  crates/warp_graphql_schema/api/client-schema.ts, so the filtered
  client schema lost the root query field plus its
  ListHarnessAuthSecretsInput, HarnessAuthSecretsOutput, and
  HarnessAuthSecretsResult types. Cynic then failed to compile the
  ListHarnessAuthSecrets fragment in
  crates/graphql/src/api/queries/list_harness_auth_secrets.rs. Adding
  the field to the allowlist and regenerating brings the types back.
- The EmbeddingConfig enum in
  crates/graphql/src/api/full_source_code_embedding.rs lacked the new
  VOYAGE_4_512 variant introduced server-side, so cynic refused to
  derive cynic::Enum on it. Added the variant with the matching
  #[cynic(rename = ...)] mapping.

cargo build -p warp_graphql and cargo clippy -p warp_graphql --tests
both succeed after these changes.

Co-Authored-By: Oz <oz-agent@warp.dev>
Adding VOYAGE_4_512 to the cynic EmbeddingConfig enum in the previous
commit broke the exhaustive From / TryFrom matches in
crates/ai/src/index/full_source_code_embedding/mod.rs.

Mirrors the new variant on the ai-side EmbeddingConfig enum and wires
both conversion match arms through to the new graphql variant, keeping
the workspace build green.

cargo build -p ai and cargo clippy -p ai --all-targets --all-features
--tests are both green after this change.

Co-Authored-By: Oz <oz-agent@warp.dev>
Adds the Rust shapes for the new server-side surface from the
tiered-usage-visibility spec, all in crates/graphql/src/api/billing.rs:

- UsageVisibilityPolicy and UsageVisibilityGranularity, with the new
  field plumbed through the Tier fragment.
- BillingCycleUsageHistory, BillingCycleUsageSummary, UsageEntry.
- AICreditsUsageAndCostSubjectType, AICreditsUsageAndCostType (with
  AGGREGATE sentinel), AICreditsUsageBucket (with AGGREGATE), and
  AICreditsUsageSource (with AGGREGATE).

All new enums carry a #[cynic(fallback)] Other(String) variant so the
client stays forward-compatible with future server-side additions.
Nothing in the client queries these fields yet; that comes in
subsequent PRs.

Co-Authored-By: Oz <oz-agent@warp.dev>
Wires the new cynic types into the workspace metadata query so the
client actually fetches the per-cycle usage breakdown and the tier's
visibility policy. No consumers yet — model conversion and rendering
land in subsequent PRs.

Co-Authored-By: Oz <oz-agent@warp.dev>
Adds the Rust-side mirrors of the new GraphQL types:

* BillingCycleUsageEntry / Summary / Data — the redacted per-cycle usage
  data returned by Workspace.billingCycleUsageHistory.
* UsageVisibilityGranularity / UsageVisibilityPolicy / UsageVisibility —
  the tier's visibility policy and the resolved per-viewer view of it.
  MaxPriorCycles is its own enum so consumers never have to handle the
  -1 sentinel from the wire format.

Tier.usage_visibility_policy and Workspace.billing_cycle_usage are
threaded through so the data has a place to land. Real From conversions
land in the next commit; for now gql_convert sets both to defaults so the
crate continues to compile.

UsageVisibility carries a temporary #[allow(dead_code)] because its
first consumer (resolve_usage_visibility) lands in the commit after gql
conversion. That annotation goes away once the resolver is added.

Co-Authored-By: Oz <oz-agent@warp.dev>
* From<GqlUsageVisibilityGranularity> for UsageVisibilityGranularity:
  maps each variant through; Other(_) is logged and falls back to OwnOnly
  (fail-closed).
* from_gql_max_prior_cycles: i32 -> MaxPriorCycles, turning the wire
  format's -1 sentinel into Unlimited and 0/N>0 into None/Limited(n).
  Defensively maps any other negative value to Unlimited with a logged
  error.
* From<GqlUsageVisibilityPolicy> for UsageVisibilityPolicy: composes
  the above two.
* convert_billing_cycle_usage: maps the nullable
  GqlBillingCycleUsageHistory into BillingCycleUsageData, flattening
  Time -> chrono::DateTime<Utc> and preserving entry shape.

Tier and Workspace conversions now use these instead of the temporary
defaults stubbed in the previous commit.

Co-Authored-By: Oz <oz-agent@warp.dev>
@cla-bot cla-bot Bot added the cla-signed label May 16, 2026
The helper folds the tier's UsageVisibilityPolicy and the viewer's admin
status into a single UsageVisibility value that downstream UI code can
match on. Admins (Owner or Admin, per Workspace::is_workspace_admin,
which matches the server's HasAdminLevelPermissions) get the policy's
admin_granularity; everyone else collapses to OwnOnly. max_prior_cycles
is plan-wide and applies to all viewers. Missing policy or viewer email
fails closed to the default {OwnOnly, MaxPriorCycles::None} \u2014 matching
the server's default-deny posture.

Tests cover the matrix: missing policy, missing viewer email, non-member
email, free user, Build admin, Build non-admin, Build Business admin,
Build Business non-admin, Enterprise admin, and an Admin-role-no-Owner
viewer.

UsageVisibility until the UI scaffold PR consumes them; the lint only
counts non-test usage.

Includes downstream fixups for test-only Workspace literals in
user_workspaces.rs (cfg(test) block), user_workspaces_tests.rs,
update_environment_form_tests.rs, and integration_testing/assertions.rs
\u2014 each gets billing_cycle_usage: Default::default() so the new
required field compiles in every test build.

Co-Authored-By: Oz <oz-agent@warp.dev>
@IsaiahWitzke IsaiahWitzke force-pushed the iw/usage-visibility-model branch from 3e7aeec to b6d0755 Compare May 16, 2026 20:29
…bounds

Mirror the GraphQL nullability exactly: the outer BillingCycleUsageHistory
is nullable, but currentPeriodStart/currentPeriodEnd are non-null when it
is present. Previously the Rust mirror flipped this — the outer field was
non-Optional and the two period bounds were independently Optional, which
admitted impossible states (one bound present and the other absent) and
required convert_billing_cycle_usage to synthesize a sentinel default.

Now:
- Workspace.billing_cycle_usage: Option<BillingCycleUsageData>
- BillingCycleUsageData.current_period_start/end are non-Optional DateTime
- convert_billing_cycle_usage takes the non-Optional GQL type directly; the
  outer Option is mapped at the call site

Co-Authored-By: Oz <oz-agent@warp.dev>
@IsaiahWitzke IsaiahWitzke marked this pull request as ready for review May 16, 2026 21:18
@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 16, 2026

@IsaiahWitzke

I'm starting a first review of this pull request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

This PR adds in-memory workspace usage-visibility types, GraphQL conversion for usage visibility and billing-cycle usage history, and resolver tests for admin versus non-admin visibility.

Concerns

  • Unexpected negative maxPriorCycles values currently fail open to unlimited history instead of failing closed.

Security

  • The maxPriorCycles conversion should not expand historical usage access when the server/client contract drifts or returns an invalid negative value.

Verdict

Found: 0 critical, 1 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Comment thread app/src/workspaces/gql_convert.rs Outdated
Hoists the helper from the standalone usage_visibility module onto the
Workspace struct and decouples it from the email-based admin lookup. The
function now takes the resolved is_admin bool directly, which:
- separates 'is the viewer an admin?' (caller's concern) from 'what
  visibility does that imply?' (policy's concern)
- makes the unit tests simpler (no need to construct workspace member
  lists)
- lets non-email callers (service accounts, future programmatic flows)
  resolve visibility without going through an email lookup

Deletes the now-empty usage_visibility / usage_visibility_tests modules
and folds the tests into the standard workspace_tests.rs sibling.

Co-Authored-By: Oz <oz-agent@warp.dev>
Comment thread app/src/workspaces/gql_convert.rs Outdated
Comment thread app/src/workspaces/gql_convert.rs Outdated
Comment thread app/src/workspaces/gql_convert.rs Outdated
Base automatically changed from iw/seat-caps-changes-2 to master May 17, 2026 05:51
@IsaiahWitzke IsaiahWitzke enabled auto-merge (squash) May 17, 2026 05:52
@IsaiahWitzke IsaiahWitzke merged commit d5d4832 into master May 17, 2026
25 checks passed
@IsaiahWitzke IsaiahWitzke deleted the iw/usage-visibility-model branch May 17, 2026 06:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants