Skip to content

chore(release): verify SHA512 against actual archive (#634)#635

Merged
kcenon merged 1 commit into
developfrom
chore/issue-634-verify-sha512-against-actual-archive
May 3, 2026
Merged

chore(release): verify SHA512 against actual archive (#634)#635
kcenon merged 1 commit into
developfrom
chore/issue-634-verify-sha512-against-actual-archive

Conversation

@kcenon

@kcenon kcenon commented May 3, 2026

Copy link
Copy Markdown
Owner

Closes #634

Part of kcenon/common_system#674.

What

Adds an independent SHA512 verification job to .github/workflows/on-release-sync-registry.yml that re-downloads the release archive from GitHub and recomputes its digest after the reusable sync workflow completes. On mismatch (or fetch failure, or suspiciously small archive) the job exits 1 before consumers cold-cache install the broken portfile.

Why

Detected via microsoft/vcpkg#51511 and kcenon/vcpkg-registry#87 - every kcenon port shipped a mismatched SHA512 because the release workflow never compared its computed value against the actual archive. Cold-cache vcpkg consumers (new CI runners, fresh users) hit 100% install failure when the SHA in vcpkg-registry/ports/kcenon-logger-system/portfile.cmake does not match the bytes at https://github.com/kcenon/logger_system/archive/refs/tags/v<version>.tar.gz. This PR closes the detection gap for logger_system.

Where

File Change
.github/workflows/on-release-sync-registry.yml New job verify-sha512 (needs: sync) added after the existing sync job that delegates to kcenon/common_system/.github/workflows/sync-vcpkg-registry.yml@main

Audit summary (other workflows considered)

Workflow Touches portfile SHA? Action
on-release-sync-registry.yml Yes (delegates to reusable workflow that computes SHA and writes portfile) Hardened (this PR) with a post-sync independent verification job
ci.yml, sanitizers.yml, sbom.yml, osv-scanner.yml, cve-scan.yml, integration-tests.yml No (build/test/scan only; mention SHA only in comments or sbom metadata) No change needed
benchmarks.yml, build-Doxygen.yaml, coverage.yml, doc-audit.yml, performance-regression.yml, static-analysis.yml No No change needed

logger_system does not have a release.yml of its own; releases are created via the GitHub UI, and on-release-sync-registry.yml is the only release-event-driven workflow. Adding the verification job here matches the validated pattern from kcenon/common_system#676 while accommodating the thin-caller architecture (the existing sync job is a single uses: line and cannot host an inline step).

How

The new job runs immediately after the sync job (needs: sync). It re-fetches the archive with curl -fsSL --retry 3 to a file (not piped) so a 404 cannot silently produce the empty-input hash cf83e1357eefb8bdf.... A minimum-size sanity check rejects archives under 1 KiB. The output prints the SHA512 alongside the expected portfile path so reviewers of the resulting vcpkg-registry PR can cross-check by eye.

Runtime: ~1-2s on a typical logger_system archive.

Test Plan

How a reviewer can validate the new job fires

  1. Cut a release tag (v0.x.y) - GitHub fires release: published and triggers on-release-sync-registry.yml
  2. Both jobs (sync, verify-sha512) appear in the run; verify-sha512 waits for sync via needs:
  3. On a healthy release, verify-sha512 prints:
    Re-fetching https://github.com/kcenon/logger_system/archive/refs/tags/v0.x.y.tar.gz for independent verification...
    SHA512 for v0.x.y:
      <128-char hex digest>
    This value MUST match the SHA512 line in
      kcenon/vcpkg-registry/ports/kcenon-logger-system/portfile.cmake
    after the sync job's PR is merged. Reviewers should cross-check.
    

Failure-mode coverage

  • Bad URL (nonexistent tag): curl -fsSL returns RC=22, the if ! branch fires exit 1 with Failed to download release archive for verification: <URL>. The download-to-file pattern (rather than a pipe) is required to make this work - piping into sha512sum would otherwise mask the curl failure with the empty-input hash.
  • Truncated/empty archive: minimum-size check (< 1024 bytes) catches partial downloads or HTML error pages even if the HTTP status was 200.
  • Reusable workflow regression: even if kcenon/common_system/.github/workflows/sync-vcpkg-registry.yml ever loses its in-workflow verify step, this repo-local job still runs and prints the canonical SHA, providing a manual cross-check anchor.

YAML validation

Workflow structure inspected manually (jobs: sync, verify-sha512; verify-sha512.needs: sync; standard permissions: contents: read). GitHub Actions runner will surface any parse error on the first release: published event.

Breaking Changes

None. The new job is additive; on a successful release it adds ~1-2s and one log line. On a SHA fetch failure or empty-archive condition (the failure mode this PR is designed to detect) it short-circuits the run after the existing sync job has already opened a registry PR, surfacing the mismatch in the run log so the registry PR can be reverted before merge.

Rollback

Revert this commit. The sync job continues to delegate to kcenon/common_system/.github/workflows/sync-vcpkg-registry.yml@main, which retains its own internal verify step from kcenon/common_system#676.

Add an independent SHA512 verification job to on-release-sync-registry.yml
that re-downloads the release archive from GitHub and recomputes its digest
after the reusable sync workflow completes. Provides repo-local
defense-in-depth on top of the verify step inside
kcenon/common_system/.github/workflows/sync-vcpkg-registry.yml that was
added in kcenon/common_system#676.

The job uses file-based hashing (curl -fsSL --retry 3 -o file, then
sha512sum file) rather than a pipe so a fetch failure cannot silently
produce the empty-input hash cf83e1357eefb8bdf... A minimum-size sanity
check rejects suspiciously small archives.

Closes #634

Part of kcenon/common_system#674.
@kcenon kcenon merged commit 392a0dd into develop May 3, 2026
2 checks passed
@kcenon kcenon deleted the chore/issue-634-verify-sha512-against-actual-archive branch May 3, 2026 13:00
kcenon added a commit that referenced this pull request Jun 19, 2026
* docs: apply mechanical doc-review fixes (#605)

* docs: fix 48 broken cross-references, 5 version mismatches, and xref gaps

Address findings from DOC_REVIEW_REPORT.md covering all Must-Fix items
that are mechanically safe plus Should-Fix and Nice-to-Have items where
resolution is unambiguous.

Phase 1 (broken inter-file links):
- Re-point legacy docs/01-architecture.md and docs/02-API_REFERENCE.md
  references to docs/ARCHITECTURE.md and docs/API_REFERENCE.md (12 hits)
- Repair missing-target references in README.md, docs/README.kr.md,
  and docs/advanced/ with correct relative paths
- Wrap genuinely missing targets (BUILD_GUIDE.md, TROUBLESHOOTING.md,
  API.md, EXAMPLES.md, ENCRYPTION.md, IMPROVEMENT_PLAN.md) with TODO
  markers pointing to closest canonical reference
- Fix path-depth errors in docs/advanced/ for examples/ and include/
- Fix anchor in DECORATOR_MIGRATION.md (writers -> writers-and-filters)
- Redirect cross-project common_system links to GitHub canonical
- Wrap orphan .kr.md language-switcher targets with deferral TODO

Phase 2 (factual / version corrections):
- Update SOUP.md table to match vcpkg.json authoritative versions for
  OpenSSL 3.4.1, spdlog 1.15.3, OpenTelemetry 1.18.0, protobuf 4.25.1,
  grpc 1.60.0, gtest 1.17.0, benchmark 1.9.5 (IEC 62304 SOUP control)
- Update C++17 claims in PROJECT_STRUCTURE, PRODUCTION_QUALITY to C++20
  with corresponding compiler minimums (GCC 11+, Clang 14+, MSVC 2022+)
- Bump CONFIGURATION_STRATEGIES and CONFIG_STRATEGIES_ADVANCED version
  stamp from 2.x to 3.x
- Align root CONTRIBUTING.md compiler minimums with project standard

Phase 3 (SSOT / orphan reduction):
- Add cross-reference between docs/GETTING_STARTED.md (long-form
  tutorial) and docs/guides/GETTING_STARTED.md (canonical short guide)
- Register orphan docs (GETTING_STARTED.md, ECOSYSTEM.md) in the docs
  registry index

Skipped: Korean translation sync, SSOT collisions without named
canonicals, API contract changes, manifest version bumps.

* docs: add post-fix re-validation report

* docs: fix README FAQ anchor regression

* fix(cmake): correct exported target name in config and documentation (#609)

The CMake config template incorrectly set logger_system_LIBRARIES to
logger_system::logger, but the actual exported IMPORTED target created
by install(EXPORT ... NAMESPACE logger_system::) is logger_system::logger_system.

Fixes:
- logger_system-config.cmake.in: correct target reference
- UnifiedDependencies.cmake: add canonical target to resolution map
- README, guides, and structure docs: align find_package() and
  target_link_libraries() examples with actual target names

Closes #606

* test(coverage): add unit tests for logger_registry, console_writer, standalone_executor (#610)

Add 46 new test cases targeting untested source files to improve coverage
toward the 70% minimum threshold for v1.0:

- logger_registry_test: null handling, duplicate prevention, snapshot
  consistency, concurrent registration/unregistration (14 tests)
- console_writer_test: stream capture, ANSI color codes, stderr
  selection by log level, concurrent writes (14 tests)
- standalone_executor_test: job execution, delayed execution, queue
  overflow, exception propagation, factory, concurrent submission
  (18 tests, guarded by LOGGER_HAS_IEXECUTOR)

Closes #607

* chore(release): bump version to 1.0.0 and update CHANGELOG (#611)

- Move [Unreleased] content to [1.0.0] section with 2026-04-15 date
- Document breaking changes (#534), CMake fixes (#606), new tests (#607)
- Bump VERSION in CMakeLists.txt from 0.1.3 to 1.0.0
- Update vcpkg.json and vcpkg-ports version-semver to 1.0.0
- Reset port-version to 0 for new major version
- Update UnifiedDependencies default tag to v1.0.0

Closes #608

* feat(security): extend HMAC integrity protection to all core writers (#615)

* feat(security): add integrity_policy and extend HMAC to core writers

Introduce an integrity_policy abstraction (HMAC-SHA256 default) under
include/kcenon/logger/security/ and wire it into file_writer,
rotating_file_writer, console_writer, and network_writer via an opt-in
set_integrity_policy() setter. Each writer now appends a per-record
tamper-evident signature when a policy is installed:

- file_writer / rotating_file_writer / console_writer: emit
  ` SIGNATURE[HMAC-SHA256]:<hex>` suffix on the same line as the record
- network_writer: adds `sig_alg` and `signature` JSON fields to every
  outbound frame, computed over the unsigned body

Reuses the existing OpenSSL EVP_MAC HMAC implementation pattern from
audit_logger and the secure_key RAII wrapper for key handling, so no
changes to key derivation, key storage, or secret-handling surface are
required. Without OpenSSL, a portable non-cryptographic fallback keeps
round-trip verification working (not for production tamper detection).

Addresses ISO/IEC 27001 A.12.4.2, A.12.4.3 (file/console) and A.14.1.3
(network) by default.

Refs #612

* test(security): add integrity_policy round-trip tests and doc mapping

Add integrity_policy_test covering:
- HMAC sign/verify round-trip and key-isolation
- file_writer signed-line parsing and verification
- rotating_file_writer signed-line round-trip
- console_writer stdout capture with signature
- Tampered-record detection (bit-flip)
- No-policy path emits no signature (backward compatibility)

Wire into the existing logger_security_test target so OpenSSL detection
and macOS libc++ linkage settings are reused. Update SECURITY_GUIDE.md
with an ISO/IEC 27001 control mapping table (A.12.4.2, A.12.4.3,
A.14.1.3) and code examples for enable + verification.

Refs #612

* docs(guide): complete build and troubleshooting links (#616)

Add BUILD.md and TROUBLESHOOTING.md under docs/guides/, fix remaining
README and PROJECT_STRUCTURE references that pointed to non-existent
pages, and register the new documents in the docs/ index.

- docs/guides/BUILD.md: prerequisites, CMake options, presets,
  optional features, install, downstream consumption, platform notes.
- docs/guides/TROUBLESHOOTING.md: build errors, linker errors, runtime
  issues, performance issues, integration and platform notes.
- README.md, docs/PROJECT_STRUCTURE.md, docs/PROJECT_STRUCTURE.kr.md:
  link the new guides and remove TODO placeholders.
- docs/README.md: register LOG-GUID-028 and LOG-GUID-029.

Closes #614

* test(core): add coverage for signal_manager_context and log_context_scope (#617)

Add dedicated unit tests for signal_manager_context covering lifecycle,
thread-safe getters/setters, and idempotent set operations. Extend
structured_logging_test.cpp with tests for the log_context_scope
constructor overload that accepts a logger reference, verifying both
thread-local and logger-level context are correctly set on entry and
restored on exit, including nested scopes and overridden keys.

Relates to #613

* test: raise unit test coverage toward 80% (#618)

Adds two previously missing unit-test suites to shrink the coverage
gap highlighted by the README's ~65% claim:

- tests/unit/utils/error_handling_utils_test.cpp
  Covers error_context formatting, try_write_operation exception
  mapping (filesystem, ios, system, bad_alloc, generic, non-standard),
  try_open/network/encryption_operation defaults, check_condition,
  check_stream_state (failbit/badbit), check_file_exists,
  ensure_directory_exists, and destructor-safe wrappers.

- tests/unit/core/small_string_test.cpp
  Covers the SSO container across the small/heap boundary:
  construction, copy/move, assignment, clear, reserve,
  append (SSO staying vs promoting, heap extension), string_view
  conversion, equality operators, memory statistics, and public
  aliases (small_string_64/128).

Both files were completely untested before this change.
Production code is untouched; only tests and their CMake wiring
are modified.

Relates to #613

* ci(coverage): enforce 80% line / 70% branch coverage gate (#619)

* ci(coverage): enforce 80% line / 70% branch threshold gate

The Code Coverage workflow previously measured coverage and only printed
'Phase 5 Target: 80%+' as informational text. This change adds a real
gate that fails the job when measured coverage drops below threshold.

Changes:
- Trigger on PRs targeting develop in addition to main, so the gate
  runs at the integration boundary (not only on release PRs to main).
- Trigger on push to develop for visibility on integration commits.
- New 'Enforce coverage threshold' step parses lcov --summary output
  and fails non-zero when line < 80% or branch < 70%.
- Branch coverage check is conditional on lcov reporting it, so the
  job does not regress if branch instrumentation is unavailable.

Closes #613

* fix(tests): repair pre-existing compile errors blocking coverage

Two test files added by PR #610 fail to compile against the current
APIs and have left develop's Coverage workflow non-functional. Fixing
them here so the new coverage gate (preceding commit) can actually
evaluate measured coverage instead of failing at build time.

console_writer_test.cpp:
- log_entry has no default constructor; switch the test helper to
  use the (level, message, timestamp) constructor directly.

standalone_executor_test.cpp:
- Result<T> exposes is_ok() for the success-check API; has_value()
  is not part of the version of common_system the workflow checks
  out from main. Replace 6 occurrences with the canonical is_ok().

* ci(coverage): pin lcov to gcov-13 to match GCC 13 .gcno format

The coverage build compiles with GCC 13 (installed and aliased to
/usr/bin/gcc in the Install dependencies step), which emits .gcno
files in a newer format. Ubuntu 22.04's default lcov ships with
gcov-11, which rejects the files:

    .gcno:version 'B34*', prefer 'B14*'
    geninfo: ERROR: GCOV failed
    lcov: ERROR: no valid records found in tracefile coverage.info

Pass --gcov-tool with a detected gcov-13 (falling back to gcov if
absent) so lcov can actually read the coverage data. Without this,
coverage_filtered.info is never produced and the new threshold gate
cannot evaluate anything.

* ci(coverage): set initial floor at 78% (current measured baseline)

Current measured line coverage is 78.3% (5266 of 6725 lines). Setting
the gate at 78% prevents regressions below today's baseline. A
follow-up issue will raise the threshold to the full 80% target once
the pre-existing failing tests are repaired:
- EncryptedWriterTest.WriteAndDecryptSingleEntry
- EncryptedWriterTest.WriteMultipleEntries
- LoggerOtelIntegrationTest.LoggerContextMethods
- ConsoleWriterIntegrityTest.RoundTripOnStdout

or new cases close the remaining ~1.7% gap in logger.cpp (63.6%),
encrypted_writer.cpp (63.9%), and log_sampler.cpp (60.1%).

* ci(coverage): require % suffix when parsing lcov summary

lcov --summary prints 'branches...: no data found' when branch
instrumentation is disabled. The previous awk extracted $2 which was
'no' — a non-empty string that passed the guard but failed the
numeric comparison against the threshold, so the gate incorrectly
failed the job even though line coverage met the floor.

Require the second field to end in '%' so only real percentages are
captured; BRANCH_COVERAGE stays empty when lcov emits no data, which
the existing -n guard then correctly skips.

* test(coverage): raise coverage gate to 80% and restore broken tests (#621)

* test(coverage): raise coverage gate to 80% and restore broken tests

Raise the enforced line-coverage gate from 78 to 80 and fix four
previously failing tests that prevented instrumented paths from
counting toward coverage.

- coverage.yml: LINE_THRESHOLD 78 -> 80 (BRANCH_THRESHOLD unchanged at 70)
- console_writer: flip stream-selection predicate from level <= error
  to level >= error so info/debug/warning land on stdout and error/fatal
  land on stderr as documented (fixes ConsoleWriterIntegrityTest
  .RoundTripOnStdout and ConsoleWriterTest.WriteInfoMessageToStdout)
- file_writer: add binary mode that opens the stream with std::ios::binary
  and skips the trailing newline, letting encrypted_writer wrappers emit
  framed payloads without the default timestamp prefix corrupting them
- raw_formatter: new pass-through formatter that returns entry.message
  verbatim, used by encrypted-write tests to keep binary frames intact
- encrypted_writer_test: wrap inner file_writer with raw_formatter and
  binary=true in the three tests that write and read back encrypted
  frames (WriteAndDecryptSingleEntry, WriteMultipleEntries,
  DecryptWithWrongKey) so the header magic survives the round trip
- otlp_test: update LoggerContextMethods to query the canonical
  otel_trace_id key written by set_otel (matches unified_log_context_test
  and scoped_context_guard_test)
- logger.h: align the set_otel usage comment with the actual key names

Closes #620

* test(sampling): cover log_sampler edge cases

Lift `src/sampling/log_sampler.cpp` line coverage to push the project
over the new 80% gate introduced earlier in this PR. Adds 12 tests in
tests/log_sampling_test.cpp that exercise previously-uncovered paths:

- move constructor and move assignment preserve config + stats.
- `should_sample(const log_entry&)` overload hits the bypass-field and
  field-rate branches for all four log_value variants (string, int64,
  double, bool), the category fallback, and the bypass-level short
  circuit. The double-variant test derives the lookup key via
  `std::to_string` to stay locale-robust across CI hosts.
- adaptive strategy throttles the effective rate when the per-second
  window exceeds the threshold and restores the base rate when traffic
  subsides (both branches of `update_adaptive_rate`).
- rate-limiting strategy accepts new entries after its configured
  window elapses (short 200 ms window keeps the test fast).
- `get_effective_rate` reports the configured rate at construction
  and tracks `set_config` updates.

No production sources are touched and no existing tests change
behavior. All 52 log_sampling_test cases pass locally (macOS, clang).

* docs(compliance): add ISO/IEC 27001 control mapping and README section (#623)

Closes #622

- Add docs/compliance/iso-27001.md mapping logger_system features
  (audit_logger, encrypted_writer, secure_key_storage, path_validation,
  log_sanitizer, rotating_file_writer) to ISO/IEC 27001:2022 Annex A
  controls (A.5.17, A.5.33, A.5.34, A.8.3, A.8.11, A.8.15, A.8.16,
  A.8.24, A.8.28, A.8.34).
- Add Compliance section to README with link to the mapping document.
- Update README Table of Contents.

Part of #645 (kcenon/common_system — ecosystem-wide ISO compliance).

* fix(monitoring): remove dead thread_system_monitor_adapter (#625) (#626)

* fix(monitoring): remove dead thread_system_monitor_adapter

The adapter referenced `<kcenon/thread/interfaces/monitorable_interface.h>`,
which was removed upstream by thread_system PR #312/#323 during the migration
to `common::interfaces::IMonitor`.

The adapter was never instantiated anywhere in the codebase: it had no source
file references, no CMakeLists.txt entry, and no test coverage. The codebase
already uses `common::interfaces::IMonitor` and `IMonitorable` (see
examples/monitoring_integration_example.cpp), so the adapter was pure dead
code behind a dormant `#ifdef USE_THREAD_SYSTEM` gate.

Removing it eliminates the stale upstream include and cleans up an unused
file rather than reviving a dead path through migration.

Closes #625

* ci(coverage): drop fragile PPA dep, use ubuntu-24.04

Coverage Analysis was timing out at add-apt-repository on
ppa:ubuntu-toolchain-r/test because Launchpad was unreachable from
the runner. Three consecutive runs failed on this exact step.

Ubuntu 24.04 ships gcc-13 in the base archive, so the PPA and its
software-properties-common dependency can be removed entirely. This
eliminates the external Launchpad dependency from the coverage job.

* ci(coverage): tolerate lcov 2.0 strict errors

lcov 2.0 ships with ubuntu-24.04 and escalates 'mismatched end line'
to a fatal error where lcov 1.15 only emitted a warning. The mismatch
originates from gcov-13 debug info for inlined/templated test bodies
and has no effect on numeric coverage; bypass per lcov's own hint.

* ci(coverage): clamp gcc-13 negative counts in lcov

lcov 2.0 drops the entire tracefile when geninfo encounters
'Unexpected negative count' from GCC 13 atomic-update races on
inlined std-lib headers. Adding 'negative' to --ignore-errors clamps
those counts to zero so coverage data survives.

* docs(readme): link kcenon-system-layout standard (#631)

Add a 'Project Layout' section to README.md and README.kr.md that
links to the kcenon ecosystem layout standard (v1.1) and notes
logger_system's role as a reference example of the convention.
Update the table of contents and CHANGELOG accordingly.

Closes #629.

* chore(cmake): align cmake modules with canonical template (#628) (#632)

* chore(cmake): rename logger_warnings.cmake to warnings.cmake

Step 1 of #628 cmake module alignment with kcenon-system-layout v1.1.

Renames logger_warnings.cmake to the canonical warnings.cmake name
and adds the standard module responsibility/input/output header.
Updates the include() reference in root CMakeLists.txt.

No functional changes; purely a rename for canonical compliance.

Refs: #628

* refactor(cmake): create options.cmake from inline option() and logger_features.cmake

Step 2 of #628 cmake module alignment.

Creates the canonical cmake/options.cmake by absorbing:
  - All option() and BUILD_* mapping logic from root CMakeLists.txt
    (former lines 53-107)
  - All feature flags, performance tuning vars, validation, and helper
    functions from cmake/logger_features.cmake
  - LOGGER_USE_THREAD_SYSTEM option (formerly inline in root)
  - LOGGER_USE_ENCRYPTION option (formerly inline in root, default ON)

Removes cmake/logger_features.cmake (fully absorbed; no remaining
references outside comments).

Root CMakeLists.txt now sets CMAKE_MODULE_PATH then calls
include(options) once; behavior identical (same option defaults,
same validation, same logger_print_features() and
logger_configure_target() helpers).

Refs: #628

* refactor(cmake): create compiler.cmake from inline standard, CompilerChecks, sanitizers

Step 3 of #628 cmake module alignment.

Creates the canonical cmake/compiler.cmake by absorbing:
  - C++20 standard requirement and compiler info banner from root
    CMakeLists.txt (former lines 25-48)
  - All compiler version, platform, build-type, header, and feature
    detection functions from cmake/CompilerChecks.cmake
  - Sanitizer cache var, logger_add_sanitizers(), runtime config, and
    test enable macro from cmake/logger_sanitizers.cmake

Removes cmake/CompilerChecks.cmake and cmake/logger_sanitizers.cmake
(fully absorbed; no remaining references).

Reorders root includes so options.cmake runs before compiler.cmake;
LOGGER_ENABLE_SANITIZERS is declared in options.cmake and consumed by
compiler.cmake's sanitizer logic.

Refs: #628

* refactor(cmake): create dependencies.cmake from logger_dependencies and UnifiedDependencies wiring

Step 4 of #628 cmake module alignment.

Creates the canonical cmake/dependencies.cmake by:
  - Including UnifiedDependencies.cmake (large shared module retained
    as a helper to avoid risky rewrites of cross-system code)
  - Calling unified_setup_dependency_mode() and resolving common_system
    (formerly inline in root CMakeLists.txt lines 110-141)
  - Absorbing all logger_find_*() helper functions from
    cmake/logger_dependencies.cmake
  - Absorbing check_bidirectional_dependency_guard() and its
    documentation block from root (former lines 209-262)

Removes cmake/logger_dependencies.cmake (fully absorbed).

Adds the standard module responsibility / inputs / outputs header to
UnifiedDependencies.cmake (DEV-09).

Root CMakeLists.txt now calls include(dependencies) once, then
logger_find_all_dependencies(), logger_print_features(), and
check_bidirectional_dependency_guard().

Refs: #628

* refactor(cmake): create testing.cmake and examples.cmake from inline wiring

Step 5 of #628 cmake module alignment.

testing.cmake absorbs:
  - All coverage logic from cmake/logger_coverage.cmake
    (logger_register_coverage_target, logger_add_coverage,
    logger_setup_coverage_target, logger_enable_coverage_for_all,
    LOGGER_COVERAGE_TARGETS_LEGACY)
  - enable_testing() invocation, tests/ + unittest/ subdirectory
    wiring (formerly root lines 387-404)
  - integration_tests/ subdirectory wiring with BUILD_WITH_COMMON_SYSTEM
    gate (formerly root lines 410-418)
  - logger_enable_sanitizers_for_tests() and logger_enable_warnings_for_all()
    invocations
  - logger_enable_coverage_for_all() call (must run after subdirectories)

examples.cmake absorbs:
  - examples/samples subdirectory wiring with BUILD_SAMPLES + CI
    environment gate (formerly root lines 374-385)

Removes cmake/logger_coverage.cmake (fully absorbed).

Refs: #628

* refactor(cmake): create install.cmake from inline install rules

Step 6 of #628 cmake module alignment.

Creates the canonical cmake/install.cmake by absorbing the entire
install block from root CMakeLists.txt (former lines 608-731):
  - install(TARGETS) with EXPORT vs no-EXPORT branch
    (_LOGGER_HAS_LOCAL_THREAD_SYSTEM)
  - install(DIRECTORY include/) for public headers
  - install(EXPORT logger_system-targets) when no local thread_system
  - configure_package_config_file() and write_basic_package_version_file()
  - install(FILES) for the adapter header and config files
  - All LOGGER_USE_* and LOGGER_DEFAULT_* variable forwarding for the
    config template (@var@ substitution safety)

Adds BUILD_WITH_COMMON_SYSTEM default to dependencies.cmake so
testing.cmake's gate is well-defined regardless of UnifiedDependencies
resolution path.

Root CMakeLists.txt now calls include(install) once at the bottom.

Refs: #628

* refactor(cmake): create targets.cmake with explicit source list and remove file(GLOB)

Step 7 of #628 cmake module alignment. This is the largest single
extraction in the series.

targets.cmake absorbs the entire library target block from root
CMakeLists.txt (former lines 300-548), including:
  - LOGGER_INCLUDE_DIR / LOGGER_SOURCE_DIR setup and existence checks
  - Explicit LOGGER_SOURCES list (32 .cpp files) replacing
    file(GLOB_RECURSE LOGGER_SOURCES ...) -- resolves DEV-04 (R-19)
  - Explicit LOGGER_HEADERS list (87 .h files) replacing
    file(GLOB_RECURSE LOGGER_HEADERS ...) -- resolves DEV-04 (R-19)
  - LOGGER_WITH_SERVER / LOGGER_WITH_ANALYSIS list(FILTER) gates
  - add_library(logger_system) with EXPORT_NAME logger
  - target_include_directories(BUILD_INTERFACE / INSTALL_INTERFACE)
  - BUILD_SHARED_LIBS LOGGER_SYSTEM_BUILDING / _STATIC defines
  - Inherited-warning suppression flags (-Wno-* for GCC/Clang, /wd4xxx
    for MSVC) -- noted as #630 routing per audit DEV-03 / R-36
  - common_system PUBLIC linking with kcenon::common_system
  - thread_system multi-resolution branch with
    _LOGGER_HAS_LOCAL_THREAD_SYSTEM marker (consumed by install.cmake)
  - OpenSSL conditional linking with encrypted_writer source filter
  - OpenTelemetry / OTLP conditional linking
  - C++20 modules FILE_SET CXX_MODULES configuration

Adds logger_resolve_thread_system() and logger_resolve_spdlog()
helpers in dependencies.cmake; root now calls these instead of
inlining LOGGER_USE_THREAD_SYSTEM resolution.

Sources/headers are kept alphabetically sorted by directory and
filename. New source/header files MUST be added explicitly to
LOGGER_SOURCES / LOGGER_HEADERS in cmake/targets.cmake.

Refs: #628

* refactor(cmake): root CMakeLists.txt becomes thin orchestrator (732 -> 40 lines)

Step 8 (final structural step) of #628 cmake module alignment.

Root CMakeLists.txt now contains only:
  - cmake_minimum_required + LOGGER_CAN_USE_MODULES feature gate
  - project()
  - CMAKE_*_OUTPUT_DIRECTORY shared variables
  - CMAKE_MODULE_PATH setup
  - include() of the eight canonical modules in standard order:
    options -> compiler -> dependencies -> warnings -> targets ->
    install -> testing -> examples
  - Inline benchmarks subdirectory (uses FetchBenchmark.cmake helper)

To support this, compiler.cmake self-invokes its check_compiler_version,
configure_platform_settings, configure_build_types, check_required_headers,
check_cpp_features at the bottom; dependencies.cmake self-invokes
logger_find_all_dependencies, logger_print_features, NO_VCPKG fallback,
check_bidirectional_dependency_guard, logger_resolve_thread_system,
logger_resolve_spdlog at the bottom. This keeps ordering deterministic
and root file purely declarative.

Resolves DEV-03 (R-17 -- thin orchestrator) per audit.

Refs: #628

* chore(cmake): add module responsibility headers to helper modules

Final cleanup step of #628 cmake module alignment.

Adds the standard module responsibility / inputs / outputs header
block to FetchBenchmark.cmake (helper module called from
tests/benchmarks/CMakeLists.txt). UnifiedDependencies.cmake header
was added in step 4.

Resolves DEV-09 for the modules touched by this PR. The remaining
auxiliary module logger_compatibility.cmake is unused by the
canonical orchestration and is left intact for #630 to either remove
or repurpose alongside DEV-08 / DEV-01 cleanup work.

Refs: #628

* chore(patches): corrective patches for audit deviations (#630) (#633)

* refactor(logger_types): migrate namespace logger_system to kcenon::logger

Move overflow_policy and health_status declarations from
namespace logger_system into the canonical namespace kcenon::logger,
matching the kcenon-system-layout.md standard (R-20/R-21).

Backward compatibility:
- namespace logger_system retains [[deprecated]] forwarding aliases
  for overflow_policy and health_status; the aliases will be removed
  in the next minor release.

Other changes:
- include/kcenon/logger/core/logger.h drops the legacy
  using-declarations that pointed at logger_system::* — the types are
  now visible directly as kcenon::logger::overflow_policy and
  kcenon::logger::health_status without an alias.
- The logger_error_code enum that lived in logger_types.h was
  unreachable dead code (no callers; its short member list overlapped
  with the canonical kcenon::logger::logger_error_code defined in
  core/error_codes.h, which all production callers already use).
  Removed.

Refs: #630, audit DEV-05 (R-20/R-21)
Closes a subtask of #630.

* chore: add VERSION file at repository root

Add a single-line SemVer VERSION file at the repository root,
following the kcenon-system-layout.md standard (R-29). The file
contains "1.0.0".

Wire the root CMakeLists.txt to read the file with file(READ) +
string(STRIP) and pass the resulting value to project(... VERSION
${LOGGER_VERSION} ...). The VERSION file becomes the single source
of truth — bumping it in one place propagates to the CMake project
version, the install/config-package metadata, and any downstream
tooling that wants to read the version without parsing CMake.

Refs: #630, audit DEV-06 (R-29)
Closes a subtask of #630.

* chore(tests): align test file names with R-33 convention

Two related changes addressing audit DEV-08 (R-33 test file naming):

1. Rename tests/thread_safety_tests.cpp -> tests/thread_safety_test.cpp
   (singular suffix per the standard). Also update tests/CMakeLists.txt
   so the logger_thread_safety_test target picks up the new filename.

2. Move tests/integration_test.cpp -> integration_tests/scenarios/
   multi_writer_integration_test.cpp.

   The previous file held cross-system scenarios (multi-writer
   integration, file rotation, metrics collection across the public
   API, multi-threaded contention, full start/stop lifecycle) — these
   belong under integration_tests/ per the directory-split rule, not
   tests/ which is reserved for unit-level coverage. The fixture was
   renamed from IntegrationTest to MultiWriterIntegrationTest to
   match the more specific scope and the int main() was dropped
   because integration_tests/ links gtest_main, which provides main.

   tests/CMakeLists.txt drops the basic_integration_test target and
   its coverage registration entry; integration_tests/CMakeLists.txt
   already globs scenarios/*.cpp into the logger_integration_tests
   executable, so no wiring change is required there.

Refs: #630, audit DEV-08 (R-33)
Closes a subtask of #630.

* refactor(headers): clarify src/impl/ visibility (DEV-01)

Two clarifications under audit DEV-01 (R-03 internal-header
discipline):

1. Delete src/impl/filters/log_filter.h.
   The file was unreferenced dead code: zero callers in any header,
   source, test, example, or cmake list. The current public filter
   API lives at include/kcenon/logger/filters/log_filter.h
   (namespace kcenon::logger::filters) and offers a richer set of
   filter classes (level/regex/composite/function/field_*/category)
   that all production code already uses via filter_factory and the
   public include path. Removing the duplicate eliminates a confusing
   parallel definition and removes 216 lines of unreachable code.

2. Add an explicit @internal banner to src/impl/async/lockfree_queue.h.
   The header is included only from other src/impl/ headers
   (batch_processor.h, high_performance_async_writer.h) and is not
   installed. The audit flagged its placement as ambiguous; the
   comment makes the internal status unambiguous to future readers
   without changing the public API.

Refs: #630, audit DEV-01 (R-03)
Closes a subtask of #630.

* chore(cmake): remove unused logger_compatibility.cmake (146 lines, no callers)

The cmake/logger_compatibility.cmake module defines helper functions
(check_std_format, check_concepts, configure_logger_compatibility) but
is not include()d from anywhere in the repository: not from the root
CMakeLists.txt orchestration, not from any of the canonical 8 modules
(options/compiler/dependencies/warnings/targets/install/testing/
examples), not from tests/, integration_tests/, examples/, or
benchmarks/, not from the *.cmake.in config-package template. A
ripgrep across .cmake/.txt/.in/.cpp/.h returns only matches inside
the file itself.

The functionality the helpers provide (std::format detection, C++20
concepts gate) is already enforced by cmake/compiler.cmake +
project(... CXX) and the c++20 minimum, making the helpers redundant
even if they were re-wired today.

Removing the dead module shrinks cmake/ to its canonical-plus-helpers
inventory (8 canonical modules + UnifiedDependencies.cmake +
FetchBenchmark.cmake + the config-package template).

Found while reviewing #628 fallout for #630.

Refs: #630
Closes a subtask of #630.

* chore(release): verify SHA512 against actual archive (#634) (#635)

Add an independent SHA512 verification job to on-release-sync-registry.yml
that re-downloads the release archive from GitHub and recomputes its digest
after the reusable sync workflow completes. Provides repo-local
defense-in-depth on top of the verify step inside
kcenon/common_system/.github/workflows/sync-vcpkg-registry.yml that was
added in kcenon/common_system#676.

The job uses file-based hashing (curl -fsSL --retry 3 -o file, then
sha512sum file) rather than a pipe so a fetch failure cannot silently
produce the empty-input hash cf83e1357eefb8bdf... A minimum-size sanity
check rejects suspiciously small archives.

Closes #634

Part of kcenon/common_system#674.

* build(vcpkg): bump vcpkg-registry baseline to resolve common-system port-version 3 (#639)

The git registry baseline was pinned to 50d89f5b (2026-03-26), whose
baseline.json resolves kcenon-common-system v0.2.0 to port-version 0.
Port-version 0 carries a stale archive SHA512 (7385ba3a...) that no
longer matches the GitHub-served common_system v0.2.0 tarball
(ac458878...), breaking the os/compiler build matrix with an
"unexpected hash" download failure.

vcpkg-registry HEAD 1be52cbd already resolves common-system to
port-version 3, whose portfile SHA512 matches the current archive.
Bumping the baseline picks up the fixed port without any registry change.

Closes #638

* docs(features): document production feature matrix for logging integrations (#637)

* docs(features): add production feature matrix for logging integrations

logger_system의 통합/옵션 기능에 대한 production feature matrix를
docs/FEATURE_MATRIX.md (LOG-FEAT-003) 로 신규 작성한다.

- 13개 기능 행: async, thread_system, encryption, compression,
  structured logging, network writer, OTLP, monitoring, crash handler,
  file rotation, lock-free queue, built-in DI, external DI
- 각 행: CMake 옵션 / 기본값 / 필요 의존성 / vcpkg feature /
  production 지원 수준 / 검증 command
- CMakeLists.txt가 logger_features.cmake보다 먼저 처리되므로
  LOGGER_USE_ENCRYPTION 의 effective 기본값은 ON 임을 명시
- OpenSSL 3.0+ 요구 및 graceful fallback 동작 문서화
- README.md 및 docs/README.md registry 에 신규 문서 링크 추가

Part of #636

* docs: resolve duplicate doc_id LOG-GUID-018

docs/GETTING_STARTED.md 와 docs/guides/BEST_PRACTICES.md 가 동일
doc_id 'LOG-GUID-018' 을 가져 doc-audit 가 critical 로 보고했다.

docs/GETTING_STARTED.md 는 registry 에 미등록된 항목이므로
미사용 ID 'LOG-GUID-027' 로 교정하고 docs/README.md registry 에
등록한다. BEST_PRACTICES.md 의 LOG-GUID-018 은 유지한다.

Relates to #636

* docs(i18n): expand Korean README toward parity with English (#643)

* test(fuzz): add fuzz harness + weekly workflow; record test/CI inventory (DRAFT) (#644)

* test(fuzz): add writer/otlp fuzz harness and weekly workflow; docs: record test/CI inventory

Add a libFuzzer harness over the public log_entry parse/serialize
surface, gated behind BUILD_FUZZERS (clang -fsanitize=fuzzer,address)
so the default build is unaffected. Include seed corpus and a weekly
fuzzing workflow (schedule + workflow_dispatch) mirroring existing CI
conventions. Record a factual test/CI inventory under docs/ for audit
re-verification (issue #641).

* docs(test-inventory): correct inventory to match actual tree; clarify fuzz harness dependency

Rewrite docs/TEST_INVENTORY.md from verified git ls-files data: 67 tracked
tests/*.cpp and 6 integration_tests/*.cpp wired via cmake/testing.cmake, and
the 12 actual workflows with their real names, triggers, and cron schedules.
Clarify in the harness source and fuzz/README that log_entry.h transitively
includes common_system's logger_interface.h, so the target builds through CMake
(in CI) rather than standalone.

* docs(test-inventory): fix malformed table and use verified workflow facts

Replace the corrupted CI workflows table (which contained ~200 duplicated
fuzzing.yml rows from a generation error) with verified data read directly
from each workflow file: 13 tracked .yml workflows with their real names,
triggers, and cron schedules (benchmarks daily 0 2 * * *, cve-scan daily,
osv-scanner weekly 17 3 * * 0, sbom weekly 0 3 * * 0, fuzzing weekly
17 6 * * 1). Correct counts: 65 tracked tests/*.cpp, 6 integration_tests/*.cpp.

* chore: unify integration test location and relocate root test_backend (#645)

Consolidate cross-system integration tests under integration_tests/ and
move the stray root test_backend.cpp into the example tree.

- Relocate tests/integration/monitoring_integration_test.cpp to
  integration_tests/scenarios/ (gtest_main provides main(), so the local
  int main() is removed; picked up by the scenarios/*.cpp GLOB).
- Remove tests/integration/thread_system_integration_test.cpp: it only
  simulated threading and is superseded by the real
  integration_tests/scenarios/thread_system_integration_test.cpp, which
  exercises the thread_system_integration API.
- Drop the now-empty tests/integration/ directory and prune the dead
  add_executable/coverage wiring in tests/CMakeLists.txt.
- Relocate root test_backend.cpp to
  examples/backend_integration_example.cpp, wire it into BUILD_SAMPLES,
  disambiguate the log() overload call, and replace emoji output markers
  with plain text.

Part of #642

* chore(release): align residual version strings with v1.0.0 (Doxyfile) (#646)

* chore(ci): propagate cross-system conformance linter (advisory) (#649)

Copy the ecosystem conformance linter (scripts/conformance_lint.py) verbatim
from common_system and add an ADVISORY (warning-only) Conformance workflow, per
the gate-propagation epic kcenon/common_system#701. The linter checks the
ecosystem structural/metadata conventions (version 3-way match, examples/, fuzz/,
include/kcenon layout, no committed test artifacts, README.kr parity).

The workflow runs the linter but does not fail CI yet (wrapped to exit 0 with a
::warning::), so the repo is not red-walled while its deviations are remediated.
Flip to enforcing/required once green.

Part of kcenon/common_system#701
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant