-
Notifications
You must be signed in to change notification settings - Fork 1.5k
feat: add overseer control plane foundations #1386
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
adamcottis-dotcom
wants to merge
10
commits into
CoplayDev:beta
Choose a base branch
from
adamcottis-dotcom:adamcottis-dotcom-build-overseer-control-plane
base: beta
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
56f2afe
feat: add overseer control plane and team definitions
Copilot ab471b7
fix: address overseer review feedback
Copilot 23b4406
fix: make ledger connections safe for API threads
Copilot 901c5a0
fix: address overseer review feedback
Copilot 069e660
Migrate legacy ledger amounts safely
Copilot 72c693b
docs: add overseer docstrings
Copilot e9d320b
test: cover negative infinite ledger amounts
Copilot 31ce92d
test: cover mixed-offset ledger ordering
Copilot 17b04c9
test: cover pending monetary ledger totals
Copilot a2cb333
test: cover valid simulation lifecycle
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| """Provider-neutral control-plane primitives for supervising commercial AI agents.""" | ||
|
|
||
| from .ledger import EventLedger, LedgerEvent, TeamSummary | ||
| from .simulation import run_support_ticket_simulation | ||
| from .teams import TEAM_SPECS | ||
|
|
||
|
|
||
| def create_overseer_app(*args, **kwargs): | ||
| """Lazily create the optional FastAPI dashboard adapter.""" | ||
| from .api import create_overseer_app as _create_overseer_app | ||
|
|
||
| return _create_overseer_app(*args, **kwargs) | ||
|
|
||
|
|
||
| __all__ = [ | ||
| "EventLedger", | ||
| "LedgerEvent", | ||
| "TeamSummary", | ||
| "create_overseer_app", | ||
| "run_support_ticket_simulation", | ||
| "TEAM_SPECS", | ||
| ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| """Read-only HTTP view of the overseer ledger.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from dataclasses import asdict | ||
|
|
||
| from hmac import compare_digest | ||
| from decimal import Decimal | ||
| from typing import Collection | ||
|
|
||
| from fastapi import FastAPI, Header, HTTPException, Query | ||
|
|
||
| from .ledger import EventLedger | ||
|
|
||
|
|
||
| def create_overseer_app( | ||
| ledger: EventLedger, | ||
| *, | ||
| api_key: str, | ||
| authorized_team_ids: Collection[str] | None = None, | ||
| ) -> FastAPI: | ||
| """Create an authenticated, read-only API backed by an existing ledger.""" | ||
| if not api_key: | ||
| raise ValueError("api_key is required") | ||
| app = FastAPI(title="Overseer Control Plane", version="1.0") | ||
| scoped_team_ids = ( | ||
| frozenset(authorized_team_ids) if authorized_team_ids is not None else None | ||
| ) | ||
|
|
||
| def serialize(value: object) -> object: | ||
| """Convert ledger values into JSON-compatible response values.""" | ||
| if isinstance(value, Decimal): | ||
| return float(value) | ||
| if isinstance(value, dict): | ||
| return {key: serialize(item) for key, item in value.items()} | ||
| if isinstance(value, list): | ||
| return [serialize(item) for item in value] | ||
| return value | ||
|
|
||
| def authorize(requested_team_id: str | None, presented_key: str | None) -> None: | ||
| """Validate the API key and optional team scope for an endpoint request.""" | ||
| if presented_key is None or not compare_digest(presented_key, api_key): | ||
| raise HTTPException(status_code=401, detail="authentication required") | ||
| if scoped_team_ids is not None: | ||
| if requested_team_id is None or requested_team_id not in scoped_team_ids: | ||
| raise HTTPException(status_code=403, detail="team access denied") | ||
|
|
||
| @app.get("/events") | ||
| def events( | ||
|
adamcottis-dotcom marked this conversation as resolved.
|
||
| team_id: str | None = Query(default=None), | ||
| limit: int = Query(default=100, ge=1, le=500), | ||
| x_overseer_api_key: str | None = Header(default=None), | ||
| ) -> list[dict]: | ||
| """Return recent ledger events visible to the authenticated caller.""" | ||
| authorize(team_id, x_overseer_api_key) | ||
| return [serialize(asdict(event)) for event in ledger.list_events(team_id, limit)] | ||
|
|
||
| @app.get("/summaries") | ||
| def summaries( | ||
| team_id: str | None = Query(default=None), | ||
| x_overseer_api_key: str | None = Header(default=None), | ||
| ) -> list[dict]: | ||
| """Return financial summaries visible to the authenticated caller.""" | ||
| authorize(team_id, x_overseer_api_key) | ||
| return [serialize(asdict(summary)) for summary in ledger.summarize(team_id)] | ||
|
|
||
| @app.get("/approvals") | ||
| def pending_approvals( | ||
| team_id: str | None = Query(default=None), | ||
| limit: int = Query(default=100, ge=1, le=500), | ||
| x_overseer_api_key: str | None = Header(default=None), | ||
| ) -> list[dict]: | ||
| """Return pending approval events visible to the authenticated caller.""" | ||
| authorize(team_id, x_overseer_api_key) | ||
| return [ | ||
| serialize(asdict(event)) | ||
| for event in ledger.list_pending_approvals(team_id, limit) | ||
| ] | ||
|
|
||
| return app | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.