13 auth token - #20
Merged
Merged
Conversation
…r, per-IP rate limiter (bounded + ctx-bound janitor), startup guard, agentfm_auth_attempts_total metric. 22 unit tests. Not wired into routes yet (PR 2).
- StartAPIServer(bind, port) — refuses non-loopback bind without API keys - AGENTFM_ALLOW_UNAUTH_PUBLIC=1 escape hatch - help.go: -api-bind row, two new examples, env-vars table - 1 new integration test (refusal); CLI smoke verified Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- api_key constructor arg (sync + async); AGENTFM_API_KEY env fallback - AuthenticationError; maps unauthorized + invalid_api_key codes - Authorization: Bearer header on every request when set - with_options inherits api_key - 15 new unit tests; 164/164 green Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Constructor + with_options use _Unset sentinel: omit -> env fallback, None -> explicit no-auth, str -> use literal - 5 new with_options tests; CHANGELOG entry under Unreleased - 169/169 SDK tests green; ruff + mypy clean Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Root README: ## Authentication with token gen, startup-refusal, per-IP rate limiting, SDK + OpenAI examples - Refreshed OpenAI drop-in snippet to show real api_key usage - Caveats: auth bullet flipped to "implemented" - Security Model table: HTTP gateway auth row added - CLI Reference: -api-bind row added - Python SDK README: brief Authentication subsection Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- C2: handleModels releases RLock before json.Encode to a slow client
(avoids starving telemetry pulse on RWMutex writer-preferring semantics)
- C3: discoverPeers checks ctx.Err() per-iteration of the FindPeers
channel range, bounds shutdown to a single dial deadline
- C4: artifact taskID requires leading alphanum + [a-zA-Z0-9_.-]{0,127};
rejects zero-length idLen entirely; new regression test
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- I5: replace time.Now().UnixNano() task IDs with newCompletionID
("task_<24hex>") at api_async.go, api_handlers.go, execute.go,
worker/sandbox.go (sessionID — concurrent containers no longer race
for /tmp/output bind-mount)
- I7: bufio.Scanner cap raised from 1 MiB to 8 MiB via maxLineBytes
const; LLM agents emitting structured-output JSON without newlines
routinely exceed 1 MiB
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- I18: runWorkerMode wraps with signal.NotifyContext so metrics.Serve and worker.Start observe SIGINT/SIGTERM (was bound to bare ctx that never cancelled — metrics server was reaped only by process exit) - I19: cmd/relay/main.go replaces bespoke signal.Notify channel with signal.NotifyContext; eliminates dual shutdown-handler smell Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…y tests - Py I3: stacklevel=4 -> 3 via ROUTING_WARNING_STACKLEVEL constant; warning now attributes to the user's create() call line - Py I4: extract raise_translated_stream_error() helper in _transport; 6 streaming sites (3 sync + 3 async) collapse to one-line dispatch; httpx.UnsupportedProtocol now mapped to InvalidRequestError on streaming endpoints (was wrongly mapped to WorkerStreamError) - Sync<->async parity: AsyncAgentFMClient.tasks.scatter_by_model gains pick=Callable kwarg matching the sync side - Tests: tests/unit/test_parity.py introspects sync vs async namespaces and asserts matching method names + matching kwargs (would have caught the historical pick= drift); test_sync_client.py adds attribution test for ROUTING_WARNING_STACKLEVEL - 174/174 SDK tests green; ruff + mypy clean Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Worker now prints a WARN-level startup banner about the host-network threat model: agent containers can reach 127.0.0.1 services (Ollama, admin endpoints, cloud metadata). Defaulting to --network none would break the entire LLM-on-loopback workflow ecosystem; doc warning is the right stop-gap until a phased rollout (issue follow-up tracked in plans/agentfm-full-audit-2026-04-27.md PR-A5 section). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- I15: Boss.asyncSlots channel caps in-flight /api/execute/async at MaxInflightAsyncTasks (256); non-blocking acquire returns 503 with Retry-After + OpenAI envelope (code=async_capacity_exhausted) when saturated; goroutine releases the slot on exit - I17: pruneDisconnectedWorkers extracted into a 30s ticker inside listenTelemetry; handleGetWorkers becomes a pure RLock + read; no side effects on a GET request - I6: replace fixed time.After(2s) artifact wait with waitForArtifact() poll (100ms cadence, 10s deadline); responsive when the file appears earlier, bounded when it doesn't Tests: pruneDisconnectedWorkers_EvictsDeadPeer, handleGetWorkers_PureRead, asyncExecuteHandler_CapacityExhausted; 7/7 packages green under -race. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ay filter) - I3: loadOrGenerateIdentity uses slog.Warn (not fmt.Printf) for corrupt-key + persist-failure paths so JSON-log aggregators see them - I13: LoadSwarmKey os.Stat checks file mode and warns if it is group/world readable; spec is 0600 - I14: isDirEmpty conservative-default behavior documented inline - I20: writeSSEDone surfaces write errors as a slog.Debug crumb instead of silent _, _ = - I10: dialWorkerStream skips the circuit-relay address when the relay is not currently connected; saves StreamDialTimeout per task against a dead lighthouse - MeshNode now caches RelayPeerID at Setup so the connectedness check doesn't have to re-parse the multiaddr per dial Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…_, sentinel test) - Py I1: WebhookReceiver._parse_content_length enforces max_body_bytes internally; cap is now in one place so a future chunked-transfer refactor can't accidentally bypass the size guard - Py I5: AgentFMClient + AsyncAgentFMClient grow defensive __del__ so a client built via with_options(...) outside a `with` block doesn't leak the underlying httpx.Client until interpreter exit - Py I13: SentinelFilter regression test for partial-sentinel input (truncated transport that opens "[AGENTFM:" but never closes it) 175/175 SDK tests green; ruff + mypy clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- WorkerProfile: drop redundant alias="name" (field already named "name") - isLoopbackBind: drop misleading "[::1]" literal switch case (net.ParseIP rejects bracketed form anyway; loopback IPv6 is matched via ParseIP+ IsLoopback below) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…uidance) - Security Model table: container --network host caveat made explicit (loopback + cloud-metadata + Ollama exposure) - Authentication section: reverse-proxy rate-limiter caveat documented; async submission cap (MaxInflightAsyncTasks=256) called out; operator-monitoring note (alert on agentfm_auth_attempts_total metrics, not log scrapes) Audit doc at ~/.claude/plans/agentfm-full-audit-2026-04-27.md updated with execution log + deferred-items rationale + follow-up issues list. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
No description provided.