diff --git a/.fusa-reqs.json b/.fusa-reqs.json index 294fbd7..2ce2a08 100644 --- a/.fusa-reqs.json +++ b/.fusa-reqs.json @@ -912,6 +912,16 @@ "verification": "test", "safety_goal": "SG-006", "asil": "ASIL-B" + }, + { + "id": "REQ-RELAY-097", + "title": "multi_protocol capabilities field tightens Requirements 1 and 6", + "text": "The capabilities document (spec \u00a712.2) MAY declare an OPTIONAL boolean multi_protocol field, defaulting to false when absent. relay conform MUST FAIL a capabilities document whose protocol is null unless multi_protocol is true (spec \u00a717 Requirement 1), and MUST FAIL a capabilities document whose adapt is false unless multi_protocol is true (spec \u00a717 Requirement 6) \u2014 replacing the prior WARN-only treatment of both cases. A capabilities document with multi_protocol:true MUST NOT produce any finding for either a null protocol or adapt:false.", + "category": "functional", + "criticality": "medium", + "verification": "test", + "safety_goal": "SG-006", + "asil": "ASIL-B" } ] } diff --git a/cmd/relay/conform.go b/cmd/relay/conform.go index 5454200..4af9d2f 100644 --- a/cmd/relay/conform.go +++ b/cmd/relay/conform.go @@ -264,7 +264,10 @@ func buildManifest(binary string) conformManifest { } req1 := statusPass - if hasFail(vFindings) { + // Requirement 1 (protocol declaration) spans both documents: spec_version + // shape (version doc) and the capabilities doc's own protocol-null check + // (§12.2, gated on multi_protocol — see validateCapabilitiesDoc). + if hasFail(vFindings) || hasFailWithReq(cFindings, "§12.2") { req1 = statusFail } req6 := statusPass @@ -318,6 +321,17 @@ func hasFail(fs []conformFinding) bool { return false } +// hasFailWithReq reports whether any finding in fs is FAIL-severity and cites +// req (spec section) exactly. +func hasFailWithReq(fs []conformFinding, req string) bool { + for _, f := range fs { + if f.Severity == sevFail && f.Req == req { + return true + } + } + return false +} + func printConformText(w io.Writer, cr conformResult) { for _, f := range cr.Findings { fmt.Fprintf(w, "%-4s %s %s\n", f.Severity, f.Req, f.Message) @@ -388,6 +402,7 @@ func validateVersionDoc(data []byte) []conformFinding { // //fusa:req REQ-RELAY-054 //fusa:req REQ-RELAY-048 +//fusa:req REQ-RELAY-097 func validateCapabilitiesDoc(data []byte) []conformFinding { doc, fs := schemaCheck("cli-capabilities", "§12.2", data) if doc == nil { @@ -410,9 +425,26 @@ func validateCapabilitiesDoc(data []byte) []conformFinding { } } - // adapt=false is valid (no Adapt() exported) but worth flagging (§10.3). + // multi_protocol (§12.2, §17 Requirements 1 and 6) self-declares that this + // binary is inherently multi-protocol tooling, not a single-protocol + // implementation. Absent/false is the default (single-protocol). + multiProtocol, _ := doc["multi_protocol"].(bool) + + // A null protocol/protocol_int is only legitimate for a self-declared + // multi-protocol tool (§10.3, §17 Requirement 1); otherwise it's a real gap. + if !multiProtocol && doc["protocol"] == nil { + fs = append(fs, fail("§12.2", "capabilities doc: protocol is null but multi_protocol is not true")) + } + + // adapt=false is only legitimate for a self-declared multi-protocol tool — + // §10.3 scopes Adapt() to protocol packages, so a multi-protocol aggregator + // has no per-protocol Adapt() to export (§17 Requirement 6). if adapt, ok := doc["adapt"].(bool); ok && !adapt { - fs = append(fs, warn("§17.6", "capabilities doc: adapt=false (Adapt() not exported)")) + if multiProtocol { + // Legitimate: no per-protocol Adapt() applies to this tool. + } else { + fs = append(fs, fail("§17.6", "capabilities doc: adapt=false (Adapt() not exported) but multi_protocol is not true")) + } } return fs diff --git a/cmd/relay/conform_test.go b/cmd/relay/conform_test.go index bcf223a..03c9911 100644 --- a/cmd/relay/conform_test.go +++ b/cmd/relay/conform_test.go @@ -88,8 +88,11 @@ func TestValidateVersionDocUnknownLanguage(t *testing.T) { //fusa:test REQ-RELAY-054 func TestValidateCapabilitiesDocValid(t *testing.T) { + // No protocol declared, so this fixture must self-declare multi_protocol: + // true (spec §12.2, §17 Requirement 1) to avoid the new protocol-null FAIL. data := []byte(`{ "kind":"capabilities","tool":"go-can","version":"1.0.0","spec_version":"0.2", + "multi_protocol":true, "commands":["version","capabilities","status"], "transports":[],"features":[],"interfaces":[],"optional_interfaces":[], "adapt":true @@ -163,29 +166,70 @@ func TestValidateCapabilitiesDocMissingCommand(t *testing.T) { } //fusa:test REQ-RELAY-054 -func TestValidateCapabilitiesDocAdaptWarn(t *testing.T) { +//fusa:test REQ-RELAY-097 +func TestValidateCapabilitiesDocAdaptFalseFails(t *testing.T) { + // A single-protocol implementation (multi_protocol absent/false) that + // exports no Adapt() MUST FAIL (spec §17 Requirement 6), not WARN. data := []byte(`{ - "kind":"capabilities","tool":"relay","version":"0.1.0","spec_version":"0.2", + "kind":"capabilities","tool":"go-can","protocol":"CAN","protocol_int":1, + "version":"0.1.0","spec_version":"0.2", "commands":["version","capabilities","status"], "transports":[],"features":[],"interfaces":[],"optional_interfaces":[], "adapt":false }`) fs := validateCapabilitiesDoc(data) - hasWarn := false hasFail := false for _, f := range fs { - if f.Severity == sevWarn && strings.Contains(f.Message, "adapt") { - hasWarn = true + if f.Severity == sevFail && strings.Contains(f.Message, "adapt") { + hasFail = true } - if f.Severity == sevFail { + } + if !hasFail { + t.Error("expected FAIL for adapt=false on a single-protocol tool, got none") + } +} + +//fusa:test REQ-RELAY-054 +//fusa:test REQ-RELAY-097 +func TestValidateCapabilitiesDocNullProtocolFails(t *testing.T) { + // A single-protocol implementation (multi_protocol absent/false) with a + // null protocol MUST FAIL (spec §17 Requirement 1), not WARN. + data := []byte(`{ + "kind":"capabilities","tool":"go-can","version":"0.1.0","spec_version":"0.2", + "commands":["version","capabilities","status"], + "transports":[],"features":[],"interfaces":[],"optional_interfaces":[], + "adapt":true + }`) + fs := validateCapabilitiesDoc(data) + hasFail := false + for _, f := range fs { + if f.Severity == sevFail && strings.Contains(f.Message, "protocol") { hasFail = true } } - if !hasWarn { - t.Error("expected WARN for adapt=false, got none") + if !hasFail { + t.Error("expected FAIL for null protocol on a single-protocol tool, got none") } - if hasFail { - t.Errorf("complete adapt=false doc should not FAIL: %+v", fs) +} + +//fusa:test REQ-RELAY-054 +//fusa:test REQ-RELAY-097 +func TestValidateCapabilitiesDocMultiProtocolExempt(t *testing.T) { + // multi_protocol:true legitimizes both a null protocol and adapt:false + // (spec §12.2, §17 Requirements 1 and 6) — RELAY's own reference CLI's + // exact shape. Neither MUST produce a finding at all, not even a WARN. + data := []byte(`{ + "kind":"capabilities","tool":"relay","multi_protocol":true, + "version":"0.1.0","spec_version":"0.2", + "commands":["version","capabilities","status"], + "transports":[],"features":[],"interfaces":[],"optional_interfaces":[], + "adapt":false + }`) + fs := validateCapabilitiesDoc(data) + for _, f := range fs { + if f.Severity != sevPass { + t.Errorf("multi_protocol:true doc must produce no FAIL/WARN for protocol/adapt, got %s %s: %s", f.Severity, f.Req, f.Message) + } } } diff --git a/cmd/relay/main.go b/cmd/relay/main.go index 9de88e8..6576fe9 100644 --- a/cmd/relay/main.go +++ b/cmd/relay/main.go @@ -18,7 +18,7 @@ import ( relay "github.com/SoundMatt/RELAY/v2" ) -const toolVersion = "2.4.0" +const toolVersion = "2.5.0" func main() { if err := run(os.Stdout, os.Stderr, os.Args[1:]); err != nil { @@ -141,13 +141,15 @@ func runVersion(w io.Writer, args []string) error { // runCapabilities implements `relay capabilities`. // RELAY is a multi-protocol spec and tooling layer, not a protocol implementation, -// so protocol and protocol_int are omitted and adapt is false. +// so protocol and protocol_int are omitted, adapt is false, and multi_protocol +// is declared true — legitimizing both per spec §12.2 / §17 Requirements 1 and 6. // //fusa:req REQ-RELAY-029 func runCapabilities(w io.Writer, _ []string) error { doc := struct { Kind string `json:"kind"` Tool string `json:"tool"` + MultiProtocol bool `json:"multi_protocol"` Version string `json:"version"` SpecVersion string `json:"spec_version"` Commands []string `json:"commands"` @@ -159,6 +161,7 @@ func runCapabilities(w io.Writer, _ []string) error { }{ Kind: "capabilities", Tool: "relay", + MultiProtocol: true, Version: toolVersion, SpecVersion: relay.SpecVersion, Commands: []string{"version", "capabilities", "status", "conform", "convert", "interop", "crossbar", "probe", "trace", "report", "sbom", "safety-case", "audit-pack", "compare", "versions", "serve"}, diff --git a/spec/CHANGELOG.md b/spec/CHANGELOG.md index 48f0d94..a6a60ce 100644 --- a/spec/CHANGELOG.md +++ b/spec/CHANGELOG.md @@ -1,5 +1,44 @@ # RELAY Spec Changelog +## v2.5 — 2026-08-21 (MINOR — new optional capabilities field, tightened §17 Requirements 1 and 6) + +- **New optional `multi_protocol` capabilities field (§12.2).** Defaults to + `false` when absent. A tool that self-declares `multi_protocol: true` + legitimately reports a null `protocol`/`protocol_int` and `adapt: false`: + §10.3 scopes the `Adapt()` contract to protocol packages, so a + multi-protocol aggregator (like RELAY's own reference CLI) has no single + protocol to declare or per-protocol adapter to export. +- **§17 Requirements 1 and 6 tightened from WARN to FAIL.** A null + `protocol`/`protocol_int`, or `adapt: false`, on a capabilities document + that does not declare `multi_protocol: true` is now a conformance FAIL, + closing a real audit-flagged gap (THEME-B, capabilities drifting silently + from the shipped binary) — previously both were only WARN, so an + implementation using `relay conform` without `--strict` never failed on + either. Both requirements move from "Partial" to "Full" black-box coverage + in the requirement-to-verifier table. +- **Scope decision**: the originating issue also proposed verifying every + declared `commands` string is actually invocable, and "exercising" every + declared `features` string with a CLI probe. Both are explicitly declined + in this release: there is no existing, spec-grounded signal distinct from + the generic "invalid arguments" exit code (§11.3) to detect an unrecognized + command across four languages' worth of implementations, and §12.2 already + states `features` are compiled-in and explicitly not runtime-probed. Adding + either would mean inventing an unproven new convention under this issue's + scope rather than tightening an existing one — deferred to a dedicated + follow-up. +- **Design note**: the naive implementation (blindly turning both WARN cases + into FAIL) would have broken RELAY's own reference CLI's passing + self-conformance CI job, which is deliberately, legitimately + multi-protocol and non-adapting. `multi_protocol` exists specifically to + let `relay conform`'s black-box CLI distinguish that legitimate case from + a genuine single-protocol implementation bug, which it previously could + not do at all. +- **Reference implementation**: `cmd/relay`'s own `capabilities` output now + declares `"multi_protocol": true`; `validateCapabilitiesDoc` in + `cmd/relay/conform.go` implements the gated FAIL logic for both fields. + New `REQ-RELAY-097`. `SpecVersion` bumped to `2.5`. Closes [NEW-SPEC-3] + (partial — commands-invocability and feature-probing deferred). + ## v2.4 — 2026-08-21 (MINOR — new §17 conformance requirement) - **New §17 Requirement 16 — Vector manifest.** The canonical diff --git a/spec/relay-spec.md b/spec/relay-spec.md index 34f96f7..8ef0e0a 100644 --- a/spec/relay-spec.md +++ b/spec/relay-spec.md @@ -1,4 +1,4 @@ -# RELAY Specification — v2.4 +# RELAY Specification — v2.5 **Real-time Embedded Link Abstraction Yoke** @@ -1182,7 +1182,7 @@ failure rather than a skip. Exit: `0` all equivalent, `1` any mismatch/error, "protocol": "CAN", "protocol_int": 1, "version": "1.2.3", - "spec_version": "2.4", + "spec_version": "2.5", "language": "go", "runtime": "go1.25.0", "commit": "a1b2c3d4" @@ -1207,7 +1207,7 @@ conformance failure, but §17.2's conformance manifest cannot populate its own "protocol": "CAN", "protocol_int": 1, "version": "1.2.3", - "spec_version": "2.4", + "spec_version": "2.5", "commands": ["version", "capabilities", "status", "connect", "send", "subscribe"], "transports": ["socketcan", "virtual"], "features": ["fd", "isotp", "j1939"], @@ -1219,6 +1219,34 @@ conformance failure, but §17.2's conformance manifest cannot populate its own `adapt` MUST be `true` if the package exports `Adapt()` per §10.3. +`multi_protocol` (OPTIONAL, boolean, defaults to `false` when absent) self-declares +that this binary is inherently multi-protocol tooling — a spec/tooling layer like +RELAY's own reference CLI, not a single-protocol implementation. A tool that sets +`multi_protocol: true` legitimately reports a null `protocol`/`protocol_int` and +`adapt: false`: §10.3 scopes the `Adapt()` contract to *protocol packages*, and a +multi-protocol aggregator has no single protocol to declare or adapt. For a +single-protocol implementation (the default, `multi_protocol` absent or `false`), +both remain governed by §17 Requirements 1 and 6 as MUSTs. Example, RELAY's own +CLI: + +```json +{ + "kind": "capabilities", + "tool": "relay", + "protocol": null, + "protocol_int": null, + "multi_protocol": true, + "version": "2.5.0", + "spec_version": "2.5", + "commands": ["version", "capabilities", "status", "conform", "convert", "..."], + "transports": [], + "features": [], + "interfaces": [], + "optional_interfaces": [], + "adapt": false +} +``` + `features` lists protocol-specific capability strings compiled into the binary. Values are set at build time — they are not runtime-probed. Unknown strings MUST be ignored by `relay conform`. Defined values per protocol: @@ -1278,7 +1306,7 @@ $ go-can version --format json "protocol": "CAN", "protocol_int": 1, "version": "1.2.3", - "spec_version": "2.4", + "spec_version": "2.5", "language": "go", "runtime": "go1.25.0" } @@ -1290,7 +1318,7 @@ $ go-can capabilities "protocol": "CAN", "protocol_int": 1, "version": "1.2.3", - "spec_version": "2.4", + "spec_version": "2.5", "commands": ["version", "capabilities", "status", "connect", "send", "subscribe"], "transports": ["socketcan", "virtual"], "features": ["fd", "isotp", "j1939"], @@ -1366,11 +1394,11 @@ LABEL org.opencontainers.image.licenses="MPL-2.0" LABEL io.relay.tool="" LABEL io.relay.language="go|cpp|rust|c" LABEL io.relay.binary="" -LABEL io.relay.spec-version="2.4" +LABEL io.relay.spec-version="2.5" ``` The `io.relay.spec-version` label MUST always match the value of `SpecVersion` -exported by the package (§17.12 / §19.4). The `"2.4"` shown above is an example; +exported by the package (§17.12 / §19.4). The `"2.5"` shown above is an example; update it on each spec minor release. The project directory is mounted at `/project` by convention: @@ -2191,12 +2219,12 @@ section and remains a separate, unpinned concern. An implementation is **RELAY-conformant** if and only if: -1. **Protocol declaration.** Capabilities document (§12.2) declares a protocol from §3 and a `spec_version`. +1. **Protocol declaration.** Capabilities document (§12.2) declares a protocol from §3 and a `spec_version`. A null `protocol`/`protocol_int` is a conformance failure unless the capabilities document declares `"multi_protocol": true`. 2. **Protocol interfaces.** All mandatory interfaces from §8 are implemented with exact method signatures. 3. **Error sentinels.** All four sentinels in §5.1 are defined; protocol-specific errors wrap them per §5.2. 4. **Lifecycle invariants.** All ten requirements in §6 are satisfied. Requirement §6.9 (zero-value safety) applies to `relay.Node` and `relay.Caller` adapters only, not to the underlying protocol interface types (`Bus`, `Participant`, etc.). 5. **Constructor contract.** Each transport sub-package exports `New` per §7; a `mock` sub-package is present. -6. **Application interface.** The root package exports `Adapt()` per §10.3; the capabilities document declares `"adapt": true`. +6. **Application interface.** The root package exports `Adapt()` per §10.3; the capabilities document declares `"adapt": true`. `"adapt": false` is a conformance failure unless the capabilities document declares `"multi_protocol": true` — §10.3 scopes `Adapt()` to protocol packages, so a self-declared multi-protocol aggregator has no per-protocol `Adapt()` to export. 7. **CLI mandatory commands.** `version`, `capabilities`, `status` per §11.1 with JSON schemas matching §12. **Every** implementation MUST provide these commands as a runnable CLI. A C++ (or other) library that does not ship a standalone binary by default MUST still expose them through a CLI target built with `-DRELAY_BUILD_CLI=ON` (or the language's equivalent build option). There is **no waiver**: an implementation that provides no conformance CLI cannot be verified by `relay conform` (§20) and is therefore not RELAY-conformant. *(Prior to v1.11 a C++ library with no CLI target had its CLI requirements assessed as "not applicable". That waiver is removed: every conformant C++ implementation already ships a CLI via the build option, so the accommodation was obsolete and conflicted with the §20 continuous-conformance gates.)* 8. **Frame constraints.** `ValidateFrame` rejects all frames violating §15 constraints. 9. **Envelope conversion.** `ToMessage()` and `FromMessage()` are lossless for mandatory fields. @@ -2219,14 +2247,14 @@ requirement list: - **Requirement 7** (CLI mandatory commands) is fully verified: all three commands run and their JSON output is schema-validated against §12. -- **Requirement 1** (protocol declaration) is partially verified: `spec_version` - presence is always schema-checked; `protocol` is schema-checked when present, - but its absence is only a WARN (multi-protocol tooling may legitimately omit - it). -- **Requirement 6** (`Adapt()`/`"adapt": true`) is partially verified: the - `capabilities` document's `adapt` field is checked, but `adapt: false` is - only a WARN, not a FAIL — `relay conform` does not currently treat exporting - `Adapt()` as strictly mandatory. +- **Requirement 1** (protocol declaration) is fully verified: `spec_version` + presence is always schema-checked, and the capabilities document's `protocol` + MUST be present unless `"multi_protocol": true` is declared, in which case + its absence is legitimate and produces no finding at all. +- **Requirement 6** (`Adapt()`/`"adapt": true`) is fully verified: the + `capabilities` document's `adapt` field MUST be `true` unless + `"multi_protocol": true` is declared, in which case `adapt: false` is + legitimate and produces no finding at all. - **Requirement 12** (`SpecVersion` constant) is shape-checked only: the `spec_version` field's presence and string format are validated, but whether it genuinely equals the implementation's compiled-in constant cannot be @@ -2268,12 +2296,12 @@ into one place: | # | Requirement | Verified by | Coverage | |---|---|---|---| -| 1 | Protocol declaration | `relay conform` (capabilities schema check) | Partial — `spec_version` always checked; `protocol` absence is WARN only | +| 1 | Protocol declaration | `relay conform` (capabilities schema check) | Full — `spec_version` always checked; `protocol` absence FAILs unless `multi_protocol: true` | | 2 | Protocol interfaces | Implementation's own test suite | Not observable through the CLI | | 3 | Error sentinels | Implementation's own test suite | Not observable through the CLI | | 4 | Lifecycle invariants | Implementation's own test suite | Not observable through the CLI | | 5 | Constructor contract | Implementation's own test suite | Not observable through the CLI | -| 6 | Application interface | `relay conform` (capabilities `adapt` field) | Partial — `adapt: false` is WARN, not FAIL | +| 6 | Application interface | `relay conform` (capabilities `adapt` field) | Full — `adapt: false` FAILs unless `multi_protocol: true` | | 7 | CLI mandatory commands | `relay conform` (`version`/`capabilities`/`status` schema validation) | Full | | 8 | Frame constraints | Implementation's own test suite | Not observable through the CLI | | 9 | Envelope conversion | Implementation's own test suite | Not observable through the CLI | @@ -2337,7 +2365,7 @@ diffable artifact. "manifest_version": "relay-conform/1", "tool": "go-can", "binary_version": "1.2.3", - "spec_version": "2.4", + "spec_version": "2.5", "git_sha": "a1b2c3d4", "capabilities_sha256": "e3b0c44298fc1c14...", "requirements": [ @@ -3086,11 +3114,11 @@ clarifications and fixes in PATCH releases. `spec/version.json` is authoritative. The spec document title is informational. -Current version: **v2.4** +Current version: **v2.5** -**Go:** `const SpecVersion = "2.4"` (update in implementations targeting v2.4) -**C++:** `constexpr std::string_view kRelaySpecVersion = "2.4";` -**Rust:** `pub const RELAY_SPEC_VERSION: &str = "2.4";` +**Go:** `const SpecVersion = "2.5"` (update in implementations targeting v2.5) +**C++:** `constexpr std::string_view kRelaySpecVersion = "2.5";` +**Rust:** `pub const RELAY_SPEC_VERSION: &str = "2.5";` --- @@ -3310,15 +3338,16 @@ second protocol implementation present. **9. Wire up CI and check conformance.** `relay conform ` (§17's own black-box-coverage discussion) is a **black-box** check: it validates the CLI JSON -schemas and Conformance Requirement 7 fully, and partially checks Requirements -1, 6, and 12 — it structurally cannot see Requirements 2-5, 8-11 (the +schemas and Conformance Requirements 1, 6, and 7 fully, and partially checks +Requirement 12 — it structurally cannot see Requirements 2-5, 8-11 (the interface, sentinel, lifecycle, constructor, and frame-constraint rules from steps 2-5 above), which the implementation's own test suite must verify -instead. §20.1 lists the three CI gates a conformant implementation's default +instead. §20.1 lists the five CI gates a conformant implementation's default branch and every PR MUST run and fail on: `relay conform --strict`, the language's full x-FuSa lifecycle (100% requirement traceability, not just an -ERROR-severity gate), and — once `convert` exists — `relay interop` reporting -EQUIVALENT for every golden vector. A green run of all three, on a release +ERROR-severity gate), — once `convert` exists — `relay interop` reporting +EQUIVALENT for every golden vector, the conformance manifest (§17.2), and the +vector manifest (§15.8). A green run of all five, on a release commit, is what §17's conformance definition and §20's continuous-conformance requirement together mean by "conformant": not "was conformant once," but "is conformant on every commit that ships." diff --git a/spec/schemas/cli-capabilities.json b/spec/schemas/cli-capabilities.json index cddff8a..70662da 100644 --- a/spec/schemas/cli-capabilities.json +++ b/spec/schemas/cli-capabilities.json @@ -23,6 +23,10 @@ "minimum": 0, "description": "Protocol integer constant matching relay.Protocol. Present for single-protocol implementations; null or omitted for multi-protocol tooling (spec §12.2)." }, + "multi_protocol": { + "type": "boolean", + "description": "OPTIONAL, defaults to false when absent. True self-declares that this binary is inherently multi-protocol tooling (not a single-protocol implementation), legitimizing a null protocol/protocol_int and adapt:false without either being a conformance FAIL (spec §12.2, §17 Requirements 1 and 6)." + }, "version": { "type": "string", "description": "Semantic version of the binary." diff --git a/spec/version.json b/spec/version.json index 8344447..7dc3f4f 100644 --- a/spec/version.json +++ b/spec/version.json @@ -1,5 +1,5 @@ { - "version": "2.4", + "version": "2.5", "date": "2026-08-21", "status": "stable", "networks": [ diff --git a/version.go b/version.go index d0a8763..0f4a3c7 100644 --- a/version.go +++ b/version.go @@ -8,4 +8,4 @@ package relay // Every RELAY-conformant implementation must export this constant (spec §17 req 12). // //fusa:req REQ-RELAY-020 -const SpecVersion = "2.4" +const SpecVersion = "2.5" diff --git a/version_test.go b/version_test.go index 13ef38d..cfd2224 100644 --- a/version_test.go +++ b/version_test.go @@ -8,7 +8,7 @@ import "testing" //fusa:test REQ-RELAY-020 func TestSpecVersion(t *testing.T) { - if SpecVersion != "2.4" { - t.Errorf("SpecVersion = %q, want %q", SpecVersion, "2.4") + if SpecVersion != "2.5" { + t.Errorf("SpecVersion = %q, want %q", SpecVersion, "2.5") } }