You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor: make command.Command valid-by-construction (#21)
## Summary
`command.Command` was `type Command string`, so its validity invariant —
leading slash, lowercase, no trailing slash — was **not enforced by the
type**. Three ways to hold an invalid command existed:
1. **Conversion** — `command.Command("FOO/")` is legal Go.
2. **Zero value** — `var c command.Command` is `""`, which `Parse`
itself rejects.
3. **Unvalidated decode** — the generated wire path did a raw
`command.Command(sval)` with no check.
This PR models `Command` on the existing `did.DID` precedent: a struct
with an unexported field, obtainable only through validating
constructors. Invalid commands become unrepresentable.
## What changed
- **`Command` is now `struct{ str string }`** (was `type Command
string`). Added `MustParse`, `Undef`, and `Defined()`, mirroring
`did.DID`.
- **Serialization methods**
(`MarshalCBOR`/`UnmarshalCBOR`/`MarshalDagJSON`/`UnmarshalDagJSON`/`MarshalJSON`/`UnmarshalJSON`)
copied from `did.DID`. cbor-gen now **delegates** to them (the
`(struct)` codegen path), and **decode validates** — a non-conforming
command from the wire is rejected instead of silently accepted.
- **Wire format unchanged.** A command still serializes as the same CBOR
text string; fixtures and test vectors round-trip byte-identically
(`delegation`/`invocation`/`container`/`receipt` tests stay green).
- Regenerated the invocation/delegation datamodels.
- `receipt.Command`: `const` → `var command.MustParse(...)` (can't
`const` a struct).
- `invocation.go`/`delegation.go`: `string(command)` →
`command.String()` at the re-parse boundary.
- Updated call sites to build commands via `MustParse`. The "bad
command" test now feeds `command.Undef` — the only error path still
reachable now that invalid commands can't be constructed.
- Added `command_test.go` (the package previously had **no tests**):
parse table, `MustParse`, CBOR/DAG-JSON round-trips, and the
decode-validation guarantees.
## Notes
- `New(segments...)` still trusts its caller's segments (like
`cid`/`did` builders) rather than validating, to avoid a breaking
signature change rippling into `bindcom`. The headline guarantee comes
from the struct itself.
- Independent of the in-flight `binding` work; this also makes a future
`binding.Of(cmd command.Command)` a safe, error-free primitive.
0 commit comments