Add team budget system with spending limits #10
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Castle currently has no budget tracking or enforcement. We need a budget system where teams (modeled as RBAC roles) can have spending limits per account per period. When a user submits an expense that would exceed their team's budget, the submission should be blocked or flagged.
Use Case
Organizations with multiple teams/departments need to:
Proposed Data Model
Proposed Endpoints
Budget Utilization Query
Current spending can be calculated via BQL:
Enforcement
When a user submits an expense via
POST /entries/expense:budget_remaining,budget_limit,budget_utilization_pctFrontend Integration
The Castle standalone app will display:
Cross-linking aiolabs/webapp#55 — there's a cross-module "teams" concept brewing that also wants to land in tasks (aiolabs/tasks#1) and possibly events. Worth a quick alignment before this issue's RBAC-role model lands, because the two designs collide in an interesting way:
libra#10 today models a team as an internal RBAC role inside castle. Memberships live in libra's own DB and aren't visible to other modules.
webapp#55 is leaning toward teams as a Nostr-shared identifier (either a
ttag convention or a NIP-51 follow set), so a user's "I'm on the animal-chores team" subscription is the same primitive whether they're seeing chores in tasks or checking the budget envelope in libra.These aren't incompatible, but they imply different sources of truth:
Budget.role_idcould optionally store a Nostr team address (30000:admin-pubkey:team:farmers) instead of a local role id, and the libra UI resolves it the same way tasks does.Worth resolving the umbrella's avenue A vs B before locking the schema here, so we don't end up with libra's
role_idmeaning something different from everything else's "team."(Filing this as a comment rather than a separate issue since the work itself stays here — this is just a heads-up that the team primitive may want to come from outside libra.)