Skip to content

feat(sdk): add out of the box controls - part 1 - #246

Open
namrataghadi-galileo wants to merge 4 commits into
mainfrom
feature/67101-out-of-box-controls
Open

feat(sdk): add out of the box controls - part 1#246
namrataghadi-galileo wants to merge 4 commits into
mainfrom
feature/67101-out-of-box-controls

Conversation

@namrataghadi-galileo

Copy link
Copy Markdown
Contributor

Summary

  • Added Phase 1 out-of-box controls bootstrap tooling so startup can safely seed controls later without duplicating rows or blocking pod startup.
  • Added evaluator gating, namespace-aware seeding, initial version creation, idempotency, duplicate-name race handling, and fail-open lifespan integration.

Scope

  • User-facing/API changes: None.
  • Internal changes: New agent_control_server.bootstrap module, startup seeding hook, and bootstrap tests.
  • Out of scope: Actual OOTB control definitions, Phase 2 regex/json/list templates, and Phase 3 Luna metadata seeding.

Risk and Rollout

  • Risk level: low
  • Rollback plan: Remove the lifespan call to seed_out_of_box_controls and/or revert the bootstrap module and related tests.

Testing

  • Added or updated automated tests
  • Ran make check (not run because uv dependency resolution hit private index 401s)
  • Manually verified behavior via targeted tests, server lint, and server mypy using the existing .venv

Checklist

  • Linked issue/spec (Phase 1 from OOTB controls technical spec)
  • Updated docs/examples for user-facing changes: N/A, no user-facing changes
  • Included any required follow-up tasks in .md format: Phase 2 follow-up not yet added as a separate .md file

@codecov

codecov Bot commented Jun 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.42424% with 10 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...nt_control_server/bootstrap/out_of_box_controls.py 91.96% 9 Missing ⚠️
server/src/agent_control_server/main.py 90.90% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

template: OutOfBoxControlTemplate,
) -> str:
control_service = ControlService(session)
if await control_service.active_control_name_exists(template.name, namespace_key=namespace_key):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Using an active, mutable name as the seed identity resurrects deleted controls and duplicates renamed ones on the next standalone startup. Could we persist an immutable seed/source ID plus an explicit opt-out tombstone, and cover delete/rename followed by reseeding?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Implemented. Out-of-box controls now persist an immutable, namespace-scoped source_id, and deleting a seeded control records an explicit opt-out tombstone. Reseeding resolves by source ID, so renamed controls are preserved and deleted controls are not resurrected. Added regression coverage for both rename → reseed and delete → reseed scenarios.

Comment thread server/src/agent_control_server/main.py Outdated
logger.info(f"Evaluator discovery complete. Available evaluators: {available}")

try:
seed_result = await seed_out_of_box_controls(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The try/except is fail-open only after this await returns. A database lock wait can hold startup before lifespan yields, especially because statement timeouts may be disabled. Please bound the whole bootstrap, or set a local lock timeout and retry later.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed. The full OOTB bootstrap await is now bounded by a configurable timeout (10 seconds by default). If it blocks, the operation is cancelled and startup continues fail-open with a warning. Added lifespan coverage using a seed coroutine that never returns.

@namrataghadi-galileo namrataghadi-galileo changed the title feat(sdk): add out of hte box controls feat(sdk): add out of the box controls - part 1 Jul 30, 2026
def __post_init__(self) -> None:
object.__setattr__(self, "source_id", _SLUG_NAME_ADAPTER.validate_python(self.source_id))
object.__setattr__(self, "name", _SLUG_NAME_ADAPTER.validate_python(self.name))
if not self.required_evaluators:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] Do not let explicit requirements replace condition dependencies

When required_evaluators is non-empty, this skips derivation from the control leaves, so a regex control with an extra Luna requirement can seed on a pod that has Luna but not regex. Always union explicit requirements with evaluator names derived from the condition, and add a mixed-requirement test.

"controls",
sa.Column("seed_opted_out_at", sa.DateTime(timezone=True), nullable=True),
)
op.create_index(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] Build the seed index without blocking writes

This emits a transactional CREATE UNIQUE INDEX, which holds a write-blocking table lock for the scan; the preceding clone-lineage migration already uses CREATE INDEX CONCURRENTLY for this rollout pattern. Use the same autocommit/concurrent approach for upgrade and downgrade.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] Make the concurrent migration retry-safe

Entering autocommit_block() commits both unguarded ADD COLUMN statements before the index build and revision stamp. If the concurrent build or stamp fails, rerunning stops on DuplicateColumn; a failed concurrent build can also leave an invalid index that IF NOT EXISTS skips by name. Split the column and index changes into retry-safe revisions and recreate any invalid existing index.

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