Skip to content

feat(apps): show owner-site quota usage and structured quota errors - #8

Open
nandiheath wants to merge 1 commit into
block:mainfrom
nandiheath:nandi/owner-site-quota-client
Open

nandiheath wants to merge 1 commit into
block:mainfrom
nandiheath:nandi/owner-site-quota-client

Conversation

@nandiheath

@nandiheath nandiheath commented Sep 25, 2026 •

Copy link
Copy Markdown

What

bl apps is ready for Compose owner-site quotas:

  • Structured errors keep their recovery fields. Control-plane failures (for example owner_site_limit_reached, owner_site_quota_maintenance, tier_resolution_unavailable, owner_site_quota_unavailable, owner_site_quota_misconfigured) now carry the server's error.details and next_action (string or structured) into the CLI failure output, not just the error code. Both are credential-redacted and made terminal-safe. Raw bodies and backend messages are still never echoed. Object keys that contain the credential or terminal control characters are rejected.
  • Quota usage passes through. bl apps list --scope owned returns the server's owner quota metadata (accounting_enabled, enforcement_enabled, tier_status, current_count, max_sites, remaining, over_limit) unchanged. The help text explains that the list count is visible apps, not quota usage; that accounting-only limits are informational; and that an unavailable tier does not block listing.
  • Guidance for create/delete. The help text covers what to do after owner_site_limit_reached: inspect owned apps, don't auto-retry during maintenance or a tier outage, and note that existing apps stay manageable. Delete help explains that logical deletion releases quota even if cleanup fails, and how to check before retrying creation.
  • The README documents these behaviors.

Servers without quota support return no quota metadata or codes, and output is unchanged.

Verification

  • cargo fmt --all -- --check
  • cargo clippy --locked --workspace --all-targets --all-features -- -D warnings
  • cargo test --locked --workspace --all-features: all suites pass. That includes CLI process tests against a local HTTP fixture:
    • A quota rejection keeps its code, details and next_action, with no mutation retry.
    • Delete sends the confirmed app and environment and keeps cleanup details.
    • Every quota error code maps correctly.
    • Hostile next_action/details values have credentials and escape sequences removed.
  • package-smoke was not run locally (needs the internal packaging build).
  • A help-text test that pinned the old delete wording was removed. The behavior is covered by the process tests above.

@nandiheath
nandiheath marked this pull request as ready for review September 25, 2026 23:55
@nandiheath
nandiheath requested a review from a team as a code owner September 25, 2026 23:55

@jonwinton jonwinton left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

redact_json_value sanitizes successful responses as well as errors (authorized_json_request, delete_app), so the change at src/bl/apps.rs:1533 affects every successful Apps Platform response, not only the error recovery fields:

  • String values now go through terminal_safe_text, which rewrites newlines, tabs, and other control characters as literal Rust-style escapes (\n becomes the two characters \ n, ESC becomes \u{1b}). print_json already emits valid JSON with bidi controls escaped, so --json consumers only lose data. For example, multi-line pod logs from bl apps debug --json now arrive as a single line with literal \n sequences. The updated contract process test (nested.message expecting \\u{1b}[31m) reflects this change on the success path.
  • The stricter key check at line 1541 also applies to successful responses. A key containing any control or bidi character now fails the whole command. For delete, that surfaces as "delete outcome unknown" after a request that may have succeeded.

Consider applying terminal-safe escaping and the unsafe-key rejection only inside sanitize_field (error details and next_action), and leaving redact_json_value as credential redaction for successful responses.

Separately, the DCO check is failing; the commit needs a Signed-off-by trailer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants