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
This commit was created on GitHub.com and signed with GitHub’s verified signature.
Added
The generated Rust decoder of a newtype enforces what the newtype declares: its alphabet, its
prefix and its invariants. A value that breaks one is refused with the path and the constraint
(broken_constraint on the type), so a served route no longer admits it
(#579, decoder half). A constraint the emitter cannot check refuses the target by
name.
A suite can fix the instant a target reads as now for one command: the hold_now step
({step: hold_now, seconds: <n>}, suite ess-conformance/50, or /51 with coverage) stands
before the execute_command it holds and names a now_offset, so a value sent as a now_offset
can sit exactly on a now boundary. The runner holds its command clock at that instant, or asks
the target through the new optional ConformanceTarget::hold_now (the generated Go runtime's NowHolder, the TypeScript runtime's holdNow); a target without it reports the scenario unsupported, naming hold_now. A suite without the step keeps its format and
bytes (#586).
Synthesis adds one scenario on each now boundary a command decides by — an input guard, or a when_subject:/when_related: predicate over a stored field written from an input — with the
value sent exactly on the boundary and a hold_now 0 before the command under test, filed as <command>/outcome/<outcome>/held/<field>/<seconds>. A value is not moved onto a boundary across
another now boundary on the same field, so every other comparison, and every row set a
decision counts, stays as it was. The guard-boundary mutant (< to <=)
answers apart there, so a target that holds now kills it; the interpreted target of ess verify conform mutate is given no clock and reports it inconclusive, not survived.
A model with such a guard therefore gets a suite in ess-conformance/50 (/51 with coverage); its off-boundary scenarios keep their bytes, and a
target without hold_now reports only the new scenario unsupported, named and counted; unlike
any other unsupported scenario it does not fail the run, so a target that passed before keeps
its verdict and exit status in the Rust, Go and TypeScript runners
(#586).
The Rust spec-types crate a model realizes enforces a String newtype's alphabet and the text
length its value.count invariants bound. Such a type is still serialized as its plain string,
but its decoder refuses a value outside the alphabet or the length, naming the type's schema
pointer and the broken constraint (broken_constraint on the type). The types report no longer
lists model_alphabet as an obligation for it (#579, spec-types half). A newtype
that declares neither keeps its exact generated bytes.
The generated Go and TypeScript sequential explorers (Explore) draw a Timestamp input, as
the concurrent ones already did, and decide a guard over now against a clock, ExploreOptions.Now (TypeScript now), the wall clock by default. Where a guard compares a Timestamp with now, a drawn instant lies an hour to a day either side of an instant it
compares with, so a target reading its own clock decides the step as the model does, and a step
whose answer would still turn on when the target reads its clock is reported in Undetermined
rather than sent. Before, every command with a Timestamp input was excluded
(#582).
The sequential explorers perform an outcome that deletes: its supplied subject: the row leaves
the model, every view must lose it, and a later step may name the deleted identity, which the
model answers as an unknown instance, so a single-use resource is explored through its
redemption. Concurrent exploration still leaves such a command out and now says why: its
workload is drawn before any call runs, so a later call can name the deleted row
(#583).
Runtime format ess-runtime/2, compiled to ess-runtime-ir/2, beside /1. A workload may
declare schedule: (a cron expression, an optional IANA time_zone, overlap: forbid, replace
or allow, history limits, suspended, start and run deadlines, a retry limit and a restart
policy), and ess generate project helm renders it as a batch/v1CronJob whose job template
carries the pod a Deployment would, with a PersistentVolumeClaim per named volume that every
run mounts. A scheduled workload without run_deadline_seconds is refused as unbounded; an
invalid cron expression, an unknown time zone, replicas, legacy storage, a provided endpoint
or a readiness probe beside a schedule, a deadline below one and a negative retry limit are
refused naming the workload. Every workload kind also takes pod settings: container resources
(cpu and memory requests and limits) and read_only_root_filesystem, workload security
(run_as_user, run_as_group, fs_group, run_as_non_root) and service_account_token, a
secret slot mount: rendered as a read-only secret volume with items and an octal mode,
and a process image given as a reference pinned by digest, rendered verbatim. An ess-runtime/1 document keeps its compiled bytes, digest and chart, and refuses the new keys
naming ess-runtime/2 (docs/design/runtime-workload-kinds.md).
ess-runtime/2 containers take TCP probes (readiness_tcp_port, liveness_tcp_port, rendered as tcpSocket), and workloads take pod annotations and affinity (node_labels as required node
affinity, spread_across as pod anti-affinity against the workload's own pods, preferred unless spread: required). An ess-runtime/2 document is refused, naming the field, where the chart
would not install or not say what the document says: a day of week of 7, an int32 count or a
pod security id above 2147483647, a container, workload, volume or mounted secret slot whose pod
name is not a DNS-1123 label, a secret item key Kubernetes refuses or an item path starting with .., a request above its limit, and {{ in any string the chart renders as written, which Helm
would evaluate at install time. ess-runtime/1 documents compile as before.
Fixed
No generated document carries a $serde_json::private::Number map any more. In a build where
another crate turns on serde_json's arbitrary_precision, an Integer enum attribute was
published in x-ess-attributes as {"$serde_json::private::Number": "2"} instead of 2, in the OpenAPI and AsyncAPI documents and the /openapi.json a generated server serves. Every YAML
write now writes such a number as the number, as a build without the feature does, and a corpus
test pins every projection of every example to the bytes of a build without it
(#579).
Format ess/26: an external refusal (external: or external_when:) beside an existing-row
branch reads the addressed row back and requires it unchanged, so a witness of the refusal can
no longer pass while the command deletes or rewrites the row (#587). Models below ess/26
keep their suite bytes.
The caller-swapped half of a synthesized scenario draws fresh values for every input a when_related: guard, a row-set selector or its forall: test reads, and for every input
written into a field such a selector reads, whatever its type (#580). A key unique across
callers, such as a name refused when any row already holds it, no longer makes a correct model
fail its own suite on --target interpreted. Suites of models without such guards keep their
bytes.
Synthesis arranges a guarded stored value or a related row's state through the declared command
that reaches it: a when_subject: defined(field) branch whose field only a later updates:
writes, a when_related branch over an owned row moved to the state it reads, and a row-set
guard over the subject's owned rows in a moved state now get scenarios instead of ESS-SYNTH-003/ESS-SYNTH-001. A field written by another command's affects: is not yet
arranged (#553).
ess verify conform mutate scores a mutant whose synthesized suite asks what the baseline's
asks (the same scenarios and steps, digests aside) as unwitnessed (ESS-MUTATE-004, "the
suite does not change") rather than survived or inconclusive, so a survivor always has a
suite that differs and still passes. One is a precedence-swap of two refusals with the same
error whose payloads no scenario tells apart.
Such a report is ess-mutation-report/7, with unchanged_suite on the mutant; every other
report keeps its version and bytes (#586).
Changed
ess-deployment: Process::image is a ProcessImage, Workload::replicas an Option<u32>,
and SecretSlot::environment and SecretSlot::key are Option<String>, for ess-runtime/2; ContainerRole gains readiness_tcp_port and liveness_tcp_port, and Workload gains annotations and affinity (Affinity, Spread).