Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
0cde0b1
feat(control-plane): add VC-based authorization foundation
AbirAbbas Feb 4, 2026
0106624
feat(vc-authorization): complete VC-based authorization system implem…
AbirAbbas Feb 5, 2026
c0f1d57
fix(control-plane): fix pre-existing test bugs exposed by FTS5 build tag
AbirAbbas Feb 5, 2026
6119f8f
fix(control-plane): fix pre-existing test bugs exposed by FTS5 build tag
AbirAbbas Feb 5, 2026
9fe8858
fix(control-plane): fix SSE tests leaking goroutines via incorrect co…
AbirAbbas Feb 5, 2026
8a4c3f3
ts sdk and bug fix on did web
AbirAbbas Feb 5, 2026
f90a875
feat(examples): add permission test agents and enable VC authorizatio…
AbirAbbas Feb 5, 2026
20bda32
Fixes
AbirAbbas Feb 6, 2026
393e519
fix(sdk-python): update test fakes for DID credential wiring in _regi…
AbirAbbas Feb 6, 2026
39a1954
more improvements
AbirAbbas Feb 6, 2026
8e671fb
6th iteration of fixes
AbirAbbas Feb 6, 2026
b83f5be
end to end tested
AbirAbbas Feb 6, 2026
8396b29
feat(sdk): add Go & TS permission test agents, fix DID auth signing
AbirAbbas Feb 6, 2026
026e4e2
fix(sdk-ts): update header-forwarding test for pre-serialized JSON body
AbirAbbas Feb 6, 2026
54aa126
manual testing updates
AbirAbbas Feb 6, 2026
c5e5556
fix(vc-auth): fix re-approval deadlock, empty caller_agent_id, and er…
AbirAbbas Feb 7, 2026
cbbcd40
fix go missing func
AbirAbbas Feb 8, 2026
e030d81
address dx changes
AbirAbbas Feb 9, 2026
7095941
temp
AbirAbbas Feb 9, 2026
668ed79
more fixes
AbirAbbas Feb 10, 2026
0cac1c2
finalized
AbirAbbas Feb 10, 2026
5df611a
better error prop
AbirAbbas Feb 10, 2026
fa18933
fix: update TS DID auth tests to match nonce-based signing format
AbirAbbas Feb 10, 2026
6ffe576
fix: add rate limiting to DID auth middleware on execution endpoints
AbirAbbas Feb 10, 2026
5cdfdf8
fix: use express-rate-limit for DID auth middleware to satisfy CodeQL
AbirAbbas Feb 10, 2026
27455d7
fix: remove duplicate countWorkflowRuns method from rebase
AbirAbbas Feb 10, 2026
ccba62a
UI cleanup
AbirAbbas Feb 10, 2026
6a09ce0
pydantic formatting fix
AbirAbbas Feb 11, 2026
3d6a50b
connector changes
AbirAbbas Feb 12, 2026
9db17be
implemented multi agents with versioning
AbirAbbas Feb 13, 2026
4ac437f
feat(ui): polished authorization page with unified tabs and visual st…
santoshkumarradha Feb 13, 2026
70a5072
Merge branch 'feat/vc-authorization' into feat/connector
AbirAbbas Feb 13, 2026
9ae4e62
multi versioning connector setup
AbirAbbas Feb 13, 2026
d89eb23
add agent to agent direct checks
AbirAbbas Feb 17, 2026
234c441
Merge branch 'feat/vc-authorization' into feat/connector
AbirAbbas Feb 18, 2026
1a6c32a
bugfixes on connector
AbirAbbas Feb 20, 2026
8d25a95
QA fixes
AbirAbbas Feb 20, 2026
c248e89
package lock
AbirAbbas Feb 21, 2026
34f1c74
Merge main into feat/vc-authorization
AbirAbbas Feb 21, 2026
f9d30dd
Merge branch 'feat/vc-authorization' into feat/connector
AbirAbbas Feb 23, 2026
f9d9dcf
bug fixes on permissions & versioning flow
AbirAbbas Feb 23, 2026
380dcb2
Merge main into feat/connector
AbirAbbas Feb 25, 2026
4f7fe7a
fix: add missing DeleteAgentVersion stub and guard postgres migration…
AbirAbbas Feb 25, 2026
a75e963
add postgres testing to dev
AbirAbbas Feb 25, 2026
6dc9172
docs: add changelog and env vars for connector, versioning, and autho…
AbirAbbas Mar 2, 2026
a5c4781
merge: resolve CHANGELOG.md conflict with main
AbirAbbas Mar 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/control-plane.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ dist/
coverage.out
*.test
tmp/
examples/go_agent_nodes/permission_agent_*
examples/go_agent_nodes/go_agent_nodes

# Compiled binaries
control-plane/agentfield-server
control-plane/af
examples/**/go_agent_node*
!examples/**/*.go

# Python
__pycache__/
Expand Down
64 changes: 64 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,70 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)

<!-- changelog:entries -->

## [Unreleased] - feat/connector

### Added

- **Multi-Versioning**: Deploy multiple versions of the same agent with weighted traffic routing. Agents are now stored with composite primary key `(id, version)`, enabling canary deployments, A/B testing, and blue-green rollouts. Includes `group_id` for logical grouping, `traffic_weight` (0–10000) per version, weighted round-robin selection, and `X-Routed-Version` response header. New storage methods: `GetAgentVersion`, `ListAgentVersions`, `ListAgentGroups`, `ListAgentsByGroup`, `UpdateAgentTrafficWeight`, `DeleteAgentVersion`. (9db17be, 9ae4e62, 3d6a50b)

- **VC-Based Authorization System**: Complete Verifiable Credential authorization with W3C DID identity, Ed25519 request signing, tag-based access policies, and admin approval workflows. Agents get `did:web` identities with keypairs derived from master seed. Request signing uses 4 headers (`X-Caller-DID`, `X-DID-Signature`, `X-DID-Timestamp`, `X-DID-Nonce`). Includes DID auth middleware, permission check middleware with auto-request-on-deny, admin API for approve/reject/revoke, and comprehensive integration test suite (1754+ lines). (0cde0b1, 0106624)

- **Connector Subsystem**: External management API with token-based authentication and capability-based access control. Provides `/connector/*` REST endpoints for managing reasoners, versions, traffic weights, and agent groups. Supports scoped capabilities (`reasoners:read`, `versions:write`, `restart`, etc.) for CI/CD and orchestration platform integration. (3d6a50b, 9ae4e62)

- **Authorization Admin UI**: Unified tabbed authorization page with Access Rules tab (ALLOW/DENY policies with color-coded borders), Agent Tags tab (manage and approve agent tags), approval dialogs with policy impact preview, and revocation support. (4ac437f)

- **Agent-to-Agent Direct Verification**: SDK `LocalVerifier` modules that cache policies, revocation lists, registered DIDs, and admin public key from the control plane. Enables offline signature verification without round-tripping. Added `/api/v1/registered-dids` endpoint. Supports nonce-based signatures and `did:key` public key resolution. (d89eb23)

- **SDK DID Auth Modules**:
- Go: `client/did_auth.go` (authenticator), `did/did_client.go` (DID client), `did/did_manager.go` (key manager), `did/vc_generator.go` (VC generation), `agent/verification.go` (LocalVerifier)
- Python: `did_auth.py` (Ed25519 signing), `verification.py` (LocalVerifier with async refresh)
- TypeScript: Expanded `LocalVerifier.ts` (registered DID caching, nonce-aware verification)

- **SDK Version Propagation**: All three SDKs (Go, Python, TypeScript) now include `version` in heartbeat and shutdown payloads for multi-versioning support.

- **Multi-Version Examples**: New examples for all three SDKs demonstrating versioned agent registration (`examples/ts-node-examples/multi-version/`, `examples/go_agent_nodes/cmd/multi_version/`, `examples/python_agent_nodes/multi_version/`)

- **Permission Test Examples**: Caller + protected target examples for all three SDKs (`examples/python_agent_nodes/permission_agent_a/`, `examples/go_agent_nodes/cmd/permission_caller/`, etc.)

- **Rate Limiting**: Added `express-rate-limit` to DID auth middleware on execution endpoints for TypeScript SDK. (6ffe576, 5cdfdf8)

- **`ExecuteError` Type**: All three SDKs now surface execution errors with status code and `error_details` propagation. (c5e5556)

### Fixed

- **Agent health status flapping** (#169): Three independent health systems (HealthMonitor, StatusManager, PresenceManager) fought each other. Now requires 3 consecutive failures before marking inactive, reduced heartbeat DB cache from 8s to 2s. (e74ed99)

- **Memory websocket blocking startup** (#165): websockets v14+ renamed `additional_headers` to `extra_headers`, and blocking reconnect prevented uvicorn from starting. Added 5s timeout and backgrounded reconnect. (4a63bec)

- **Python SDK hardcoded version** (#166): Registration payload hardcoded version to "1.0.0" and omitted agent metadata. Now passes actual values. (35d2685)

- **Async execution polling missing auth headers** (#180): `_poll_single_execution` and `_batch_poll_executions` did not include auth headers, causing 401 errors. (26692de)

- **Re-approval deadlock**: Re-approval only triggered for empty status, not revoked/rejected. Also fixed empty `caller_agent_id` and error propagation (200 → 502 for agent-to-agent failures). (c5e5556)

- **Permissions/versioning flow**: Removed `DenyAnonymous` (broke backward compat), preserved approved tags during re-registration, cleaned stale empty-version DB rows. (f9d9dcf)

- **UI workflow delete 404** (#174): Cleanup route was not registered. (ee47f56)

- **Workflow cleanup orphaned summaries** (#177): Deletion left behind orphaned run summaries. (ab2ce92)

- **Missing DeleteAgentVersion stub**: CI failure from missing interface method and postgres migration on fresh DBs. (4f7fe7a)

- **Reasoner name mismatch**: Python SDK used `func_name` instead of `reasoner_id` for endpoint path. (f427b9b)

- **Reasoner path normalization**: Added execution status guards for `waiting` state, approval expiration, execution event streaming. (f7a4a4d)

- **Duplicate `countWorkflowRuns`**: Removed duplicate method from rebase. (27455d7)

- **Pydantic formatting**: Fixed AI response formatting in Python SDK. (6a09ce0)

### Changed

- Database schema uses composite primary key `(id, version)` for agent nodes (migration 015)
- `AgentNode` type includes new fields: `GroupID`, `TrafficWeight`
- `StorageProvider` interface expanded with version-aware methods
- Discovery response includes `GroupID` in `AgentCapability`

## [0.1.42] - 2026-02-27


Expand Down
7 changes: 7 additions & 0 deletions control-plane/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ AGENTFIELD_STORAGE_MODE=local
# AGENTFIELD_STORAGE_CLOUD_CONNECTION_POOL=true
# AGENTFIELD_STORAGE_CLOUD_REPLICATION_MODE=async

# VC Authorization
# Admin token for admin API endpoints (tag approval, policy management)
# AGENTFIELD_AUTHORIZATION_ADMIN_TOKEN=admin-secret
# Internal token sent to agents during request forwarding.
# Agents with RequireOriginAuth=true validate this to ensure only the control plane can invoke them.
# AGENTFIELD_AUTHORIZATION_INTERNAL_TOKEN=internal-secret-token

# Development/Debug
# GIN_MODE=debug
# LOG_LEVEL=info
Binary file removed control-plane/agentfield-server
Binary file not shown.
71 changes: 71 additions & 0 deletions control-plane/config/agentfield.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 31 additions & 3 deletions control-plane/dev.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
# Start control plane with hot-reload using Air
#
# Usage:
# ./dev.sh # Start with hot-reload (SQLite mode)
# ./dev.sh postgres # Start with PostgreSQL (set AGENTFIELD_DATABASE_URL first)
# ./dev.sh # SQLite mode with hot-reload
# ./dev.sh postgres # PostgreSQL mode (starts postgres via docker-compose)
# ./dev.sh pg-stop # Stop the dev postgres container
# ./dev.sh pg-reset # Stop postgres and wipe its data volume
# ./dev.sh pg-test # Run Go postgres tests against dev database
#
# Prerequisites:
# go install github.com/air-verse/air@v1.61.7
Expand All @@ -17,12 +20,37 @@ if ! command -v air &> /dev/null; then
go install github.com/air-verse/air@v1.61.7
fi

pg_up() {
echo "Starting dev postgres..."
docker compose -f docker-compose.dev.yml up -d --wait
echo "Postgres ready at localhost:5432 (agentfield_dev)"
}

pg_down() {
docker compose -f docker-compose.dev.yml down "$@"
}

case "${1:-}" in
postgres|pg)
pg_up
echo "Starting control plane with PostgreSQL (hot-reload)..."
export AGENTFIELD_STORAGE_MODE=postgresql
export AGENTFIELD_STORAGE_MODE=postgres
air -c .air.toml
;;
pg-stop)
echo "Stopping dev postgres..."
pg_down
;;
pg-reset)
echo "Stopping dev postgres and wiping data..."
pg_down -v
;;
pg-test)
pg_up
echo "Running postgres storage tests..."
POSTGRES_TEST_URL="postgres://agentfield:agentfield@localhost:5433/agentfield_dev?sslmode=disable" \
go test ./internal/storage/ -run TestPostgres -v -count=1
;;
*)
echo "Starting control plane with SQLite (hot-reload)..."
export AGENTFIELD_STORAGE_MODE=local
Expand Down
20 changes: 20 additions & 0 deletions control-plane/docker-compose.dev.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion control-plane/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ require (
github.com/spf13/cobra v1.8.1
github.com/spf13/viper v1.20.1
github.com/stretchr/testify v1.10.0
golang.org/x/crypto v0.37.0
golang.org/x/term v0.32.0
google.golang.org/grpc v1.67.3
google.golang.org/protobuf v1.36.6
Expand Down Expand Up @@ -94,7 +95,6 @@ require (
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/arch v0.15.0 // indirect
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/sync v0.13.0 // indirect
golang.org/x/sys v0.36.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions control-plane/internal/application/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/Agent-Field/agentfield/control-plane/internal/cli/framework"
"github.com/Agent-Field/agentfield/control-plane/internal/config"
"github.com/Agent-Field/agentfield/control-plane/internal/encryption"
"github.com/Agent-Field/agentfield/control-plane/internal/core/services"
"github.com/Agent-Field/agentfield/control-plane/internal/infrastructure/process"
"github.com/Agent-Field/agentfield/control-plane/internal/infrastructure/storage"
Expand Down Expand Up @@ -55,6 +56,9 @@ func CreateServiceContainer(cfg *config.Config, agentfieldHome string) *framewor
// Create DID registry with database storage (required)
if storageProvider != nil {
didRegistry = didServices.NewDIDRegistryWithStorage(storageProvider)
if passphrase := cfg.Features.DID.Keystore.EncryptionPassphrase; passphrase != "" {
didRegistry.SetEncryptionService(encryption.NewEncryptionService(passphrase))
}
} else {
// DID registry requires database storage, skip if not available
didRegistry = nil
Expand Down
Loading
Loading