Skip to content

chore(release): verify SHA512 against actual archive (Part of #674)#676

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

chore(release): verify SHA512 against actual archive (Part of #674)#676
kcenon merged 1 commit into
developfrom
chore/issue-675-verify-sha512-archive

Conversation

@kcenon

@kcenon kcenon commented May 3, 2026

Copy link
Copy Markdown
Owner

Closes #675

Part of #674.

What

Adds an independent SHA512 verification step to .github/workflows/sync-vcpkg-registry.yml that re-downloads the release archive from GitHub and compares the recomputed digest against the value the workflow is about to write to portfile.cmake. On mismatch, the step prints both SHAs and exits 1 before any registry commit happens.

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-common-system/portfile.cmake does not match the bytes at https://github.com/kcenon/common_system/archive/refs/tags/v<version>.tar.gz. This PR closes the detection gap for common_system.

Where

File Change
.github/workflows/sync-vcpkg-registry.yml New step Verify SHA512 against actual GitHub archive inserted between the existing sha step (id: sha) and Update portfile.cmake with new SHA512 and REF

Audit summary (other workflows considered)

Workflow Touches portfile SHA? Action
sync-vcpkg-registry.yml Yes (computes steps.sha.outputs.sha512, writes to portfile) Hardened (this PR)
release.yml No (build/test/GitHub Release only) No change needed
release-template.yml No (reusable build/test template) No change needed
on-release-sync-registry.yml No (thin caller of sync-vcpkg-registry.yml) Inherits hardening automatically
port-sync-check.yml Compares git-blob SHAs for drift detection, not archive SHA512 Out of scope

Only sync-vcpkg-registry.yml actually computes a SHA512, so an inline step in that single workflow is more appropriate than extracting a composite action.

How

The new step runs immediately after the existing Download release archive and compute SHA512 step and before Update portfile.cmake with new SHA512 and REF. 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.... The exit-1 error message includes both the workflow-computed SHA and the archive's actual SHA so debug logs are immediately useful.

Runtime: ~1-2s on a typical common_system archive (~200 KB).

Test Plan

How a reviewer can validate the new step fires

  1. Cut a release tag (v0.x.y) - the existing Sync Registry on Release workflow triggers sync-vcpkg-registry.yml
  2. Inspect the run log for the new step Verify SHA512 against actual GitHub archive. On a healthy release, the step prints:
    Re-fetching https://github.com/kcenon/common_system/archive/refs/tags/v0.x.y.tar.gz for independent verification...
    SHA512 verified against https://github.com/kcenon/common_system/archive/refs/tags/v0.x.y.tar.gz
      <128-char hex digest>
    

How to simulate a mismatch

Locally executed and confirmed before push:

  • Match path (real v0.2.0 archive, real workflow-computed SHA): step exits 0, prints verification line.
  • Mismatch path (real archive SHA, workflow SHA replaced with all-zero digest): step exits 1 with annotations SHA512 mismatch detected for v0.2.0 / Workflow computed: 000... / GitHub archive: ac4588... / Refusing to commit a portfile that would not install.
  • Bad URL path (nonexistent tag v999.999.999): 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.

YAML structure validated with js-yaml; step ordering confirmed (Verify is step 5 of 12, after sha and before portfile update).

Breaking Changes

None. The new step is additive; on a successful release it adds ~1-2s and one log line. On a SHA mismatch (the failure mode this PR is designed to detect) it short-circuits the existing run before any vcpkg-registry commit, which is the desired behavior.

Add an independent SHA512 verification step in sync-vcpkg-registry.yml
that re-downloads the release archive from GitHub and compares the
recomputed SHA against the value the workflow is about to write to
portfile.cmake. On mismatch the step prints both SHAs and exits 1
before any registry commit happens.

Mitigates the failure mode found in microsoft/vcpkg#51511 and
kcenon/vcpkg-registry#87, where every kcenon port shipped a SHA that
did not match the actual archive and cold-cache vcpkg installs failed.

The audit confirmed sync-vcpkg-registry.yml is the only workflow in
this repo that computes SHA512; release.yml and release-template.yml
build/test/publish but do not write portfile SHAs, so no changes were
needed there. on-release-sync-registry.yml is a thin caller that
inherits the new step automatically.

Implementation notes:
- New step runs between 'Download release archive and compute SHA512'
  (id: sha) and 'Update portfile.cmake with new SHA512 and REF', so a
  mismatch fails the run before any portfile mutation
- Downloads to a file (not pipe) so curl's --fail exit code is not
  masked by sha512sum producing the empty-input hash on fetch error
- curl uses --retry 3 --retry-delay 2 for transient network blips
- Runtime cost ~1-2s for a kcenon archive

Part of #674.
@kcenon kcenon merged commit c90d4b8 into develop May 3, 2026
7 checks passed
@kcenon kcenon deleted the chore/issue-675-verify-sha512-archive branch May 3, 2026 12:37
kcenon added a commit to kcenon/logger_system that referenced this pull request May 3, 2026
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 added a commit to kcenon/database_system that referenced this pull request May 3, 2026
Add a defense-in-depth pre-verification job to on-release-sync-registry.yml
that downloads the published GitHub release archive and computes its SHA512
before delegating to the shared sync workflow that writes the SHA into
portfile.cmake.

The downstream reusable workflow
(kcenon/common_system/.github/workflows/sync-vcpkg-registry.yml) was hardened
in kcenon/common_system#676 to compare its computed SHA against the actual
archive. This change adds an independent check in this repo so a release
that produces an unfetchable or empty archive fails fast in this repo's
release run, with a clear log line, before the sync workflow ever runs.

The check uses file-based hashing (curl -fsSL --retry 3 ... -o tmpfile)
rather than piping curl into sha512sum, so a fetch failure cannot silently
produce the empty-input SHA512 (cf83e1357eefb8bdf...). The empty-input
hash is also explicitly rejected as a final safety net.

Audit:
  - on-release-sync-registry.yml: thin caller of common_system reusable
    workflow; this PR adds an independent pre-verification job here.
  - release.yml: builds and publishes platform artifacts, no SHA write.
  - vcpkg-overlay.yml: local overlay-port build/test, no SHA write.
  - All other workflows (ci, sanitizers, coverage, integration, etc.):
    no portfile SHA computation.

Closes #588
Part of kcenon/common_system#674
kcenon added a commit that referenced this pull request Jun 19, 2026
* docs: apply mechanical doc-review fixes (#642)

* chore(release): prepare common_system for v1.0.0

- Bump version from 0.2.0 to 1.0.0 in VERSION and vcpkg.json
- Move CHANGELOG [Unreleased] entries to [1.0.0] release section
- Add API stability guarantee documentation to README (EN/KR)
- Add v1.0 API stability milestone section to VERSIONING.md
- Update typed_error_code documentation to reflect stable naming
- Update FetchContent example tags to v1.0.0

Closes #640

* fix(vcpkg): update SHA512 hash for v0.2.0 source tarball

GitHub regenerated the v0.2.0 tarball with a different hash,
causing vcpkg install to fail on Windows CI (no binary cache hit).

* docs: fix 31 broken links, 4 version drifts, 12 cross-references

- Fix intra-file anchor slugs (ADAPTER_GUIDE adaptert, API_REFERENCE
  resultt-pattern-recommended, DEPENDENCY_MATRIX trailing hyphen,
  GUIDE_TEMPLATE step titles).
- Fix inter-file paths after guides/ and advanced/ reorganization:
  ARCHITECTURE, MIGRATION, STRUCTURE, INTEGRATION, INTEGRATION_POLICY,
  QUICK_START, BEST_PRACTICES, CONTRIBUTING, README.kr, templates.
- Align versions to vcpkg.json and CMakeLists.txt: gtest 1.17.0,
  benchmark 1.9.5, CMake 3.20+ (3.28+ for modules).
- Update 2025 copyright to 2026 in RELEASING.md and CONTRIBUTING.md
  sample snippets.
- Align ERROR_CODES "Last Updated" with frontmatter doc_date.
- Mark missing Korean counterparts and missing targets
  (NEED_TO_FIX.md, OPTIMIZATION.md, result_pattern.md etc.) with
  HTML TODO comments so broken links are traceable.
- Fix README quick links to existing CONTRIBUTING headings.
- Add current-as-of date to RUST_PARITY.md.
- Track review history by including DOC_REVIEW_REPORT.md.

* docs: add post-fix re-validation report

* docs(modules): document dual-build strategy for C++20 modules (#648)

Add docs/guides/CXX20_MODULES.md covering:
- When to use header-only vs module builds
- Compiler/CMake/generator compatibility matrix
- Fallback behavior when toolchain lacks module support
- Known limitations (Apple Clang, sanitizers, generators)
- Consuming the module target from downstream projects

Link the new guide from README.md documentation table.

Closes #644

* docs(release): document automated portfile SHA512 sync flow (#649)

Document the existing vcpkg-registry sync automation in docs/RELEASING.md so
release engineers understand that SHA512 hashes and port files are updated
automatically on GitHub release publish. Adds a new section covering:

- Trigger workflow (on-release-sync-registry.yml)
- Reusable sync workflow (sync-vcpkg-registry.yml)
- Prerequisites (VCPKG_REGISTRY_PAT secret)
- Verification commands
- How downstream ecosystem repos reuse the workflow

Closes #643

* docs(readme): link C++20 Modules guide from content section (#650)

The README reference table already links docs/guides/CXX20_MODULES.md, but the
'C++20 Modules' usage section did not. Add a direct link so readers looking at
the usage example can discover the full dual-build strategy, toolchain matrix,
and fallback behavior without scrolling to the reference table.

Closes #644

* docs(compliance): add ISO_OVERVIEW.md ecosystem summary (#654)

Closes #651

- Add docs/compliance/ISO_OVERVIEW.md — single navigable index of every
  ISO standard the kcenon ecosystem touches (14882, 27001, 20000-1, 8601,
  9075, 12052, 27799), with per-standard summaries, status (Enforced,
  Documented, Implemented, Planned), and links to per-system mapping docs.
- Link logger_system's ISO 27001 mapping as the first Documented entry.
- Add README Compliance section and TOC entry.
- Document operator responsibilities that cannot be satisfied by libraries
  alone (key rotation, retention policy, incident response, training).

Part of #645 (ecosystem-wide ISO compliance EPIC).

* docs(ecosystem): document version pins in ECOSYSTEM_OVERVIEW.md (#655)

Closes #652

- Add Versions section to docs/ECOSYSTEM_OVERVIEW.md covering all 8 kcenon
  vcpkg ports with current version, tier classification, and kcenon
  dependencies.
- Pin baseline SHA to b3fe244d03 (2026-04-10) and reference
  versions/baseline.json as the authoritative source.
- Include reproducible vcpkg-configuration.json snippet so downstream
  consumers can lock to the tested ecosystem composition.
- Document how versions advance (release.yml + sync-vcpkg-registry.yml)
  so pinned consumers know when and how to advance their baseline.
- Add README Ecosystem Version Baseline subsection linking to the
  Versions anchor.

Part of #646 (Ecosystem-wide vcpkg distribution readiness EPIC).

* docs(layout): add kcenon-system-layout.md v1.0 (#663)

Publish v1.0 of the canonical directory-structure standard for the
kcenon ecosystem (8 systems: common, thread, logger, container,
monitoring, database, network, pacs).

The document specifies:
- include/kcenon/<name>/ public header path with kcenon:: namespace
- src/ implementation layout, header-source separation
- tests/ (GTest unit) and integration_tests/ split
- 8-module cmake/*.cmake decomposition (extracted from pacs_system)
- forwarding-header policy for breaking moves
- documented exceptions (pacs_system Catch2 retention)

Refs #658
Part of #656

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

Add a short Layout Standard subsection under Architecture pointing to
docs/kcenon-system-layout.md so the ecosystem-wide layout standard is
discoverable from the project entry point.

Closes #662

* chore(cmake): extract kcenon-cmake-template from pacs_system (#665)

* chore(cmake): add kcenon-cmake-template suite

Extract pacs_system's modular CMake decomposition into a reusable,
project-agnostic template under cmake/template/. The template defines the
canonical eight-module layout described in docs/kcenon-system-layout.md
and is owned by common_system as the foundation tier.

Modules
  options.cmake       Standard option set + export-bridge / register helpers
  compiler.cmake      C++ standard, build type, IDE compile-commands baseline
  dependencies.cmake  find_package CONFIG/MODULE fallback, Homebrew probing
  warnings.cmake      Per-target warning flags scoped to project targets only
  targets.cmake       Include-directory and ALIAS conventions
  install.cmake       One-call install + config-package generation
  testing.cmake       enable_testing(), GTest discovery, gtest helper
  examples.cmake      Option-gated add_subdirectory + helper

The template is consumed by adding cmake/template to CMAKE_MODULE_PATH and
calling kcenon_template_*() helpers from the consuming root CMakeLists.txt.
README documents the adoption checklist, required variables, and the SemVer
version policy tracked in cmake/template/VERSION.

Part of #656.
Closes #659.

* chore(cmake): adopt kcenon-cmake-template in common_system root

Refactor the root CMakeLists.txt to consume the template suite added in
the previous commit. common_system serves as the reference adopter for
the other seven kcenon ecosystem systems.

Adoption details
  * Add cmake/template to CMAKE_MODULE_PATH and include() all eight modules
  * kcenon_template_set_cpp_baseline / set_default_build_type / enable_compile_commands
    replace the inline CMAKE_CXX_STANDARD / build-type plumbing
  * kcenon_template_define_standard_options(COMMON) defines the canonical
    BUILD_TESTS / BUILD_EXAMPLES / BUILD_BENCHMARKS / BUILD_DOCS /
    BUILD_MODULES / WARNINGS_AS_ERRORS options. COMMON_BUILD_EXAMPLES is
    pre-set to ON via cache to preserve common_system's historical default.
  * kcenon_template_install_package consolidates install(TARGETS),
    configure_package_config_file, write_basic_package_version_file,
    install(EXPORT), install(FILES), and the build-tree export() into a
    single call.
  * kcenon_template_setup_testing wraps enable_testing + GTest discovery.
    Caller still owns the unit / integration test combination logic.
  * kcenon_template_create_aliases factors out the three historical
    namespaced ALIAS targets (kcenon::common, kcenon::common_system,
    common_system::common_system).

Preserved unchanged
  * VERSION file reading and project() declaration
  * features.cmake (KCENON_WITH_* feature flags) and
    KcenonCompilerRequirements.cmake — domain-specific kcenon helpers, not
    part of the build-infrastructure template
  * Event Bus ABI configure_file plumbing (abi_version.h / .cpp generation)
  * BUILD_INTEGRATION_TESTS umbrella flag handling
  * COMMON_HEADER_ONLY and the optional static-library variant
  * COMMON_BUILD_MODULES C++20 module support block
  * BUILD_WITH_YAML_CPP optional dependency block
  * COMMON_BUILD_DOCS Doxygen target
  * ENABLE_COVERAGE flag handling
  * Configuration summary print

Net change: 270-line root CMakeLists.txt down to ~280 lines including
adoption boilerplate and section headers. The reduction is offset by
clearer section separation and helper call sites that document intent.

Part of #656.
Closes #659.

* ci(infra): add ecosystem cross-build workflow (#666)

Validates that structural changes to common_system (cmake/, include/) do not
silently break sibling consumers. Each of the 7 sibling systems is fetched at
its default branch and rebuilt against the PR's common_system in dependency
order:

  Tier 0: common_system  (this PR — header-only install)
  Tier 1: thread_system, container_system, database_system
  Tier 2: logger_system  (needs thread), network_system (needs thread)
  Tier 3: monitoring_system  (needs logger + network)
  Tier 4: pacs_system    (needs monitoring + container + database)

Per-tier install trees pass downstream via upload-artifact / download-artifact
so each sibling configures against the PR-built upstream chain rather than
released vcpkg ports. This complements ecosystem-vcpkg-integration.yml (which
validates released ports) by catching path renames, removed exports, and
CMake config changes pre-merge.

Triggers: push/PR to develop+main paths cmake/, include/, CMakeLists.txt,
CMakePresets.json, this workflow file. Also workflow_dispatch (with
sibling_ref input) and repository_dispatch type ecosystem-structural-change
so siblings can request a re-validation.

Escape hatch: PR label skip-cross-build short-circuits the matrix; the
rationale must be documented in the PR body when used.

Initial-rollout caveats:
- ubuntu-24.04 only; macOS to be added once cycle time is measured.
- database_system and pacs_system jobs are advisory (continue-on-error)
  until libpq/sqlite/DCMTK are reliably available in the runner image —
  both still emit logs and aggregate into the summary.

Layout doc cross-build CI section now points at the workflow file path
instead of the placeholder linking issue #660.

Refs #660

* docs(layout): document cmake/template/ exception (#672)

Add an Exceptions entry permitting common_system to keep its canonical
cmake modules under cmake/template/, enabling the template to be
version-tracked and copied verbatim by downstream systems. Bump the
standard version from v1.0 to v1.1 (additive convention, SemVer MINOR).

This amendment formalizes the deviation surfaced by DEV-01 in the
Phase 7 audit (#661) and preserves the obligation that all other
systems place their copied modules directly under cmake/.

Closes #671.

* chore(cmake): post-audit corrective patches for #661 deviations (#670) (#673)

* chore(integration_tests): replace file(GLOB) with explicit source lists

Replaces four file(GLOB) calls in integration_tests/CMakeLists.txt with
explicit set(...) lists, satisfying layout standard rule R-19 (no
file(GLOB) for source discovery). Existing sources under scenarios/,
failures/, performance/, and stress/ are enumerated. Behavior is
unchanged because the previous globs already resolved to these files.

Closes part of #670 (DEV-03).

* chore(tests): drop improved_ prefix from test filenames

Renames tests/improved_result_test.cpp -> tests/result_test.cpp and
tests/improved_event_bus_test.cpp -> tests/event_bus_test.cpp to satisfy
layout standard rule R-33 (<unit>_test.cpp). The improved_ prefix was
historical, used to distinguish a revised test suite from an older
baseline that has since been superseded and removed.

Updates:
- tests/CMakeLists.txt source list
- docs/TRACEABILITY.md feature mapping
- @file doc comments inside the renamed files

Closes part of #670 (DEV-04).

* chore(cmake): remove redundant enable_testing() in test subdirs

Removes enable_testing() calls from tests/CMakeLists.txt and
integration_tests/CMakeLists.txt. The root CMakeLists.txt already
invokes kcenon_template_setup_testing() which calls enable_testing()
at the root scope. Subdirectory calls are redundant and would limit
CTest discovery scope when invoked from there.

Satisfies layout standard rule R-34.

Closes part of #670 (DEV-05).

* refactor(cmake): extract project-specific logic into common-*.cmake modules

Refactors the root CMakeLists.txt from 364 LOC of mixed orchestration
and inline target/install/extras logic into a thin orchestrator (110
LOC) plus seven project-specific cmake modules under cmake/. This
satisfies layout standard rule R-17 (root CMakeLists.txt MUST be a
thin orchestrator).

New modules (each carries the canonical Responsibility / Required
input / Side effects header block):

- cmake/common-abi.cmake      ABI version configure_file generation +
                              umbrella BUILD_INTEGRATION_TESTS forwarding
- cmake/common-targets.cmake  INTERFACE library, aliases, optional
                              static variant, optional yaml-cpp support
- cmake/common-modules.cmake  Optional C++20 named-modules build
- cmake/common-install.cmake  Header + package install rules
- cmake/common-tests.cmake    tests/ + integration_tests/ subdir wiring
- cmake/common-extras.cmake   examples / benchmarks / Doxygen / coverage
- cmake/common-summary.cmake  Configuration summary block

The root file now appends both cmake/template (template owner exception
per SA-01 amendment) and cmake (project-specific layer) to
CMAKE_MODULE_PATH, then includes the eight canonical template modules
followed by the seven common-* project modules in dependency order.

Behavior is unchanged. Targets, options, install rules, and configure
output are byte-identical to the previous root CMakeLists.txt.

Closes part of #670 (DEV-02).

* chore(release): add SHA512 verify-against-archive step (#675) (#676)

Add an independent SHA512 verification step in sync-vcpkg-registry.yml
that re-downloads the release archive from GitHub and compares the
recomputed SHA against the value the workflow is about to write to
portfile.cmake. On mismatch the step prints both SHAs and exits 1
before any registry commit happens.

Mitigates the failure mode found in microsoft/vcpkg#51511 and
kcenon/vcpkg-registry#87, where every kcenon port shipped a SHA that
did not match the actual archive and cold-cache vcpkg installs failed.

The audit confirmed sync-vcpkg-registry.yml is the only workflow in
this repo that computes SHA512; release.yml and release-template.yml
build/test/publish but do not write portfile SHAs, so no changes were
needed there. on-release-sync-registry.yml is a thin caller that
inherits the new step automatically.

Implementation notes:
- New step runs between 'Download release archive and compute SHA512'
  (id: sha) and 'Update portfile.cmake with new SHA512 and REF', so a
  mismatch fails the run before any portfile mutation
- Downloads to a file (not pipe) so curl's --fail exit code is not
  masked by sha512sum producing the empty-input hash on fetch error
- curl uses --retry 3 --retry-delay 2 for transient network blips
- Runtime cost ~1-2s for a kcenon archive

Part of #674.

* feat(cmake/template): add BUILD_INTERFACE-only include helper (#677)

Add kcenon_template_add_build_interface_includes(<target> <visibility>
<dir>...) to cmake/template/targets.cmake. The helper wraps the common
pattern of attaching one or more $<BUILD_INTERFACE:...>-only include
directories to a target.

Use this when an include directory must be visible during the build but
should NOT be exported via INSTALL_INTERFACE (e.g., build-only test
fixtures, generated code that should not be installed). The existing
kcenon_template_setup_target_includes always pairs BUILD_INTERFACE with
INSTALL_INTERFACE, so it cannot serve this case.

Promoting this helper to the template lets pacs_system delete its local
inline equivalent (pacs_add_build_interface_include_dirs in
cmake/options.cmake) and aligns other ecosystem systems on the same
name.

Bump template VERSION 1.0.0 -> 1.1.0 (MINOR per template versioning
policy: new helper added). Update template README.md adoption checklist
with a usage example for the new helper.

Closes #667

* feat(cmake/template): add shared build-summary helper (#680)

Promote the build-configuration summary block (previously a pacs-only
helper) into the canonical template suite. The new
`kcenon_template_print_summary()` function accepts PROJECT, optional
VERSION/BANNER, and OPTIONS/TARGETS/DEPENDENCIES lists, replacing the
ad-hoc `message(STATUS ...)` blocks each system maintained at the end
of its root CMakeLists.txt.

common_system itself is migrated to use the new helper as the reference
adopter, replacing the inline summary in cmake/common-summary.cmake.
Template VERSION bumped 1.1.0 -> 1.2.0 (MINOR: new module added).

Closes #668

* feat(cmake/template): add safety.cmake with forbid-in-release helper (#681)

Add the new `cmake/template/safety.cmake` module that hosts defensive
build-config guards. The first helper,
`kcenon_template_forbid_in_release(<flag_var> [REASON <text>])`, encodes
the "prohibit a mock-only flag in Release builds" idiom previously
re-implemented inline by individual systems (e.g. pacs_system's
`PACS_USE_MOCK_S3` guard in `cmake/options.cmake`).

The helper is multi-config-aware: on multi-config generators (Visual
Studio, Xcode, Ninja Multi-Config) `CMAKE_BUILD_TYPE` is empty at
configure time because the build type is selected per-build, so the
configure-time check is skipped. Per-config enforcement on multi-config
generators must be expressed as a generator-expression guard at the
call site if required.

Updates:
- New `cmake/template/safety.cmake` (single helper, include_guard GLOBAL).
- Template `README.md` directory layout, adoption checklist (now 10
  modules, new `include(safety)` step), and a new "Safety helpers"
  section documenting the helper signature, multi-config behaviour, and
  the optional REASON argument.
- Reference adopter `CMakeLists.txt` includes the new module.
- Template VERSION bumped 1.2.0 -> 1.3.0 (MINOR per template versioning
  policy: new module added).
- CHANGELOG entry under [Unreleased] / Added.

Closes #669

* chore(release): sync Doxyfile/CLAUDE version metadata with VERSION (#691)

* docs: add Result/event_bus consolidation roadmap; ci: surface macOS module-build skip (#695)

Add ADR-004 documenting the dual representation of Result<T> and event_bus
(classic headers under include/kcenon/common/ as the SSOT vs the C++20
named-module units under src/modules/ that re-export them) and a phased
consolidation roadmap with risks and a decoupled deprecation sequence.

Surface the macOS module-build coverage gap explicitly: add a dedicated
module-build-coverage job in ci.yml that emits a GitHub Actions warning
annotation stating the C++20 named-modules surface is not exercised on
macOS/AppleClang (which is omitted from the module-build matrix), and
correct the misleading "silently disabled with a warning" comment in
cmake/common-modules.cmake. Documentation/visibility only; no change to
which toolchains build modules and no source consolidation.

* test(fuzz): add foundation fuzz harness and weekly workflow; docs: reconcile coverage claim with gate (#692)

* chore(ci): consolidate Doxygen workflows; mark governance SSOT (DRAFT) (#694)

* chore(ci): consolidate Doxygen workflows; docs: mark governance SSOT

Make the reusable/caller relationship between the twin Doxygen
workflows explicit and mark a single source of truth for the root
vs docs governance files.

- doxygen.yml: document it as the canonical reusable (workflow_call)
  build/deploy workflow; build-Doxygen.yaml: document it as the thin
  event caller. No behavior change; clarifies role separation so the
  two files are not mistaken for duplicate twins.
- CONTRIBUTING.md (root): add SSOT marker designating
  docs/contributing/CONTRIBUTING.md (COM-PROJ-017) as canonical and
  this file as a brief quick-start redirect.
- CHANGELOG.md (root): add SSOT marker (canonical English changelog;
  Korean at docs/CHANGELOG.kr.md; registry mirror at docs/CHANGELOG.md
  COM-PROJ-002).
- README.md: point the Contributing doc-table link at the canonical
  docs/contributing/CONTRIBUTING.md for consistency.

doc-audit workflows are role-separated (PR-gate vs scheduled ecosystem
scan), not duplicates; left unchanged.

Closes #689

* docs: repoint README Contributing doc-table link to canonical docs/contributing/CONTRIBUTING.md

* chore(ci): add cross-system conformance linter and CI gate (#693)

* fix(error): classify positive codes as Invalid not Success (#703)

get_category_name reported any code>=0 as "Success", so positive codes
emitted into the shared error_info.code (monitoring 1000-4999 via
to_common_error, container 100+) were silently classified as success.
Only the success sentinel (0) now maps to "Success"; positive
out-of-range codes map to "Invalid". The negative-range category ladder
is unchanged.

Closes #698

* feat(error): gate error-code registry SSOT (header <-> module) (#704)

error.cppm re-declared the registry inline and had drifted from
error_codes.h: it was missing the 6 DI error codes and still used the
pre-#698 classifier (code>=0 -> "Success"). Reconcile the module to the
header SSOT, add a std-lib Python guard
(scripts/check_error_registry_ssot.py) that fails CI on any header/module
divergence, wire it into conformance.yml, and add a runtime contract test
locking the classifier behaviour and disjoint reserved ranges.

Closes #699

* docs(deps): fix dangling FetchContent tag; refresh DEPENDENCY_MATRIX (#705)

README FetchContent example pointed at GIT_TAG v1.0.0, a tag that does
not exist (highest is v0.2.0). Refresh DEPENDENCY_MATRIX third-party rows
(OpenSSL 3.4.1, spdlog 1.15.3, gRPC 1.60.0, Protobuf 4.25.1, OTel 1.18.0,
libpqxx 7.9.2) and the internal ecosystem pins (thread/container/database
now v1.0.0-tagged; others at their real pre-1.0 tags) to match current
vcpkg.json and git tags; redate the footers.

Closes #702

* fix(error): remove exported using-directive (#706)

C++20 forbids exporting a using-directive; clang-16 promotes
-Wexport-using-directive to an error under -Werror, breaking the
Module Build (ubuntu-22.04 / clang-16). The directive only re-exported
the lowercase common_errors names, which no ecosystem consumer uses
(all reference the uppercase compatibility aliases), so this is
behavior-preserving dead-code removal.

* chore: reconcile develop with main (Dependabot CI-action bumps #678, #683) (#707)

* build(deps): bump dawidd6/action-download-artifact from 20 to 21 (#678)

Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 20 to 21.
- [Release notes](https://github.com/dawidd6/action-download-artifact/releases)
- [Commits](dawidd6/action-download-artifact@v20...v21)

---
updated-dependencies:
- dependency-name: dawidd6/action-download-artifact
  dependency-version: '21'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump google/osv-scanner-action from 2.3.5 to 2.3.8 (#683)

Bumps [google/osv-scanner-action](https://github.com/google/osv-scanner-action) from 2.3.5 to 2.3.8.
- [Release notes](https://github.com/google/osv-scanner-action/releases)
- [Commits](google/osv-scanner-action@v2.3.5...v2.3.8)

---
updated-dependencies:
- dependency-name: google/osv-scanner-action
  dependency-version: 2.3.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
kcenon added a commit to kcenon/logger_system 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