Files
2026-09-30 20:30:56 +03:00

6.1 KiB

Context

The scanner already persists exact and ambiguous routing hints for overlapping Qwen, DeepSeek, and Kimi sk-... findings. Provider workers, however, claim service-specific candidates and reject any hint that is not exactly their own service, so an ambiguous candidate can be repeatedly left unconsumed and quarantined. A ZAI detector already exists, but candidate extraction and a ZAI keychecker do not.

The authoritative runtime uses PostgreSQL candidate leases and transactional result completion. Compatibility JSONL and status files are projections and must not control routing.

Goals / Non-Goals

Goals:

  • Resolve one ambiguous credential sequentially across only its compatible providers.
  • Stop at the first response that proves the credential belongs to a provider.
  • Persist the successful result under the provider that recognized the credential.
  • Add direct ZAI extraction plus model-list authentication and a minimal generation/billing probe through the global and China APIs.
  • Preserve fenced candidate completion, capacity accounting, and restart safety.

Non-Goals:

  • Redesign credential storage or secret-retention policy.
  • Probe every supported provider for every unknown string.
  • Run provider probes for one ambiguous credential in parallel.
  • Automatically retry credentials whose current status is configured as terminal.

Decisions

Use one virtual resolver candidate

Findings with a single strong provider hint continue to produce that provider's existing candidate. Findings with an ambiguous generic-key hint produce one provider_resolver candidate, deduplicated by credential within a staged scan bundle. The resolver owns one normal PostgreSQL lease and invokes compatible provider adapters in order, avoiding sibling candidates and cross-worker races.

This is preferred to enqueueing one active candidate per provider because the latter requires new coordination state, can spend quota concurrently, and complicates exact queue-capacity release.

Keep route selection bounded and deterministic

Persisted provider evidence limits the compatible set. The default fallback order is deepseek,zai,qwen,kimi; a provider identified by the originating detector is moved to the front when it belongs to the compatible set. The order is configurable, deduplicated, and never expanded beyond the supported generic-key provider set.

Provider-specific formats such as sk-sp-..., zai-..., and ZAI's dotted key form remain direct routes when the finding evidence is unambiguous.

Normalize adapter outcomes

Each adapter returns its existing detailed status plus a resolver outcome:

  • match: a successful authenticated response or provider-specific account/quota response proves ownership.
  • no_match: the provider definitively rejects the credential as invalid.
  • retry: network, server, generic rate-limit, malformed, or otherwise inconclusive responses.

The resolver continues past no_match and may continue past retry to find a later positive match. If no provider matches, any retryable attempt keeps the result unresolved; only an all-no_match route is exhausted.

Reassign a matched candidate during fenced completion

When a resolver result names a matched provider, complete_keycheck_candidate obtains or creates the canonical credential row for that provider, reassigns the leased candidate to it, and writes the result/current state under the matched service in the same transaction. The existing provider-key fingerprint, event fence, projection reservation, and capacity accounting remain unchanged. No schema migration is required.

Legacy Qwen, DeepSeek, or Kimi candidates carrying an ambiguous persisted hint delegate to the same resolver so explicitly retried old candidates do not return to the unconsumed quarantine loop.

Authenticate ZAI through model listing and prove usability

The ZAI adapter first calls authenticated GET /models on https://api.z.ai/api/paas/v4 and https://open.bigmodel.cn/api/paas/v4, then sends a one-token POST /chat/completions probe to the fixed glm-5.2 target. A key is VALID only when that probe succeeds. Model-list authentication still proves provider ownership when the probe reports quota, balance, permission, model access, or transient failures, but those outcomes are persisted outside the alive set. HTTP, documented ZAI business codes, and bounded message markers distinguish invalid authentication, recognized quota/balance restrictions, rate limits, permission restrictions, and transient failures.

Risks / Trade-offs

  • [A transient response from an early provider could hide a later match if probing stopped] -> Continue through the bounded compatible set while retaining the transient outcome if nobody matches.
  • [The same text could theoretically be valid at more than one compatible gateway] -> Deterministic first-match ordering is explicit and recorded with all preceding attempts.
  • [All-provider fallback increases requests for weak-context findings] -> Restrict it to detector-qualified generic-key formats and one sequential resolver candidate.
  • [Existing quarantined candidates are not silently mutated] -> Make legacy candidates resolver-aware; operators can explicitly retry affected quarantine records through the existing review path.
  • [Provider API behavior may change] -> Keep ZAI endpoints configurable and cover response classification with mocked regression tests.
  • [The usability probe consumes provider resources] -> Request one output token from one deterministic chat model and stop after the first conclusive authenticated endpoint.

Migration Plan

  1. Deploy extraction, resolver, ZAI adapter, runner registration, and transactional service reassignment together.
  2. Restart the supervised runtime so the lifecycle code manifest and service registry are rebuilt atomically.
  3. Verify new ambiguous candidates are owned by provider_resolver and matched rows are projected under the actual provider.
  4. Explicitly retry only relevant legacy provider-routing quarantine records after the new behavior is active.

Rollback requires stopping the runtime and restoring the previous code/config manifest. No database schema rollback is needed.

Open Questions

None.