13 KiB
nenjim-journal-format Specification
Purpose
Defines the observable format-version-1 contract and immutable domain meaning of a complete, artifact-scoped Nenjim Journal snapshot.
Requirements
Requirement: Artifact-scoped complete snapshots
The Journal format SHALL describe exactly one artifact identified by the coordinate <GROUP>-<MODULE>-<ARTIFACT>, SHALL contain no JOURNAL_ID or artifact TYPE, and SHALL represent a complete immutable worldview rather than a delta from its predecessor.
Scenario: Valid artifact identity
- WHEN metadata contains non-empty
GROUP=com_r35157_nenjim,MODULE=hubd, andARTIFACT=api - THEN the parsed coordinate is
com_r35157_nenjim-hubd-api
Scenario: Obsolete identity fields
- WHEN a Journal contains
JOURNAL_IDorTYPE - THEN parsing fails as an unknown or misplaced field without silently ignoring it
Scenario: No-op semantic revision
- WHEN a later valid snapshot differs from its predecessor only by
JOURNAL_VERSIONandPREVIOUS_JOURNAL_DIGEST - THEN the snapshot remains valid because revisions are complete worldviews and need not change their semantic content
Requirement: Strict top-level structure and comments
The parser SHALL require the logical order FORMAT_VERSION=1, JOURNAL_VERSION, optional PREVIOUS_JOURNAL_DIGEST, [METADATA], optional [POLICY], and one or more [RELEASE <version>] sections. Blank lines and full-line or trailing # comments SHALL be accepted, except that a # inside a quoted value is data.
Scenario: Comments before format entry
- WHEN blank lines and full-line comments precede
FORMAT_VERSION=1 - THEN the format entry is treated as the first actual configuration entry and parsing proceeds
Scenario: Hash inside quoted text
- WHEN
DESCRIPTION='Project #1' # trailing commentis parsed - THEN the decoded description is
Project #1and the trailing comment is discarded
Scenario: Unsupported format
- WHEN the first actual entry is
FORMAT_VERSION=2 - THEN parsing fails explicitly because the format version is unsupported
Scenario: Misordered or duplicate structure
- WHEN a required entry or section is missing, duplicated, malformed, unknown, or placed outside its defined order
- THEN parsing fails and no unknown content is ignored
Requirement: Journal and publication timestamps
JOURNAL_VERSION and PUBLISHED_AT SHALL each use a strict UTC uuuuMMddHHmmssSSS'Z' timestamp with millisecond precision and SHALL retain distinct revision-time and release-time meanings.
Scenario: Valid timestamp
- WHEN
20260819121530842Zis supplied as a Journal or publication timestamp - THEN it is represented as the corresponding immutable UTC instant/value
Scenario: Invalid timestamp
- WHEN a timestamp has missing milliseconds, a non-UTC suffix, an impossible calendar value, or trailing characters
- THEN parsing fails
Requirement: Quoted metadata values
[METADATA] SHALL contain exactly one non-empty GROUP, MODULE, ARTIFACT, and single-quoted DESCRIPTION, and MAY contain at most one single-quoted INFORMATION_URI. The parser SHALL decode \' and \\, reject other malformed escaping and empty quoted values, and expose information URI as Optional<URI> only when the decoded value is a syntactically valid non-empty absolute URI, without restricting its scheme.
Scenario: Valid quoted metadata
- WHEN metadata contains
DESCRIPTION='Nenjim\'s reference hub'andINFORMATION_URI='ftp://ftp.domain.com/components/123.txt' - THEN the model exposes description
Nenjim's reference huband the exact absolute FTP URI
Scenario: Optional information URI absent
- WHEN valid metadata omits
INFORMATION_URI - THEN the model exposes an empty optional URI
Scenario: Scheme-independent URI
- WHEN a syntactically valid absolute
https:,ftp:, oripfs:URI is supplied - THEN parsing accepts it without fetching, opening, or scheme-specific interpretation
Scenario: Invalid metadata text or URI
- WHEN a required quoted value is unquoted, empty, unterminated, badly escaped, or the information URI is relative or syntactically invalid
- THEN parsing fails at that field
Requirement: Exact artifact releases and content
Every release section SHALL identify a unique exact major.minor.patch stable semantic version and SHALL contain exactly one non-empty quoted LICENSE, exactly one valid PUBLISHED_AT, one or more supported unique CONTENT_DIGEST values, and exactly one non-negative long CONTENT_SIZE.
Scenario: Valid release content
- WHEN release
1.0.3contains decoded license text, a valid publication timestamp, a SHA-256 digest, an optional CIDv1 digest, and a non-negative content size - THEN the immutable release model exposes all values without normalizing or interpreting the license
Scenario: Invalid release version
- WHEN a release heading uses
1,1.0,1.0.0-beta, or1.0.0+build.42 - THEN parsing fails rather than normalizing it to another exact release
Scenario: Duplicate release
- WHEN two release sections identify the same exact version
- THEN parsing fails
Scenario: Invalid license
- WHEN a release omits
LICENSE, repeats it, or supplies an unquoted, malformed, or empty value - THEN parsing fails
Scenario: Digest validation
- WHEN content digests use valid
sha256:<64 lowercase hexadecimal characters>and/orcid1:<CIDv1 base32 text>values whose payload is the exact canonical unpadded lowercase Base32 encoding of a valid CIDv1 envelope, with at most one digest of each scheme - THEN all supplied content identities remain inspectable in the release model
Scenario: Canonical CIDv1 envelope
- WHEN a CIDv1 content digest is supplied
- THEN its version, multicodec, multihash code, and digest-length fields use their shortest unsigned varint encoding within the supported
longrange, and the declared digest length matches the payload
Scenario: Non-canonical CIDv1
- WHEN a CIDv1 spelling has non-zero unused Base32 padding bits, a non-minimal varint, or a varint that overflows the supported
longrange in any envelope field - THEN parsing fails even if a permissive decoder could produce the same CID bytes or a truncated numeric value
Scenario: Invalid content identity
- WHEN no content digest exists, a digest scheme is unknown, a digest syntax is invalid, a scheme repeats, or content size is negative or outside the long range
- THEN parsing fails
Requirement: Normalized version expressions
The model SHALL distinguish exact artifact versions from partial version boundaries, normalize semantically equivalent selector syntax, support membership and set containment, and reject unsupported or empty expressions.
Scenario: Equivalent exact forms
- WHEN
1.0.3and[1.0.3]are parsed - THEN both produce the same exact version-expression representation
Scenario: Minor series
- WHEN
[1.0]is parsed - THEN it contains every stable
1.0.xrelease from1.0.0through the release immediately before1.1.0and is not normalized to exact1.0.0
Scenario: Inclusive and exclusive ranges
- WHEN
[1.0.3-->1.0.7]and[1.0.3-->1.0.7)are parsed - THEN the first contains both endpoints and the second excludes
1.0.7
Scenario: Partial range boundaries
- WHEN
[1.0-->1.2]or[1.0-->1.2)is parsed - THEN the inclusive form contains the entire
1.2.xseries and the exclusive form excludes the entire1.2.xseries
Scenario: Explicit cross-major range
- WHEN
[1.0-->3.0)is parsed - THEN it contains stable versions in major lines 1 and 2 but none in major line 3
Scenario: Open upper range
- WHEN
[1.0-->,(1.0-->, or[1.0.3-->is parsed - THEN its implicit exclusive upper boundary is
2.0.0, while its lower boundary respectively starts at1.0.0,1.1.0, or1.0.3
Scenario: Expression union
- WHEN
[1.0.0-->1.0.3], [1.0.7], 1.1.1is parsed for a repeatable/list-valued rule - THEN the model represents the normalized union and accepts whitespace around commas and
-->
Scenario: Invalid expression
- WHEN an expression uses a major-only boundary, a bare incomplete exact version, prerelease/build syntax, mathematical comparison syntax, whitespace inside a numeric version, an empty list element, reversed boundaries, or an empty range
- THEN parsing fails
Requirement: Nenjim dependencies
Each artifact release SHALL model each nenjim:<artifact-coordinate> dependency target with exactly one DEPENDS_ON base expression set, zero or more described EXCLUDES entries, and zero or more described PREFERRED entries. Unknown schemes SHALL fail explicitly, exclusions and preferences SHALL require a corresponding base dependency, and the complete preferred set SHALL be contained by DEPENDS_ON - EXCLUDES.
Scenario: Valid dependency relationship
- WHEN a release depends on
nenjim:com_r35157_nenjim-hubd-api=[1.0-->, excludes1.0.4with a description, and prefers1.0.3 - THEN the model preserves the target, base constraint, and individual described exclusion/preference rules
Scenario: Repeated exclusion and preference rules
- WHEN multiple
EXCLUDESorPREFERREDlines refer to one declared target - THEN their expression sets form unions while every line and optional description remains individually inspectable
Scenario: Duplicate base dependency
- WHEN the same dependency target has two
DEPENDS_ONentries - THEN parsing fails
Scenario: Orphan relationship rule
- WHEN an
EXCLUDESorPREFERREDtarget has no correspondingDEPENDS_ON - THEN parsing fails
Scenario: Invalid preferred subset
- WHEN any preferred version lies outside the base dependency set or inside an exclusion
- THEN parsing fails because preference cannot make an invalid version valid
Scenario: Unsupported dependency scheme
- WHEN a dependency uses
maven:or another unsupported scheme in format version 1 - THEN parsing fails clearly rather than ignoring or resolving it
Requirement: Artifact policy
An optional [POLICY] section SHALL preserve individual BLACKLIST, DISCOURAGED, and RECOMMENDED rules and descriptions. Blacklist SHALL be a hard constraint, discouraged and recommended SHALL be hints, overlaps SHALL be valid, and each recommended rule SHALL identify exactly one exact release present in the same snapshot. These recommendation invariants SHALL be enforced both while parsing and when the public model types are constructed directly without the parser.
Scenario: Valid overlapping policy
- WHEN a broad discouraged range overlaps a blacklisted exact release and an existing exact release is recommended
- THEN all individual rules and descriptions remain inspectable and the blacklist has the documented stronger meaning without flattening the rules
Scenario: Repeated policy entries
- WHEN policy contains several blacklist, discouraged, or recommended lines
- THEN all lines are retained as immutable individual rules
Scenario: Invalid recommendation
- WHEN
RECOMMENDEDcontains a non-exact range or identifies a release absent from the snapshot - THEN parsing fails
Scenario: Direct policy construction rejects a non-exact recommendation
- WHEN a caller constructs
JournalPolicydirectly with a recommended rule containing a range, a minor series, multiple versions, or any other non-exactVersionExpressionSet - THEN construction fails because one recommended rule must identify exactly one exact
major.minor.patchversion
Scenario: Direct Journal construction rejects an absent recommendation
- WHEN a caller constructs
Journaldirectly with an exact recommended version that is absent from that Journal's release map - THEN construction fails because recommendations refer only to releases in the same snapshot
Scenario: Direct construction preserves valid policy overlaps
- WHEN a caller constructs a Journal with an existing exact release recommended while that version also belongs to discouraged or blacklist rules
- THEN construction succeeds and all individual rules remain inspectable because overlaps are valid
Scenario: Optional description decoding
- WHEN a repeatable policy or dependency rule ends with
:'Known \'issue\' on C:\\tmp' - THEN its decoded non-empty description is
Known 'issue' on C:\tmp
Scenario: Invalid optional description
- WHEN an explicitly supplied description is empty, unquoted, unterminated, or has malformed escaping
- THEN parsing fails
Requirement: Complete diagnostics and immutable results
Parsing SHALL validate the entire document before it is accepted, SHALL report the known logical source, one-based line number, and reason for every parse failure, and SHALL return immutable defensively copied objects and collections without using null for optional values.
Scenario: Source-aware failure
- WHEN line 12 of logical source
example.journalcontains an invalid field - THEN the parse exception identifies
example.journal, line 12, and the validation reason
Scenario: Immutable model
- WHEN callers obtain metadata, releases, policies, dependencies, digests, or expression collections
- THEN callers cannot mutate the Journal snapshot through those returned values