Review on #1446 flagged that the publication gate parsed only the first
__DATA_CONST flags word of an otool -l capture, so a universal library
with a healthy first slice and a broken later slice would still ship.
Replace the inline one-shot awk with scripts/release/extract-data-const-
flags.awk, a state machine that emits one flags word per __DATA_CONST
segment in every slice (segname is only honored directly after cmdsize,
so section entries can never contribute), and fail closed if any entry
lacks SG_READ_ONLY.
Add a regression test driven by real otool captures: broken/healthy
v1.0.62 thin binaries, the vendored universal runtime dylib, and a
universal sample whose last slice is broken — the exact case the old
parser wrongly passed. Also remove MACOSX_DEPLOYMENT_TARGET from the
--exec ambient pass-through so the container always receives the single
unconditional 11.0 pin from compiler_env.
The v1.0.62 darwin/amd64 asset was rejected by dyld before main() with
'__DATA_CONST segment missing SG_READ_ONLY flag' (#1441). The osxcross
x86_64 wrapper in the pinned cross image defaults the deployment target
to macOS 10.13, where ld64-711 emits __DATA_CONST without SG_READ_ONLY;
the arm64 toolchain floor is 11.0 and is unaffected. CGO=0 builds used
Go's internal linker and were also unaffected.
Pin MACOSX_DEPLOYMENT_TARGET=11.0 for the CGO release builds, matching
the arm64 floor and the vendored SafeChat library, and add a release
gate that statically checks SG_READ_ONLY on the binary and its runtime
library and launches every Darwin asset the macOS runner can execute
(amd64 via Rosetta) before publication.
Verified against the pinned cross image: the real dws darwin/amd64
binary builds with __DATA_CONST flags 0x10 (was 0x0), CGO_ENABLED=1 and
the SafeChat backend linked.
* feat(dev): add DEAP agent commands
* feat(dev): add DEAP profile flags
* feat(deap-agent): 观测命令对齐 HSF 接口收敛
- 删 run-executions、resolve-run-id 两个命令(HSF 接口已移除对应方法)
- run-status 改双定位:--run-id 或 --source-id+--source-type 二选一,全场域通用;
移除旧的 assistantId+taskId 单聊口径
- 新增 send-message:以数字员工身份发消息返回 runId,写操作需 --yes 确认
- source-type 加白名单 enum(im_message/trigger_rule/scenario_instance)
- 同步契约测试与叶子清单
* refactor(deap-agent): source-type 白名单收敛为 im_message + trigger_rule
chat-2 删除 scenario_instance 来源类型后同步;并注明 im_message 的 sourceId 是
钉钉开放态 openMessageId,单聊/群@/群感知三条链路含义一致。
* fix(deap-agent): 按规范解析内建 MCP 端点
* fix: align deap agent cli with mcp tools
* refactor(deap-agent): 删除 send-message;run-status/trace 只按来源定位
- 删除 send-message 命令(HSF 侧 sendMessage 已移除)
- run-status / trace 去掉 --run-id 与 --trace-id,统一 --source-id + --source-type
且与 --assistant-id 一并必填:调用方拿不到 runId,留个填不了的 flag 只诱导瞎传
- 保留辰驷 c158ea17 对生命周期命令的 MCP 文案对齐
* refactor(deap): 提到顶级 dws deap 前缀,分管理态/观测态两子组
DEAP 是独立平台,与开放平台应用(agentId/clientId/机器人配置)无包含关系,
此前挂在 dws dev deap-agent 下会让两个产品的路由与文案互相干扰。
命令树:
- dws deap manage create/detail/list/save-draft/publish/delete(含不可逆写)
- dws deap observe run-status/trace(全部只读)
契约:ProductID dev→deap,canonicalPath 与 CLIPath 全量更新;MCP tool 名不变,
MCP 侧配置无需调整。
Skill 文档:新增 references/deap/(index + manage + observe),并在 misc 路由表、
说明与 frontmatter 注册。observe.md 写清 openTaskId→openMessageId 两跳取法——
dws chat message send 只返回 openTaskId,直接拿它查必然 NOT_FOUND,而报错
看不出是 ID 类型错了。
* refactor(deap): dev.go / devapp_test.go 回退至主干,不在其领域留痕
dev 是开放平台应用的命令树,属另一领域。DEAP 迁到顶级 dws deap 后,
dev 侧无需任何改动——之前加的挂载已删,剩下的注释与文案提示也一并回退,
两个文件现与 origin/main 逐字一致。
DEAP 不再挂 dev 的事实由 deap_agent_test.go 的 TestDeapIsNotMountedUnderDev
单独钉住(断言写在本领域测试文件里,不侵入 dev 的测试)。
* docs(deap): 去掉与 dev 的对比性提示
那些"两者是不同产品/别搞混/曾挂在 dev 下"的措辞源于早先把 DEAP 挂在 dev 下的
误解。dev 与 DEAP 本无关联,写对比反而凭空建立联想并暗示一段已不存在的历史。
清理:deap-index.md 的混淆警示、misc SKILL.md 的路由提示、deapHandler 与
deapProductID 的注释、TestDeapIsNotMountedUnderDev(该测试同时耦合 devHandler)。
保留 AvoidWhen 里的产品边界声明:create 在两侧同名,属真实可能的误选,
与"别搞混"的元叙述不同。
* feat(deap): select detail configuration type
* ci(actions): 简化构建并发布 Release
* feat: add Skill and MCP commands to deap agent
* fix(deap): compose Skill upload and creation
* fix(deap): route MCP query to published tool
* fix(deap): route skill query to registered tool
* feat(deap): support combined response modes
* feat(deap): use scoped credential for skill upload
* fix(deap): call published skill upload credential tool
* fix(deap): follow renamed upload credential tool
* docs(deap): explain temporary dws token workflow
* docs(deap): remove deprecated dws token workflow
* feat(dingtalk-tag): rename deap command and add auth token
* docs(dingtalk-tag): clarify dws auth credential response
* refactor(dingtalk-tag): group capabilities and unify agent IDs
* feat(dingtalk-tag): support main program type
* docs(dingtalk-tag): document local agent program type
* feat(skill): align dingtalk-tag guidance
* feat(dingtalk-tag): connect digital employees to local DSH
* fix(dingtalk-tag): constrain main program types
* feat(dingtalk-tag): filter employee list by program type
* fix(dingtalk-tag): resolve managed token identity
* fix(dingtalk-tag): bind managed identities to published profile
* fix(dingtalk-tag): resolve async reply receipts
* docs(dingtalk-tag): clarify default program type guidance
* feat(dingtalk-tag): add profile-only connect mode [skip ci]
* fix(dingtalk-tag): resolve operator in employee token scope
* feat(dingtalk-tag): add isolated local Agent adapters
* fix(dingtalk-tag): close registration races and verify worker lifecycle
* fix(dingtalk-tag): validate saved employee self identity
* feat(dingtalk-tag): unify adapter lifecycle and DSH release control
* fix(dingtalk-tag): fence lost hosts and recover DSH registration
* feat(dingtalk-tag): rename managed login command
* feat(dingtalk-tag): complete managed employee login
* fix(auth): complete external code login and address review findings
Based on build.17.1. Expose auth exchange with client-id selection, verified identity persistence, transactional direct credentials, scoped configuration and accurate provenance. Redact code arguments in performance reports. Include regression tests and bounded real-service verification notes.
* fix(auth): isolate exchange invocations and preserve credential pairing
* fix(auth): close early-exit and config-snapshot isolation gaps
* fix(dingtalk-tag): tolerate temporarily unavailable send receipts
* feat(dingtalk-tag): integrate server device binding lifecycle
* fix(dingtalk-tag): fence uncertain binding writes and preserve retry receipts
* test(dingtalk-tag): update binding command and interface contracts
* fix: refresh local agent binding token and classify rejections
* chore: repair digital employee release fragment metadata
* fix: align local agent MCP tool names
* fix(release): upload only distributable archives and checksums
* docs(release): require change notes and include installation guidance
* fix: align local agent MCP binding contract (#13)
Validated against the pre-production bind -> rebind -> unbind lifecycle on PR head 49e20e79cdbf9b07efbc581aefe90cb839957dff.
* fix(dingtalk-tag): mark digital employee event source
* feat(dingtalk-tag): remove connect profile-only mode
* feat(dingtalk-tag): 移除 connect bind 和 rebind 子命令
* fix(dingtalk-tag): flatten MCP config and require employee scope
* fix(connect): 修正未知命令纠错和发布详情错误提示
* docs(dingtalk-tag): align MCP draft auto-mount guidance
* docs(dingtalk-tag): correct MCP auto-mount release note
* feat(dingtalk-tag): add digital employee management and local agent integration
* fix(dingtalk-tag): align dry-run contracts and cross-platform CI
* fix(event): 修正数字员工传输就绪与系统帧处理
* docs: 补充数字员工真实收发与恢复验收证据
* test(dingtalk-tag): cover platform identity and failure boundaries
* test(dingtalk-tag): exercise worker startup and upload failure paths
* fix(dingtalk-tag): handle Windows shutdown and corrupt state paths
* test(dingtalk-tag): cover login delivery and unbind recovery boundaries
* docs: 明确原消息故障未解决并补充来源对照
* fix: adapt upstream named registration and test employee failure boundaries
* fix: complete employee lifecycle cancellation and failure coverage
* test: wait for consumer startup before cancellation
* docs: align shared skill descriptions with upstream routing
* fix: allow atomic employee state replacement during Windows reads
* fix: retry bounded Windows snapshot rename contention
* test: exercise employee daemon lifecycle on Windows
* feat(dingtalk-tag): align user-facing manage contract
* fix(dingtalk-tag): unify supervisor user id field
* fix: 数字员工事件消费沿用默认来源
* fix(dingtalk-tag): unify avatar URL handling
* fix(dingtalk-tag): map agent type to MCP contract
* fix(dingtalk-tag): validate response mode by agent type
* feat(dingtalk-tag): add manage set-visibility command and align merged tests
- Add `dws dingtalk-tag manage set-visibility` leaf binding the set_visibility
MCP tool (agent-uuid/visibility required; staff-ids/dept-ids as full-replace
string slices), with full contract (Identity/Interface/Safety/Selection).
- Align merge-carried PR-only tests with the feature branch's authoritative
contract:
- drop deapAgentProfileJSON assertions (profile-json flag removed by feature)
- remove retired employee-no size-validation case
- update published-detail missing-identity error assertion to the generalized
message that no longer leaks field names
- provide required --response-mode in RemovesRetiredFlags create case (open_code
default now mandates it) and reflect it in expected MCP args
* fix: address PR #1391 CI lint and auto-CR P1/P2 findings
- CI Lint (make format-check): gofmt-realign the create-args map literal in
deap_agent_test.go so the format gate passes and the full test matrix runs.
- [P1] external_exchange.go: reuse the ClientSecret of the finally selected
clientID by scanning all candidates. The reuse loop was gated on
clientID == configured.id, but configured is only the first valid candidate,
so explicitly selecting a later app/env candidate via --client-id dropped its
unmanaged secret and fell through to an empty-secret managed exchange,
breaking that app's normal OAuth authorization-code login. Managed-ness is now
decided per candidate. Adds env/app later-candidate regression tests.
- [P2] apiclient: reject CR/LF in the streaming UploadMultipart field keys,
file field name and file name before creating the pipe/goroutine, matching the
existing non-streaming newMultipartBody guard, so user-controlled names cannot
inject extra MIME headers/fields. Adds streaming-entry injection tests.
* test(app): align deap-agent schema contract with simplified dingtalk-tag contract
The feature branch simplified the digital-employee create/save-draft/list
contract in source but internal/app/schema_deap_agent_contract_test.go still
asserted the pre-simplification shape, so the final-schema gate failed once CI
Lint stopped fail-fast-skipping the matrix. Verified the same failures exist on
the pristine feature branch (pre-existing test debt, not a merge artifact).
- create_digital_employee: 11 -> 7 params (drop dept-name/icon/profile-json/
employee-no/position-name/supervisor-uid; add avatar-url/supervisor-user-id;
main-program-type property digitalTagEmployeeProfile.mainProgramType -> type).
- update_digital_employee_draft: 15 -> 11 params (same removals/additions).
- list_digital_employees: main-program-type property mainProgramType -> type.
- MCP auto-mount help/schema: expected phrases 自动追加/selectedSkills ->
自动挂载/回读确认 to match the current create_mcp guidance.
- Add set_visibility to the final-schema contract (new manage leaf: write/high/
user_required; agent-uuid/visibility required, staff-ids/dept-ids arrays).
* fix(dingtalk-tag): make create example pass agent dry-run gate
The create_digital_employee example was rewritten to showcase --avatar-url but
dropped --response-mode and pointed avatar-url at a local ./avatar.png. Under
DWS_AGENT_EXAMPLES_DRY_RUN the example must survive the command's own
validation: open_code (default) now requires a --response-mode, and a local
avatar path must be a readable image file, which the dry-run harness does not
materialize. Restore --response-mode mention_only and use a public HTTPS avatar
URL so the example dry-runs through the standard request preview without a
local file read.
* test(helpers): reach 100% changed-code coverage for deap avatar/skill-upload; preserve credential error cause
The changed-code coverage gate (target 100%) failed at 97.74% because the
platform harness only runs TestCrossPlatformCoverage*/TestAllShortcuts tests,
and the digital-employee avatar-upload feature shipped without such tests.
- Rename the four TestDevDeapAgent* avatar/local-agent tests to the
TestCrossPlatformCoverage* convention so the platform coverage harness runs
them (avatar uncovered statements 59 -> 32).
- Add deap_agent_avatar_coverage_test.go covering the remaining branches:
avatar URL validation (http-no-host/unsafe-path/bad-ext/unreadable/dir/
oversize/valid), stage-error formatting + Unwrap, created-UUID envelope
traversal, profile preparation, invalid main-program-type, save-draft
response-mode/avatar validation, create/save avatar call branches (dry-run,
transport error, parse error, upload error), and the OpenAPI avatar uploader
delegate.
- Improve the skill-upload credential error: stop collapsing every cause into a
bare "OpenAPI 认证失败". Preserve the underlying stage cause and server
code/trace for the MCP credential call (no secret exists yet on failure),
while still redacting the injected resolver error so credential material can
never leak. Covered by a new temporaryCredential MCP-branch test.
Local platform coverage gate now reports 100.0000% (2971 changed statements).
* test(helpers): make avatar unsafe-path case cross-platform for Windows coverage
The avatar URL-input branch test used "/abs/path.png" to trigger SafeInputPath's
absolute-path rejection, but filepath.IsAbs("/abs/path.png") is false on Windows,
so it fell through to the unreadable-file branch and failed Coverage (Windows)
with '本地文件不可读' instead of '路径不安全'. Use a NUL control character
("invalid\x00.png"), which rejectControlChars rejects on every platform (same
convention as the existing upload-boundaries test), keeping the unsafe-path
branch covered cross-platform.
* fix(dingtalk-tag): gate employee enqueue on capacity before writing ledger
Previously enqueue wrote the audit entry and dedup task file before checking
the 128-conversation and 32-per-queue capacity limits. A transient capacity
rejection therefore left an 'accepted' task file behind, so Event Bus
redelivery of the same event was short-circuited as already handled and the
message was permanently swallowed (recovery only rewrites accepted->needs_review,
never reprocessing).
Move both capacity checks ahead of audit/writeEmployeeJSON. enqueue holds r.mu
and is the sole producer, so a queue with room can never fill before the send,
letting the record persist only once acceptance is guaranteed; the send is now
unconditional and non-blocking.
Add regression coverage asserting that queue_capacity and conversation_capacity
rejections leave no dedup record and that redelivering the same event after the
backpressure clears is accepted and persisted.
* docs(dingtalk-tag): describe set-visibility scope as ALL/PARTIAL
Align the set-visibility command help, flag usage, MCP description, example and
parameter docs with the server contract that now accepts ALL and PARTIAL
(SELECTED kept only as a legacy alias). PARTIAL is stated explicitly to mean
'visible to the specified members/departments', and the example uses the full
--visibility PARTIAL value instead of the truncated PART.
* feat(dingtalk-tag): unify capability lifecycle
* 补齐数字员工能力跨平台覆盖测试
* docs: add reproducible test evidence for PR #1391
* fix(dingtalk-tag): upload the validated skill file handle
* docs: refresh PR 1391 test evidence and CR resolutions
* ci: give Windows native coverage enough time to finish
* fix(dingtalk-tag): align profile contracts and require explicit type
* fix(test): satisfy required employee type fixture
---------
Co-authored-by: chensi.wx <chensi.wx@alibaba-inc.com>
Co-authored-by: siyideng <dsy274007@alibaba-inc.com>
Co-authored-by: chichuan <haofeng.hf@alibaba-inc.com>
Co-authored-by: 赤川 <30925823+haofeng0705@users.noreply.github.com>
Co-authored-by: 丞天 <yuanchenyu.ycy@alibaba-inc.com>
Co-authored-by: dingpan <dingpan.dp@alibaba-inc.com>
* fix: normalize command validation errors
* fix: normalize command validation errors
* fix: preserve non-validation pre-run errors
* fix: preserve non-validation pre-run errors
* fix: centralize command validation lifecycle
* fix: preserve validation across Cobra traversal and proxies
* chore: preserve upstream Cobra source formatting
* ci: bind Cobra compatibility checks to the PR head
* docs: record completed validation architecture review
* fix: preserve validation failure ownership and lock regression boundaries
* fix: type native Cobra validation for generated commands
* fix: classify legacy Cobra argument lookup failures
* test(app): close the file logger before Windows temp dir cleanup
Executing the runtime root opens <config dir>/logs/dws.log and keeps that
handle for the process lifetime. With DWS_CONFIG_DIR pointed at a
t.TempDir(), Windows cannot remove the directory while the handle is open,
so TestCrossPlatformCoverageTypedValidationErrorGateExtensions failed only
on the Windows coverage job while passing everywhere else.
Register CloseFileLogger after the TempDir so LIFO cleanup releases the
handle first, matching the convention the credential and skill tests use.
* test: cover the fail-closed branches the platform coverage gate counts
The macOS and Windows gates require 100% coverage of changed statements
but only execute TestCrossPlatformCoverage*/TestAllShortcuts* tests, so
three changed statements stayed uncovered even though the full suite passed:
- ResultInvoke rejected without an active unified-result rollout was already
tested, only under a name the gate filter skips. Rename it.
- ExecuteCForTest propagating a PrepareCommandTree failure, reachable when
the root itself is unprepared but a descendant already is.
- Root assembly panicking instead of returning a half-adapted tree when a
mount has already been prepared.
* test(corecmd): cover the ExecuteContext*ForTest success path in package
The aggregate coverage gate assembles per-shard profiles whose -coverpkg is
derived from each shard's changed packages, so a statement in internal/corecmd
exercised only by internal/app or internal/helpers callers can stay uncovered
in the union even though the platform gate, which instruments all four packages
at once, reports 100%. ExecuteContextCForTest's SetContext-and-delegate path
was in that position: in-package tests only reached its nil guard.
Cover it from inside the package so the statement no longer depends on
cross-package instrumentation.
* test(helpers): run standalone whiteboard tests through the prepared tree
Merging main brought in nine new whiteboard tests that execute through bare
cmd.Execute(). A standalone Cobra execution never installs the framework's
validation adapters, so those tests exercised the unprepared path while the
nine pre-existing tests in the same file already used corecmd.ExecuteForTest.
Route all of them through ExecuteForTest so the whole file asserts against the
prepared tree, matching the contract that standalone command tests use the
corecmd *ForTest helpers. Every migrated site used only the returned error, so
the change is one-to-one.
* docs: require standalone command tests to run through the prepared tree
AGENTS.md said standalone command tests may use the corecmd *ForTest helpers.
Permissive wording let a merge from main bring in nine whiteboard tests that
execute through bare cmd.Execute(), which never installs the preparation-stage
validation adapters, so they asserted against the un-adapted path and a
parameter-validation regression would have passed silently.
Make the helper mandatory, record why bare execution is unsafe, and state that
tests arriving from main are in scope so a merge has to re-check them.
* docs: scope the ForTest requirement to test-constructed commands
The rule as first written also flagged root.Execute() after NewRootCommand(),
which is correct code: the app factory already prepared that tree, so bare
Execute runs the adapted path. An over-broad rule forces pointless churn and
cries wolf on valid tests, so exempt factory roots and name the real risk,
which is a tree the test built itself and never prepared.
* fix(errors): keep deadline classification at the business error boundary
WrapErrorWithOperation switched its pass-through guard from "is a structured
*apperrors.Error" to PreserveClassification. That predicate also returns true
for the cancellation and deadline sentinels, so a real context.DeadlineExceeded
left the wrapper untouched, never reached the network-timeout branch, and fell
through to apperrors.ExitCode as internal/exit 5 — losing NETWORK_TIMEOUT, the
API exit code and the retry hint. resolveFileDomain now preserves and wraps
deadlines explicitly, so genuine request timeouts hit this reliably.
Split the concept instead of reverting it, because both behaviours are correct
in their own place. DeclaresClassification recognises only errors carrying a
contract of their own, a structured *Error or an ExitCoder, and is what a
classification boundary should use. PreserveClassification keeps adding
cancellation and deadline identity for validation boundaries, where a timeout
must never be rewritten as a parameter failure.
The existing message table did not catch this: it feeds errors.New(text), and
errors.Is matches only the real sentinel. The regression was in fact pinned by a
test asserting that a wrapped deadline passes through unchanged, so that
assertion is corrected and the sentinel is now tested bare and wrapped, with a
negative control confirming it fails against the old predicate.
* docs(pr): add drive/errors/leaf/oa/recruit/wiki CI evidence
Add a local command-CI collage for PR #1292 covering the Auto CR
required domains, generated from passing focused tests on 7cb5c4dc.
Co-authored-by: john <typefield@users.noreply.github.com>
* test(helpers): compare whiteboard export path via JSON on Windows
Coverage (Windows) failed TestCrossPlatformCoverageWhiteboardExportDownloadsUsingBoardName
because JSON encodes backslashes, so a raw filepath substring no longer matches.
Co-authored-by: john <typefield@users.noreply.github.com>
* Sync merge tree rename deletions
* fix(test): keep result-store installation store-only; tidy go.sum
EmitStoredResult must stay with the caller: unified-result tests set the
output writer after execution and emit themselves, so an automatic emit
inside ExecuteCForTest wrote to the default writer and consumed the
store's emitAttempted, leaving captured stdout empty. go mod tidy drops
cobra v1.10.2 checksums orphaned by the merge (Policy tidy gate).
---------
Co-authored-by: 玉澜 <yulan.wqy@alibaba-inc.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: john <typefield@users.noreply.github.com>
Merging current main copies interface_const_params.go onto v1.0.62 snapshots; that file now imports commandstore, so Interface Integrity failed with a missing package.
Co-authored-by: Cursor <cursoragent@cursor.com>
Schema runtime cache shared-root installer hardening: validate and lock every parent directory before creation or chmod, and re-verify before the first permission change. Adds symlink-swap regression tests for non-sticky writable parents and sticky-parent acceptance.
Consume the reviewed schema_availability_hardening ledger so the four contract review commands stay as hidden argv stubs, publish Schema availability unavailable, and stop calling retired review MCP tools.
Co-authored-by: Cursor <cursoragent@cursor.com>
Register reviewed schema_availability_hardening plans so a follow-up PR can hide the four legacy contract review commands and mark their Schema unavailable without self-approving the surface change.
Co-authored-by: Cursor <cursoragent@cursor.com>
The per-target CC/CXX templates resolve through .Env. .goreleaser.yaml also
declares the twelve CC_/CXX_ entries earlier in the same builds.env list, and
GoReleaser happens to surface those to later entries because TemplateEnv
re-binds the template after each evaluation. That is an undocumented internal,
so a GoReleaser upgrade could silently leave every target with an empty CC and
fall back to the host toolchain under CGO_ENABLED=1.
Export the same twelve values from the cross-toolchain wrapper as explicit
--env NAME=VALUE entries, so the container process environment supplies them
regardless of how the config list is evaluated. The config entries stay, which
keeps a direct goreleaser invocation self-contained.
TestReleaseCrossCompilerEnvMatchesWrapper compares the two sources for every
goos/goarch in the release matrix and asserts the wrapper actually forwards
them to docker run, so a value can only be added, changed or dropped in one
place if the other disagrees. Verified non-vacuous by perturbing
CC_darwin_amd64 and observing the mismatch report.
require_glibc_on_linux rejected on the mere existence of
/lib/ld-musl-*.so.1 before consulting ldd. A glibc distribution that has
musl or musl-tools installed carries that file while its default loader
stays glibc, so the installer refused a system that runs the release
binary fine.
Make ldd --version the authority: reject when it reports musl, accept
when it reports GNU libc/glibc. Keep the loader-file probe as the
fallback for musl distributions whose ldd reports no version, notably
Alpine where BusyBox ldd only forwards to the loader, which is what the
probe was added for.
Tests stub ls alongside the existing ldd stub so a case can simulate the
loader file being present without writing to the host /lib, covering the
glibc-with-musl coexistence that was previously untested, plus an
ordering assertion so a future reorder fails statically.
Review follow-ups on the default-CGO SafeChat release change:
- Hold the trackedCipher mutex across the whole backend call so Close
waits for in-flight operations. The vendor client reads Client.inited
before taking its own mutex, so a Close overlapping an encrypt or
decrypt was a reproducible data race now that the backend ships in
every default CGO build.
- Refuse musl-based Linux in install.sh, install-event.sh, and
install-devapp.sh before resolving or downloading the asset. The
release binaries link glibc and cannot start on musl, which previously
surfaced only as an opaque loader error after a successful install.
- Record the breaking removal of dws safechat selftest/decrypt with the
chat crypto decrypt migration path, and document the glibc baseline.
- Stage, verify, and atomically publish the cached GoReleaser and Zig
tools behind a mkdir lock, and re-verify both the pinned archive digest
and the executable digest on a cache hit. An interrupted download or
extraction can no longer leave a half-installed tool that a later run
would accept.
- Pin that every goos/goarch target in the release matrix declares its
CC_/CXX_ entries, so the per-target compiler template cannot silently
resolve to an empty compiler.