Skip to content

OAS v0.20.1

Choose a tag to compare

@github-actions github-actions released this 25 Aug 19:24
· 29 commits to main since this release
a9ceeaf

OAS v0.20.1

OAS v0.20.1 is a corrective release for the v0.20.0 capability-materialization
line. The framework release includes @oas-framework/oas@0.20.1,
@oas-framework/pi@0.20.1, and OAS Desktop 0.20.1. There are no new features;
the changes are the three corrections below and the hardening they forced.

Doctor recognizes revised-v2 capability locks

oas doctor no longer reports installed capabilities from a canonical
revised-v2 lock as orphans. The orphan check is scope-exact: a capability row
is judged against the lock of the scope that installed it, reading the
revised-v2 capabilities table directly instead of inferring provenance from
package rows. Legacy v1 locks keep their previous diagnostic behavior.

Own-property config handling and __proto__ rejection

Config parsing and diagnostics no longer consult inherited Object.prototype
properties anywhere: key dispatch, capability binding, command-owner lookup,
and shape validation are own-property. YAML keys named __proto__ are refused
with the typed failure unsafe-config-key. Internal engine annotations
(underscore keys such as _capabilityLock) are stripped from every manifest
and soul reader, so on-disk files cannot impersonate engine state.

Configless oas use states the real problem

Running oas use in a scope with no config chain now fails with the typed
error E_NO_CONFIG and prints a deterministic remedy — initialize the scope
with oas init --raw --dir <dir> — instead of the misleading acquired: none
report. OAS does not author adopter policy: the remedy initializes an empty
config; adopting a package profile remains an explicit separate step.

Config writes fail closed

Text that would change the shape of a written config is now refused with
typed failures instead of being written:

  • unsafe-config-value — values containing line breaks (including U+2028,
    U+2029, and U+0085, which earlier releases wrote and then silently dropped
    on read), embedded " #" (which opens a trailing comment), empty values,
    and leading YAML structure indicators.
  • unsafe-config-key — keys and --soul/--type names carrying :, #,
    or __proto__.

This includes the scaffolded name: line: oas init, and the first
oas use/oas type add in a fresh scope, now refuse to run in a directory
whose basename cannot be stored as one YAML scalar — for example a name
beginning with @, #, or a flow bracket, or containing " #" or a line
break. The refusal names the offending basename and writes nothing. This is a
deliberate behavior change: earlier releases wrote such names verbatim, and a
basename containing a line break could inject top-level config blocks.

Untrusted text (directory names, $HOME) is never used as a regex
replacement string, so names containing $&-style sequences are stored and
reported literally.

Desktop parity with the kernel

The OAS Desktop deployment reader now reads revised-v2 capability locks (it
previously rejected them) and matches the kernel's judgments: it refuses
every lock shape the kernel refuses (path canonical form, source grammar,
duplicate dependencies), and its legacy-v1 artifact digest now counts .git
and nested lock files exactly as the kernel does — a payload planted in a
v1-locked artifact after locking is integrity drift in the app, not an
invisible exclusion.

Compatibility

  • New typed failures: E_NO_CONFIG (configless oas use),
    unsafe-config-key, unsafe-config-value. Scripts matching error text
    should match the typed codes.
  • oas init and first-write commands refuse directory basenames that cannot
    be stored as one YAML scalar (see above).
  • No lockfile, manifest, or CLI-surface changes otherwise; v0.20.0 locks and
    configs are unaffected.

See the package engine contract for
the typed-failure table.