Skip to content

Add unit mismatch validation and tenant existence checks#35

Merged
amavashev merged 3 commits intomainfrom
claude/audit-server-admin-sXb3F
Mar 24, 2026
Merged

Add unit mismatch validation and tenant existence checks#35
amavashev merged 3 commits intomainfrom
claude/audit-server-admin-sXb3F

Conversation

@amavashev
Copy link
Collaborator

Summary

This PR adds critical validation for unit mismatches in budget operations and implements tenant existence/status checks in budget and policy creation Lua scripts. It also fixes API key validation to reject deleted tenants and updates the audit documentation.

Key Changes

Unit Mismatch Validation

  • Added validateCreateUnits() in BudgetController.create() to ensure allocated amount unit matches budget unit
  • Added unit validation in BudgetController.fund() to verify funding amount unit matches budget unit
  • Added unit validation in BudgetController.update() to verify overdraft limit unit matches budget unit
  • All three endpoints now throw UNIT_MISMATCH error (400) when units don't match
  • Added comprehensive test coverage for all three scenarios in BudgetControllerTest

Tenant Existence & Status Checks

  • Updated CREATE_BUDGET_LUA script to validate tenant exists and is ACTIVE before creating budget
    • Returns -1 if tenant not found (404 TENANT_NOT_FOUND)
    • Returns -2 if tenant not ACTIVE (400 INVALID_REQUEST)
  • Updated CREATE_POLICY_LUA script with identical tenant validation logic
  • Added error handling in BudgetRepository.create() and PolicyRepository.create() to process Lua return codes
  • Added test cases in BudgetRepositoryTest and PolicyRepositoryTest for both tenant not found and tenant not active scenarios

API Key Validation Hardening

  • Modified ApiKeyRepository.validate() to return TENANT_NOT_FOUND when tenant data is missing (defense-in-depth)
  • Changed from silently accepting deleted tenants to explicitly rejecting them
  • Updated test in ApiKeyRepositoryTest.validate_tenantDataNull_returnsInvalid() to verify rejection

Tenant Creation Enhancement

  • Updated TenantRepository.create() to accept and use defaultReservationTtlMs, maxReservationTtlMs, maxReservationExtensions, and reservationExpiryPolicy from request
  • Falls back to spec defaults (60s, 1h, 10, AUTO_RELEASE) when not provided
  • Updated TenantCreateRequest model to include these four new optional fields

REPAY_DEBT Ledger Fix

  • Fixed Lua script in BudgetRepository to maintain ledger invariant:
    • Now increments remaining by repayment amount
    • When repayment < amount, also increments allocated by excess before updating remaining

Admin Key Auth Fix

  • Changed AuthInterceptor.validateAdminKey() to return 401 (not 403) for invalid admin keys per spec
  • Updated test in AuthInterceptorTest to expect 401 status

OpenAPI Spec Update

  • Added four new optional fields to TenantCreateRequest schema in complete-budget-governance-v0.1.24.yaml

Documentation

  • Updated AUDIT.md to reflect all 26 issues fixed across Rounds 1–5
  • Added production deployment notes section
  • Updated issue tracking table with Rounds 4–5 fixes

https://claude.ai/code/session_01VJvpvZFGJdxeXdU75D6M7a

claude added 3 commits March 24, 2026 18:28
…dation

Three spec-compliance and correctness fixes for release readiness:

1. REPAY_DEBT ledger invariant bug: the Lua script was not restoring
   repaid debt to remaining, and excess funds were added to remaining
   without updating allocated. This broke the invariant
   remaining = allocated - spent - reserved - debt.

2. AuthInterceptor: invalid admin API key returned 403 FORBIDDEN
   instead of 401 UNAUTHORIZED. Per spec, invalid credentials → 401;
   403 is for tenant mismatch/ownership violations.

3. Unit mismatch validation: budget create, fund, and update endpoints
   now validate that Amount.unit matches the budget's unit, returning
   400 UNIT_MISMATCH on mismatch. Prevents silently creating budgets
   with inconsistent unit fields.

https://claude.ai/code/session_01VJvpvZFGJdxeXdU75D6M7a
… tenants

Three data integrity fixes to prevent bad data from entering the system:

1. ApiKeyRepository.validate(): if tenant data is null (deleted from
   Redis), validation now returns valid=false with TENANT_NOT_FOUND
   instead of silently falling through to valid=true.

2. BudgetRepository.create(): Lua script now atomically validates
   tenant exists and is ACTIVE before creating the budget. Returns
   404 TENANT_NOT_FOUND or 400 if tenant is not ACTIVE. Per spec:
   "Tenant must exist and be ACTIVE" (createBudget description).

3. PolicyRepository.create(): same tenant validation added to the
   Lua script for consistency.

Also:
- TenantCreateRequest now accepts all config fields that were
  previously only settable via update: default_reservation_ttl_ms,
  max_reservation_ttl_ms, max_reservation_extensions,
  reservation_expiry_policy. OpenAPI spec updated to match.

https://claude.ai/code/session_01VJvpvZFGJdxeXdU75D6M7a
Documents all 7 issues found and fixed in the pre-release audit:
- #20: REPAY_DEBT ledger invariant (CRITICAL)
- #21: Invalid admin key 403→401 (MEDIUM)
- #22: Unit mismatch validation (MEDIUM)
- #23: Deleted tenant accepted by key validation (HIGH)
- #24-25: Budget/policy create without tenant check (HIGH)
- #26: TenantCreateRequest missing config fields (LOW)

Added production deployment notes section covering port, Redis,
logging, admin key config, and operational characteristics.

https://claude.ai/code/session_01VJvpvZFGJdxeXdU75D6M7a
@amavashev amavashev merged commit a0942d4 into main Mar 24, 2026
2 checks passed
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