Repository navigation
test(privatefile, workspaceidentity): 补齐凭据原子写与路径排除边界的单元测试 - #517
Open
Qiyuanqiii wants to merge 2 commits into
Open
Qiyuanqiii wants to merge 2 commits into
Qiyuanqiii wants to merge 2 commits into
Conversation
internal/privatefile 与 internal/workspaceidentity 此前没有任何测试文件,而两者都处在安全边界上:前者负责 OAuth 凭据的原子写与跨进程锁,后者决定 Agent 不允许读写哪些路径。 internal/privatefile/file.go 已预留可注入的 rename 钩子用于测试提交被中断,但仓库中从未有测试使用它。 本 PR 不改动任何生产代码,仅新增测试: - internal/privatefile 0% -> 83.3% - internal/workspaceidentity 0% -> 95.4% 新增 44 个用例覆盖中断提交后原文件不变且临时文件已清理、路径逃逸与绝对路径拒绝、非法 glob 与控制字符、并发持锁互斥等拒绝路径。
7 of 8 tasks
Qiyuanqiii
pushed a commit
that referenced
this pull request
Oct 30, 2026
internal/approval 是审批账本的核心安全原语,但 bounded_grant.go 与 SessionGrant/CreateGrantRequest/RevokeGrantRequest 的校验矩阵此前没有 单元测试(包覆盖率 24.9%)。本 PR 仅新增测试,无生产代码改动: - boundedGrantPermission 权限白名单(command_runtime/command_process × ask/auto/full,及 workspace_access 历史路径) - MatchesBoundedGrantScope 全字段绑定校验(逐字段漂移拒绝) - CheckBoundedConsumption 消费核验:作用域漂移、显式撤销否决、过期、 ordinal 超用、以及"额度耗尽型撤销"的合法终局用例 - SessionGrant.Validate 有界/遗留(legacy)一致性、TTL≤15min、 MaxUses≤8、撤销元数据一致性等边界 - GrantConsumption/Record/DecisionRequest 校验与指纹辅助函数绑定 包覆盖率 24.9% → 87.6%。与 #517(privatefile/workspaceidentity)互补, 不触碰其文件。
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.
Description
internal/privatefileandinternal/workspaceidentityare two packages without a single test file, and both sit on a security boundary:internal/workspaceidentityprovidesPathPolicy, which decides which paths an Agent may not read or write, andFingerprint, which binds a workspace root to a platform file identity (dev/ino, or volume serial number plus file index).internal/privatefileperforms the atomic write and the cross-process lock behind the OAuth credential files, and is imported directly byinternal/chatgptauthandinternal/mcpoauth.internal/privatefile/file.goalready reserves an injection point for tests:No test in the repository used it, so the interrupted-commit failure path was never verified.
This PR adds tests only. No production code changes, no runtime behavior changes.
Test design
Follows the existing repository conventions. Internal test packages (
package privatefile/package workspaceidentity), stable error-code assertions (apperror.CodeOf(err) != apperror.CodeInvalidArgument, matchinginternal/application/agent_code_project_config_test.go), no new dependencies, no new test framework, and no contact withinternal/llmor any API contract.Covers the refusal paths, not the happy path. The value of a security boundary lives in its rejection branches.
PathPolicycovers absolute paths,..escapes, unnormalized paths, control characters, invalid UTF-8, malformed globs, and an invalid policy itself;privatefilecovers an injected interrupted commit (the original file content stays unchanged and the temporary file is cleaned up), a missing parent directory, an already-cancelled context, a context that times out while waiting for the lock, and mutual exclusion between concurrent holders.Locks the current contract instead of making a semantic decision for maintainers.
MatchPath("a/**", "a")currently returns true, that is,**also matches zero path segments. The existing test (agent_code_project_config_test.gousesExcludePaths: ["secrets/**"]) passes under both semantics, so the intent cannot be inferred. This PR asserts the current implementation behavior and states the reason in a code comment:**covering zero segments keeps the decision forCheck("a")consistent withCheck("a/b/c"), avoiding a split where the directory is visible but its contents are hidden. If maintainers think at least one segment should be required, that is a separate behavior change and belongs in its own issue, not in a test PR.Platform portability. The
0600permission assertion is skipped on Windows, whereChmodonly affects the read-only bit. The symlink case skips itself witht.Skipfwhere symlinks cannot be created, so it never passes silently. The process-lock case relies on mutual exclusion between different handles, which Linuxflockand WindowsLockFileExboth provide.21 test functions were added, including three table-driven groups that cover 37 further cases.
Type of Change
This is a test-only addition: no production file changes, and the classified check is
backendonly.Surface governance
N/A — no Surface change. No registry entry, generated inventory, or documentation contract is touched, because the change only adds test files and alters no public contract.
Validation
Current revision:
b0a3eef5, synchronized withmainthroughb58f8981.gofmt -l internal/privatefile internal/workspaceidentityb0a3eef5go vet ./internal/privatefile/... ./internal/workspaceidentity/...b0a3eef5go test -count=1 ./internal/privatefile/... ./internal/workspaceidentity/...b0a3eef5go test -race -count=1 ./internal/privatefile/... ./internal/workspaceidentity/...b0a3eef5./internal/codeintel/... ./internal/credential/...b0a3eef5go build ./...b0a3eef5go test -count=1 ./...(full repository)internal/app, because the heavyinternal/applicationandinternal/storepackages exceed the local session budget on this Windows host. The only failure observed,internal/appTestRunCommandExecuteIsConfirmedAuditedAndExactlyOnce(controlled command execution platform is unavailable: approved executable is unavailable), reproduces identically on the untouched baseb58f8981in a separate worktree, so it is a limitation of this host and not a regression from this PR.b0a3eef5b0a3eef5scripts/ci/classify_changes.py, baseb58f8981Selected checks: backend;full,store,web,journeys,lsp,rust,native,ui,race,audit, andpackagingare all falseb0a3eef5TestFingerprintRefusesFilesSymlinksAndMissingRootsnow runsregular file,missing root, andsymlinked rootas separate subtests, so a host without symlink support skips only the symlink caseb0a3eef5Select affected checksandGo checksgo vetandgo testfor both changed packages, plusinternal/releasegateandinternal/producte2e; every other gate was skipped by classificationb0a3eef5Local validation used Windows amd64 with Go 1.26.10, the version pinned by
go.modand selected automatically throughGOTOOLCHAIN=auto.Limitations
lock_unix.goandidentity_unix.gopaths were not exercised on a real macOS machine.TestFingerprintRefusesFilesSymlinksAndMissingRootsskipped locally because symlink creation is not available for this account on Windows; the Linux CI run exercised it instead.internal/llm, the OpenAPI contract, and every frontend file are untouched, sonpm run check:apiand the frontend suites were not run.Checklist
go fmt,go vet)Go checksgate pass; the singleinternal/appfailure seen during the full local run also fails on the untouched baseMiniMax-AI-Devaccount, so the "no AI attribution in commits" clause does not hold here. The tool and model are disclosed below, the contributor has reviewed the generated tests, and the contributor will answer maintainer questions and review comments.AI Assistance
The tests, the validation runs, and this description were prepared with MiniMax Code using the MiniMax M3.1 Flash model. The single commit is authored by the
MiniMax-AI-DevGitHub account. The contributor has reviewed the generated tests and remains responsible for answering maintainer questions and review comments.Related Issues
None.