Skip to content

feat: S08.03 slice 10 honest hostname (RFC 5424 §6.2.4 IP fallback) + NILVALUE PROCID#316

Merged
DavidCozens merged 4 commits into
mainfrom
feat/freertos-host-procid-fallback
May 10, 2026
Merged

feat: S08.03 slice 10 honest hostname (RFC 5424 §6.2.4 IP fallback) + NILVALUE PROCID#316
DavidCozens merged 4 commits into
mainfrom
feat/freertos-host-procid-fallback

Conversation

@DavidCozens

@DavidCozens DavidCozens commented May 10, 2026

Copy link
Copy Markdown
Owner

Purpose

Closes #315. Last slice of S08.03 (#268). Applies the slice-9 RFC-honest
reference-example pattern to HOSTNAME and PROCID — the post-merge audit
of slice 9 (#313) caught these as the same shape we'd just landed for
TIMESTAMP. The library already supports both via NULL-callback /
IP-stack introspection; only the example wiring and the BDD step
semantics change. Includes the slice-9 DEVLOG entry rebased onto this
branch (PR #314 was closed in favour of this).

Change Description

HOSTNAME — RFC 5424 §6.2.4 walk (Example/FreeRtos/SingleTask/main.c)

The §6.2.4 preference order is FQDN → static IP → hostname → dynamic IP → NILVALUE. The reference target has no FQDN (no DNS resolver), no
integrator-supplied hostname, and no DHCP, so rung 2 (static IP) is the
highest-preference value it can supply. GetHostname queries the IP
back from the running endpoint via FreeRTOS_GetEndPointConfiguration
and formats it with FreeRTOS_inet_ntoaTEST_IP_ADDRESS (the byte
array passed to FreeRTOS_FillEndPoint at boot) is the single source
of truth in C; no EXAMPLE_STATIC_IPV4_STR literal duplicating it.
The walk lives in a comment block that reads as a literal §6.2.4
checklist, so a future slice introducing DHCP or an integrator-hostname
hook can satisfy a different rung without touching the function shape.

PROCID — RFC 5424 §6.2.6 NILVALUE

config.getProcessId = NULL falls through to the library's
NilStringFunction (no-op write); FormatStringField then sees an
empty field and emits - on the wire
(Core/Source/SolidSyslog.c:320-336).
QEMU FreeRTOS has no process model, so this is the honest answer per
§6.2.6's "NILVALUE MAY be used when no value is provided".

Smart-step BDD pattern (Bdd/features/steps/syslog_steps.py)

Per design discussion: smart steps over a tag-split, since the same
wire field with the same RFC meaning resolves to different values per
runner. No new @hostname / @procid tag taxonomy — the existing
steps branch on context.target and assert the RFC-correct value:

  • step_check_system_hostnamesocket.gethostname() on
    linux/windows; EXAMPLE_FREERTOS_STATIC_IP = "10.0.2.15" on
    freertos. The Python-side constant mirrors TEST_IP_ADDRESS in the
    C example; that's the one irreducible spec/code mirror.
  • step_check_example_pid — spawned PID on linux/windows; ""
    (NILVALUE → empty after parsing) on freertos.
  • parse_syslog_ng_line — explicit PROCID=(\S*) capture so wire
    NILVALUE lands in context.fields["PROCID"] as "" rather than
    being silently dropped by the generic (\w+)=(\S+) regex.

Untag four scenarios

  • header_fields.feature: "Hostname matches the system hostname" and
    "Process ID matches the example program PID".
  • syslog.feature: "SolidSyslog sends a valid RFC 5424 message" —
    walking-skeleton end-to-end, asserts both fields.
  • message_fields.feature: "Complete RFC 5424 message with all
    fields" — also asserts both.

Note on the bundled scenarios' timestamp assertion

syslog.feature and message_fields.feature also assert "timestamp
within 5 seconds of now"
. On RTC runners (Linux/Windows), ${ISODATE}
faithfully reflects the wire timestamp from the message — honest test.
On FreeRTOS the wire is NILVALUE (slice 9), and syslog-ng substitutes
receipt time for ${ISODATE} — the assertion passes vacuously
("receipt time is within 5s of now" is tautological). This is the same
NILVALUE-substitution behaviour we explored in slice 9; preserving it
here is the right call because timestamp.feature is feature-level
@rtc (the dedicated RTC assertion), and the bundled scenarios'
timestamp step exists to prove the full RFC 5424 message round-trips,
not to gate timestamp correctness specifically.

Drop dead code

g_hostname global, g_processId global, OnSet "hostname" /
OnSet "procid" branches, and the now-unused GetProcessId callback
all gone. The interactive set hostname / set procid commands
disappear with them — the reference doesn't permit overriding fields
the device cannot honestly supply.

DEVLOG

Includes two cherry-picked commits from PR #314 (closed):

  1. The original slice-9 closure entry, verbatim.
  2. A ### Update — audit caught hostname/PROCID gap sub-section
    appended below it, noting epic S08.03: UDP syslog from FreeRTOS reaches the oracle #268 was reopened and recording
    the lesson — when introducing an "RFC explicit fallback rather
    than placeholder TEST value" pattern, audit all fields of
    similar shape before declaring the epic done.

Test Evidence

  • cmake --build --preset freertos-cross --target SolidSyslogFreeRtosSingleTask — clean.
  • behave --tags='not @wip and not @freertoswip and not @rtc and @udp' Bdd/features/
    inside freertos-target: 8 features / 24 scenarios pass, 0 fail, 25 skipped
    (up from 20 in slice 9; 4 newly-untagged scenarios all green).
  • behave --tags='not @wip and not @no_rtc' Bdd/features/header_fields.feature Bdd/features/syslog.feature Bdd/features/message_fields.feature for the Linux
    pair: 7 scenarios pass, 0 fail.
  • clang-format --dry-run --Werror on Core/Interface Core/Source Tests Example
    — clean.
  • Python syntax validated via py_compile on syslog_steps.py.

Areas Affected

  • Example/FreeRtos/SingleTask/main.c (Tier 3 — example): drops
    g_hostname, g_processId, GetProcessId, two OnSet branches;
    rewrites GetHostname to query the IP-stack; sets
    config.getProcessId = NULL.
  • Bdd/features/steps/syslog_steps.py: target-aware
    step_check_system_hostname / step_check_example_pid; explicit
    PROCID capture in parse_syslog_ng_line; new
    EXAMPLE_FREERTOS_STATIC_IP constant.
  • Bdd/features/{header_fields,syslog,message_fields}.feature: four
    @freertoswip tags removed.
  • DEVLOG.md: slice-9 closure entry + audit-correction sub-section.

No production library code changed. No CI tag-filter changes (smart
steps mean no new tags).

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • FreeRTOS example now correctly implements RFC 5424 hostname fallback behavior (derives hostname from configured IP address).
    • Improved PROCID field handling to properly distinguish between empty and absent values.
  • Chores

    • Pinned syslog-ng dependency to version 4.8.2.
  • Changes

    • FreeRTOS example app hostname and process ID are no longer interactively updateable; appname remains updateable.

Review Change Stack

DavidCozens and others added 3 commits May 10, 2026 10:28
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Same-day post-merge audit of the remaining @freertoswip tags showed
the slice 9 closure was premature: HOSTNAME (RFC 5424 §6.2.4 IP
fallback) and PROCID (§6.2.6 NILVALUE) follow the same RFC-honest
pattern as the no-RTC TIMESTAMP. Epic #268 reopened; slice 10
(#315) extends the pattern.

Append-only — preserves the slice 9 entry verbatim and adds the
correction as a sub-section so the temporal sequence is honest.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… NILVALUE PROCID on FreeRTOS

Closes #315. Last slice of S08.03 (#268).

Apply the slice-9 RFC-honest reference-example pattern to two more
fields. The library already supports both via NULL-callback / IP-stack
introspection; only the example wiring and the BDD step semantics change.

HOSTNAME — RFC 5424 §6.2.4 walk
  1. FQDN              — n/a (no DNS resolver)
  2. Static IP address — present (queried via FreeRTOS_GetEndPointConfiguration)  ← emit
  3. hostname          — n/a (no integrator-supplied hostname)
  4. Dynamic IP        — n/a (no DHCP)
  5. NILVALUE          — fallthrough
The example calls FreeRTOS_GetEndPointConfiguration + FreeRTOS_inet_ntoa
on the running endpoint, so TEST_IP_ADDRESS is the single source of truth
in C. No EXAMPLE_STATIC_IPV4_STR literal — the same byte array that
configures Plus-TCP at boot is read back at log-time.

PROCID — RFC 5424 §6.2.6 NILVALUE
config.getProcessId = NULL drops through NilStringFunction → empty
field → FormatStringField writes "-" on the wire (Core/Source/SolidSyslog.c).

BDD steps become target-aware
- step_check_system_hostname: gethostname() on linux/windows;
  EXAMPLE_FREERTOS_STATIC_IP="10.0.2.15" on freertos (Python-side
  spec value mirroring TEST_IP_ADDRESS).
- step_check_example_pid: spawned PID on linux/windows; "" (NILVALUE)
  on freertos.
- parse_syslog_ng_line: explicit `PROCID=(\S*)` capture so empty
  values land as "" instead of being silently dropped by the
  generic `(\w+)=(\S+)` regex.

Untag the four @freertoswip scenarios
- header_fields.feature: hostname + procid
- syslog.feature: walking skeleton (asserts both)
- message_fields.feature: complete RFC 5424 message (asserts both)

The walking-skeleton and complete-message scenarios also assert
"timestamp within 5 seconds of now"; on FreeRTOS this passes vacuously
because the wire is NILVALUE and syslog-ng's ${ISODATE} substitutes
receipt time. Honest on RTC runners; benign-but-vacuous on FreeRTOS.

Drop the now-unused g_hostname / g_processId globals, the OnSet
"hostname" / "procid" branches, and the GetProcessId callback
function. The corresponding `set` commands disappear from the
interactive shell — the FreeRTOS reference doesn't permit overriding
fields that the device cannot honestly supply.

FreeRTOS BDD: 20 → 24 scenarios green (no failures, 25 skipped).
Linux/Windows BDD: unchanged.

Epic #268 closes on this slice's merge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 10, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@DavidCozens has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 52 minutes and 44 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e5cfda78-bbb0-4e55-9089-fcb4d1285717

📥 Commits

Reviewing files that changed from the base of the PR and between d9cd8bf and f98beef.

📒 Files selected for processing (2)
  • Bdd/features/steps/syslog_steps.py
  • DEVLOG.md
📝 Walkthrough

Walkthrough

This PR implements RFC 5424 §6.2.4 fallback behavior for FreeRTOS HOSTNAME and PROCID fields. The FreeRTOS example now derives HOSTNAME from its configured static IP address and emits NILVALUE for PROCID via a NULL callback, replacing hardcoded placeholder test values. BDD tests are updated to assert these RFC-honest values, and @freertoswip skip tags are removed from four affected scenarios.

Changes

RFC 5424 honest hostname/PROCID fallbacks for FreeRTOS

Layer / File(s) Summary
Reference constants and field parsing
Bdd/features/steps/syslog_steps.py
Introduces EXAMPLE_FREERTOS_STATIC_IP constant set to "10.0.2.15" and updates parse_syslog_ng_line to explicitly capture empty PROCID values so NILVALUE cases are distinguishable from absent fields.
FreeRTOS example wiring
Example/FreeRtos/SingleTask/main.c
Adds FreeRTOS_Sockets.h header; GetHostname now derives the static IP from the FreeRTOS stack configuration and formats it as dotted-quad instead of using a mutable buffer; removes g_hostname and g_processId globals; OnSet command drops hostname and procid handlers; getProcessId callback is set to NULL to emit NILVALUE.
BDD assertion step updates
Bdd/features/steps/syslog_steps.py
HOSTNAME assertion now expects the configured static IP for FreeRTOS and socket.gethostname() for other targets. PROCID assertion expects empty string for FreeRTOS and the spawned example PID for other targets.
BDD scenario tag cleanup
Bdd/features/header_fields.feature, message_fields.feature, syslog.feature
Removes four @freertoswip skip tags from "Hostname matches the system hostname", "Process ID matches the example program PID", "Walking skeleton end-to-end", and "Complete RFC 5424 message with all fields" scenarios.
Documentation
DEVLOG.md
Records S08.03 slice 9 work (syslog-ng pin to 4.8.2, no-RTC timestamp wiring) and slice 10 epic reopen (audit finding that hostname/PROCID used placeholders instead of RFC fallback behavior) with planned NULL-callback implementation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • #315: This PR directly implements the full deliverables for slice 10—FreeRTOS hostname/PROCID wiring via static IP and NULL callback, BDD assertion updates, and @freertoswip tag removal.

Possibly related PRs

Poem

A FreeRTOS hop through RFC's halls, 🐰
No hostname ghost—just IP calls!
PROCID sleeps in NILVALUE's nest,
Honest fallbacks pass the test. ✓

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the primary changes: adding honest RFC 5424 §6.2.4 IP fallback for hostname and NILVALUE PROCID on FreeRTOS, matching the PR's main objectives.
Description check ✅ Passed The description follows the template structure with comprehensive Purpose, Change Description, Test Evidence, and Areas Affected sections that thoroughly explain design decisions, implementation details, and testing.
Linked Issues check ✅ Passed All coding requirements from issue #315 are met: RFC 5424 §6.2.4 HOSTNAME walk implemented with static IP fallback, PROCID set to NILVALUE via NULL callback, BDD steps made target-aware, and four scenarios untagged with RFC-correct assertions.
Out of Scope Changes check ✅ Passed All changes directly support the slice-10 objectives; DEVLOG documentation of slice-9 closure and audit findings is appropriate context; no unrelated features or exploratory code introduced.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/freertos-host-procid-fallback

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Bdd/features/steps/syslog_steps.py`:
- Around line 935-939: In the FreeRTOS branch (the block guarded by `if
context.target == "freertos"` in syslog_steps.py) assert that the "PROCID" key
is present in `context.fields` and then assert its value is the empty string;
replace the current `context.fields.get("PROCID", "")` usage with an explicit
presence check (e.g., `if "PROCID" not in context.fields: fail...`) followed by
`actual = context.fields["PROCID"]` and the existing empty-string assertion so
that missing vs present-but-empty are distinguished.

In `@DEVLOG.md`:
- Around line 5105-5110: Update the DEVLOG entry that currently states "Slice 10
(`#315`) is in flight" for Epic `#268` to record completion: change the wording to
indicate slice-10 has been merged (include the merge context PR `#316`) and, if
preferred, add a short follow-up entry noting that the slice-10 implementation
applies fallbacks and untags the four `@freertoswip` scenarios in
`header_fields.feature`, `syslog.feature`, and `message_fields.feature` while
library code remained unchanged (NULL-callback path continues to drive NILVALUE
TIMESTAMP/PROCID and HOSTNAME-IP fallback).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5736bf39-4de2-46b4-ab67-71a659643452

📥 Commits

Reviewing files that changed from the base of the PR and between 186c129 and d9cd8bf.

📒 Files selected for processing (6)
  • Bdd/features/header_fields.feature
  • Bdd/features/message_fields.feature
  • Bdd/features/steps/syslog_steps.py
  • Bdd/features/syslog.feature
  • DEVLOG.md
  • Example/FreeRtos/SingleTask/main.c
💤 Files with no reviewable changes (3)
  • Bdd/features/header_fields.feature
  • Bdd/features/syslog.feature
  • Bdd/features/message_fields.feature

Comment thread Bdd/features/steps/syslog_steps.py
Comment thread DEVLOG.md
@github-actions

Copy link
Copy Markdown
Contributor

☀️   Quality Summary

   🚦   build-linux-gcc: 100% successful (✔️ 1105 passed, 🙈 3 skipped)
   🚦   build-linux-clang: 100% successful (✔️ 1042 passed, 🙈 3 skipped)
   🚦   sanitize-linux-gcc: 100% successful (✔️ 1042 passed, 🙈 3 skipped)
   🚦   integration-linux-openssl: 100% successful (✔️ 9 passed)
   🚦   integration-windows-openssl: 100% successful (✔️ 9 passed)
   🚦   bdd-linux-syslog-ng: 94% successful (✔️ 46 passed, 🙈 3 skipped)
   🚦   bdd-windows-otel: 90% successful (✔️ 44 passed, 🙈 5 skipped)
   🚦   bdd-freertos-qemu: 49% successful (✔️ 24 passed, 🙈 25 skipped)
   🚦   build-windows-msvc: 100% successful (✔️ 954 passed, 🙈 1 skipped)
   ⚠️   Clang-Tidy: No warnings
   ⚠️   CPPCheck: No warnings


Created by Quality Monitor v1.14.0 (#f3859fd). More details are shown in the GitHub Checks Result.

… 10 DEVLOG entry

- syslog_steps.py: PROCID step now asserts presence-then-value (not
  .get(default)), so template-gap bugs can't masquerade as NILVALUE
  passes. The explicit `PROCID=(\S*)` parse already preserves the
  absent-vs-empty distinction; the step now honours it.
- DEVLOG.md: append the slice 10 closure entry alongside the slice 9
  one (both ride this PR rather than a follow-up). Records the DRY
  catch on the IP literal, the smart-step decision over a tag split,
  the bundled-scenario timestamp asymmetry, and the two process
  misses (network-namespace restart, clang-format-on-Python).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

☀️   Quality Summary

   🚦   build-linux-gcc: 100% successful (✔️ 1105 passed, 🙈 3 skipped)
   🚦   build-linux-clang: 100% successful (✔️ 1042 passed, 🙈 3 skipped)
   🚦   sanitize-linux-gcc: 100% successful (✔️ 1042 passed, 🙈 3 skipped)
   🚦   integration-linux-openssl: 100% successful (✔️ 9 passed)
   🚦   integration-windows-openssl: 100% successful (✔️ 9 passed)
   🚦   bdd-linux-syslog-ng: 94% successful (✔️ 46 passed, 🙈 3 skipped)
   🚦   bdd-windows-otel: 90% successful (✔️ 44 passed, 🙈 5 skipped)
   🚦   bdd-freertos-qemu: 49% successful (✔️ 24 passed, 🙈 25 skipped)
   🚦   build-windows-msvc: 100% successful (✔️ 954 passed, 🙈 1 skipped)
   ⚠️   Clang-Tidy: No warnings
   ⚠️   CPPCheck: No warnings


Created by Quality Monitor v1.14.0 (#f3859fd). More details are shown in the GitHub Checks Result.

@DavidCozens DavidCozens merged commit c9dcf02 into main May 10, 2026
19 checks passed
@DavidCozens DavidCozens deleted the feat/freertos-host-procid-fallback branch May 10, 2026 10:12
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.

S08.03 slice 10: honest hostname (RFC 5424 §6.2.4 IP fallback) + NILVALUE PROCID on FreeRTOS

1 participant