diff --git a/.gitignore b/.gitignore index e04a3f2..fed34d6 100644 --- a/.gitignore +++ b/.gitignore @@ -82,4 +82,4 @@ !/.agents !/.agents/** -!/.agents/**/* \ No newline at end of file +!/.agents/**/* diff --git a/AGENTS.md b/AGENTS.md index 5c04148..26491e8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -5,3 +5,6 @@ tags: [agents, instructions, repository, coding-conventions] --- See [BUILDING.md](./BUILDING.md) for coding rules and conventions. + +Agent skills live in [.agents/skills/](./.agents/skills/). Each skill's +`SKILL.md` front-matter describes when to use it. diff --git a/BUILDING.md b/BUILDING.md index 73263c8..4100dde 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -66,16 +66,16 @@ which Docker can't build for. ## Markdown front-matter -Every `.md` file requires frontmatter with `title`, `summary`, and `tags` — +Every `.md` file requires front-matter with `title`, `summary`, and `tags` — makes docs easy to index for agents. Exception: the root `README.md`, which -doesn't need frontmatter. Module `README.md` files do need it — see +doesn't need front-matter. Module `README.md` files do need it — see [Module README](./docs/README.md#readme-readmemd). ## Agents Don't commit AI agent config that's exclusive to a single agent (Claude-only, -Codex-only, etc.) — it lives in the dev's own environment. Config meant to -work across agents may be committed. +Codex-only, etc.) — it lives in the dev's own environment. Config meant to work +across agents may be committed. ## Code standards diff --git a/README.md b/README.md index d7d395e..91a6a6e 100644 --- a/README.md +++ b/README.md @@ -2,24 +2,24 @@ Kraf is a neutral layer for humans and autonomous agents, designed to provide a consistent way to work with software projects across tools, environments, and -vendors — without vendor lock-in. The goal is to start a development -environment with the least possible friction, and fast. +vendors — without vendor lock-in. The goal is to start a development environment +with the least possible friction, and fast. ## Summary Kraf explores a portable, vendor-neutral foundation for developer and agent -environments. Rather than replacing the tools, configuration files, or -workflows a project already uses, Kraf resolves them into an environment -plan, then materializes it wherever it's needed — a local shell today; CI, -containers, or an airgapped agent later. Materialization targets change; -the resolved plan doesn't. +environments. Rather than replacing the tools, configuration files, or workflows +a project already uses, Kraf resolves them into an environment plan, then +materializes it wherever it's needed — a local shell today; CI, containers, or +an airgapped agent later. Materialization targets change; the resolved plan +doesn't. Kraf's guiding rule: **materialize only what the workload proves it needs.** -The project is currently under active development. Its first working slice -is environment variable resolution and isolation — an isolated `HOME` and -working directory per run, real system state passed through deliberately -rather than by accident — materialized into a shell you can use today. +The project is currently under active development. Its first working slice is +environment variable resolution and isolation — an isolated `HOME` and working +directory per run, real system state passed through deliberately rather than by +accident — materialized into a shell you can use today. ## Contributing diff --git a/docs/README.md b/docs/README.md index 835e109..95ba247 100644 --- a/docs/README.md +++ b/docs/README.md @@ -27,9 +27,9 @@ Documentation lives with the feature it describes. Never in root /docs / └── docs/ ├── -intent.md - └── / - ├── .spec.md - └── .acceptance.md + └── -/ + ├── -.spec.md + └── -.acceptance.md ``` Documentation does not need to map one-to-one to source files, platform files, @@ -95,12 +95,17 @@ tags: [, , ...] > sources planned for its evolution. It does not imply that all of these > capabilities are already implemented. +## Overview + + + ## Documentation - [Intent](./docs/-intent.md): purpose, boundaries, and evolution of this module. -- [](./docs//.spec.md): requirements and acceptance - scenarios. +- [](./docs/-/-.spec.md): + requirements and acceptance scenarios. ``` ### Intent (*.intent.md) @@ -132,7 +137,7 @@ tags: [, , ...] ## Documentation - [Readme](../README.md): module overview. -- [](.//.spec.md): Specification. +- [](./-/-.spec.md): Specification. ``` ### Specification (*.spec.md) @@ -173,7 +178,7 @@ THEN THE SOFTWARE SHALL . **Layout:** -```md +````md --- title: - SPEC summary: @@ -196,7 +201,7 @@ Name: **Links:** -- [_-ACC-0001](./.acceptance.md#_-acc-0001) +- [_-ACC-0001](./-.acceptance.md#_-acc-0001) - [Intent](../-intent.md) **Status**: @@ -204,10 +209,12 @@ Name: - Doc status: Draft - Implementation status: Not implemented -**WHEN:** , +```text +WHEN: , -**THE SOFTWARE SHALL:** . +THE SOFTWARE SHALL: . ``` +```` ### Acceptance (*.acceptance.md) @@ -259,7 +266,7 @@ Name: **Links:** -- [_-REQ-0001](./.spec.md#_-req-0001) +- [_-REQ-0001](./-.spec.md#_-req-0001) **Status**: diff --git a/docs/example/example.spec.md b/docs/example/example.spec.md index d343bfd..ca4d7ac 100644 --- a/docs/example/example.spec.md +++ b/docs/example/example.spec.md @@ -20,14 +20,16 @@ Name: Explicit configuration **Links:** -- [EXAMPLE_AREA-ACC-0001](./example.acceptance.md#example_area-acc-0001) - [Intent](../example-intent.md) +- [EXAMPLE_AREA-ACC-0001](./example.acceptance.md#example_area-acc-0001) **Status**: - Doc status: Draft - Implementation status: Not implemented -**WHEN:** Configuration provides an unknown key, +```text +WHEN: Configuration provides an unknown key, -**THE SOFTWARE SHALL:** reject the configuration. +THE SOFTWARE SHALL: reject the configuration. +``` diff --git a/src/environment/src/env_var/README.md b/src/environment/src/env_var/README.md new file mode 100644 index 0000000..f17f4bf --- /dev/null +++ b/src/environment/src/env_var/README.md @@ -0,0 +1,77 @@ +--- +title: Environment variables +summary: Declarative model, resolution, and projection of environment variables in Kraf. +tags: [environment, env-var, resolution, projection] +--- + +This module defines and resolves Kraf's declarative model for environment +variables: their sources (host, organization, user, project, and session), +aliases, and projections exported to Kraf-managed processes. + +> **Note:** this document describes Kraf's environment-variable model, including +> concepts and sources planned for its evolution. It does not imply that all of +> these capabilities are already implemented. + +## Overview + +- [**Sources**](#sources): where environment-variable values, configuration, and + restrictions come from. +- [**Declaration**](#declarations): the canonical definition of a variable. +- [**Resolver**](#resolution): the component that applies declarations to values + from sources to produce an effective value. +- [**Projection**](#projection): the set of effective variables that Kraf + exports to a managed process. + +### Sources + +- **Host:** provides values available in the current environment and platform. +- **User:** provides persistent personal preferences. +- **Organization:** provides shared configuration and policies enforced by the + organization. +- **Project:** provides versioned, project-specific configuration. +- **Session:** provides ephemeral values controlled by Kraf. + +### Declarations + +A canonical definition of a variable in Kraf. A declaration specifies: + +- its canonical key; +- import and export aliases; +- sources eligible to provide a value; +- resolution strategy; +- fallback; +- keys that may be projected to a child process. + +### Resolution + +The resolver applies declarations to values available from sources and produces +the effective value of each variable. + +For each declaration, it defines: + +- precedence between sources; +- how values are combined, when applicable; +- how conflicts or missing values are handled; +- when a fallback is applied; +- how placeholders in values and fallbacks are expanded. + +### Projection + +A projection is the set of effective variables exported by Kraf to a managed +process. + +A declaration can produce one internal canonical key and zero or more export +keys. Not every resolved value must be projected to a child process. + +## Documentation + +- [Intent](./docs/env-var-intent.md): purpose, boundaries, and evolution of this + module. +- [Declarations](./docs/env-var-declarations/env-var-declarations.spec.md): + declaration requirements and acceptance scenarios. +- [Resolution](./docs/env-var-resolution/env-var-resolution.spec.md): resolution + requirements and acceptance scenarios. +- [Projection](./docs/env-var-projection/env-var-projection.spec.md): projection + requirements and acceptance scenarios. +- [Host mappings](./docs/env-var-host/env-var-host.spec.md): platform mapping + requirements and acceptance scenarios. diff --git a/src/environment/src/env_var/docs/env-var-declarations/env-var-declarations.acceptance.md b/src/environment/src/env_var/docs/env-var-declarations/env-var-declarations.acceptance.md new file mode 100644 index 0000000..f700c2a --- /dev/null +++ b/src/environment/src/env_var/docs/env-var-declarations/env-var-declarations.acceptance.md @@ -0,0 +1,160 @@ +--- +title: Environment variables declaration - Acceptance +summary: Acceptance scenarios for declaring environment variables. +tags: [environment, env-var, acceptance, declaration, gherkin] +--- + +## ENV-VAR_DECLARATIONS-ACC-0001 + +Name: Unknown runtime declaration is rejected + +**Links:** + +- [ENV-VAR_DECLARATIONS-REQ-0001](./env-var-declarations.spec.md#env-var_declarations-req-0001) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_DECLARATIONS-FEAT-0001 — Environment variable declarations + + Rule: ENV-VAR_DECLARATIONS-REQ-0001 — Static declaration + + Scenario: ENV-VAR_DECLARATIONS-ACC-0001 — Unknown runtime declaration is rejected + Given no declaration exists for "EXAMPLE_KEY" + When runtime configuration provides a value for "EXAMPLE_KEY" + Then the software rejects the configuration + And "EXAMPLE_KEY" is not projected to a managed process +``` + +--- + +## ENV-VAR_DECLARATIONS-ACC-0002 + +Name: Known runtime declaration accepts a value + +**Links:** + +- [ENV-VAR_DECLARATIONS-REQ-0001](./env-var-declarations.spec.md#env-var_declarations-req-0001) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_DECLARATIONS-FEAT-0001 — Environment variable declarations + + Rule: ENV-VAR_DECLARATIONS-REQ-0001 — Static declaration + + Scenario: ENV-VAR_DECLARATIONS-ACC-0002 — Known runtime declaration accepts a value + Given a declaration exists for "EXAMPLE_KEY" + When runtime configuration provides a value for "EXAMPLE_KEY" + Then the software accepts the configuration +``` + +--- + +## ENV-VAR_DECLARATIONS-ACC-0003 + +Name: Duplicate canonical key is rejected + +**Links:** + +- [ENV-VAR_DECLARATIONS-REQ-0002](./env-var-declarations.spec.md#env-var_declarations-req-0002) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_DECLARATIONS-FEAT-0001 — Environment variable declarations + + Rule: ENV-VAR_DECLARATIONS-REQ-0002 — Canonical key uniqueness + + Scenario: ENV-VAR_DECLARATIONS-ACC-0003 — Duplicate canonical key is rejected + Given two declarations use the canonical key "EXAMPLE_KEY" + When the software loads the declaration set + Then the software rejects the declaration set +``` + +--- + +## ENV-VAR_DECLARATIONS-ACC-0004 + +Name: Merge mapping declares multiple import aliases + +**Links:** + +- [ENV-VAR_DECLARATIONS-REQ-0003](./env-var-declarations.spec.md#env-var_declarations-req-0003) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_DECLARATIONS-FEAT-0001 — Environment variable declarations + + Rule: ENV-VAR_DECLARATIONS-REQ-0003 — Mapping mode validity + + Scenario: ENV-VAR_DECLARATIONS-ACC-0004 — Merge mapping declares multiple import aliases + Given a declaration uses merge import mode + When the declaration defines fewer than two import aliases + Then the software rejects the declaration +``` + +--- + +## ENV-VAR_DECLARATIONS-ACC-0005 + +Name: Pass-through mapping imports only its canonical key + +**Links:** + +- [ENV-VAR_DECLARATIONS-REQ-0003](./env-var-declarations.spec.md#env-var_declarations-req-0003) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_DECLARATIONS-FEAT-0001 — Environment variable declarations + + Rule: ENV-VAR_DECLARATIONS-REQ-0003 — Mapping mode validity + + Scenario: ENV-VAR_DECLARATIONS-ACC-0005 — Pass-through mapping imports only its canonical key + Given a declaration uses pass-through import mode + When the declaration imports an alias other than its canonical key + Then the software rejects the declaration +``` + +--- + +## ENV-VAR_DECLARATIONS-ACC-0006 + +Name: Pass-through mapping has no fallback + +**Links:** + +- [ENV-VAR_DECLARATIONS-REQ-0003](./env-var-declarations.spec.md#env-var_declarations-req-0003) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_DECLARATIONS-FEAT-0001 — Environment variable declarations + + Rule: ENV-VAR_DECLARATIONS-REQ-0003 — Mapping mode validity + + Scenario: ENV-VAR_DECLARATIONS-ACC-0006 — Pass-through mapping has no fallback + Given a declaration uses pass-through import mode + When the declaration defines a fallback + Then the software rejects the declaration +``` diff --git a/src/environment/src/env_var/docs/env-var-declarations/env-var-declarations.spec.md b/src/environment/src/env_var/docs/env-var-declarations/env-var-declarations.spec.md new file mode 100644 index 0000000..cb44f5d --- /dev/null +++ b/src/environment/src/env_var/docs/env-var-declarations/env-var-declarations.spec.md @@ -0,0 +1,99 @@ +--- +title: Environment variables declaration - SPEC +summary: Requirements for declaring environment variables. +tags: [environment, env-var, specification, spec, declaration] +--- + +> [!IMPORTANT] +> Requirements in this specification use EARS notation. **SHALL** and **SHALL +> NOT** define mandatory behavior; **SHOULD** and **SHOULD NOT** define expected +> behavior that requires an explicit justification to deviate from; **MAY** +> defines optional behavior. +> +> These terms follow RFC 2119 and RFC 8174. + +## Requirements + +### ENV-VAR_DECLARATIONS-REQ-0001 + +Name: Static declaration + +**Links:** + +- [Intent](../env-var-intent.md): module intent. +- [ENV-VAR_DECLARATIONS-ACC-0001](./env-var-declarations.acceptance.md#env-var_declarations-acc-0001) +- [ENV-VAR_DECLARATIONS-ACC-0002](./env-var-declarations.acceptance.md#env-var_declarations-acc-0002) + +**Status**: + +- Doc status: Draft +- Implementation status: Not implemented + +```text +The software SHALL resolve and project only environment-variable declarations +that are built into the software or packaged as immutable metadata with a +plugin. + +The software MAY accept values for known declarations from runtime +configuration. + +The software SHALL NOT accept declarations, import aliases, export aliases, or +source eligibility from runtime configuration. + +WHEN: Runtime configuration provides a value for an unknown declaration, + +THE SOFTWARE SHALL: reject the configuration. +``` + +--- + +### ENV-VAR_DECLARATIONS-REQ-0002 + +Name: Canonical key uniqueness + +**Links:** + +- [Intent](../env-var-intent.md): module intent. +- [ENV-VAR_DECLARATIONS-ACC-0003](./env-var-declarations.acceptance.md#env-var_declarations-acc-0003) + +**Status**: + +- Doc status: Draft +- Implementation status: Partially implemented + +```text +The software SHALL accept at most one declaration for each canonical key. + +WHEN: A declaration set contains duplicate canonical keys, + +THE SOFTWARE SHALL: reject the declaration set. +``` + +--- + +### ENV-VAR_DECLARATIONS-REQ-0003 + +Name: Mapping mode validity + +**Links:** + +- [Intent](../env-var-intent.md): module intent. +- [ENV-VAR_DECLARATIONS-ACC-0004](./env-var-declarations.acceptance.md#env-var_declarations-acc-0004) +- [ENV-VAR_DECLARATIONS-ACC-0005](./env-var-declarations.acceptance.md#env-var_declarations-acc-0005) +- [ENV-VAR_DECLARATIONS-ACC-0006](./env-var-declarations.acceptance.md#env-var_declarations-acc-0006) + +**Status**: + +- Doc status: Draft +- Implementation status: Partially implemented + +```text +The software SHALL accept a declaration using merge import mode only when it +declares at least two import aliases. + +The software SHALL accept a declaration using pass-through import mode only when +its canonical key is its only import alias. + +The software SHALL NOT accept a declaration using pass-through import mode that +declares a fallback. +``` diff --git a/src/environment/src/env_var/docs/env-var-host/env-var-host.acceptance.md b/src/environment/src/env_var/docs/env-var-host/env-var-host.acceptance.md new file mode 100644 index 0000000..5e0d886 --- /dev/null +++ b/src/environment/src/env_var/docs/env-var-host/env-var-host.acceptance.md @@ -0,0 +1,107 @@ +--- +title: Environment variables host mappings - Acceptance +summary: Acceptance scenarios for platform-specific environment-variable mappings. +tags: [environment, env-var, acceptance, host, platform, gherkin] +--- + +## ENV-VAR_HOST-ACC-0001 + +Name: Every shared canonical key has a Linux mapping + +**Links:** + +- [ENV-VAR_HOST-REQ-0001](./env-var-host.spec.md#env-var_host-req-0001) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_HOST-FEAT-0001 — Environment variable host mappings + + Rule: ENV-VAR_HOST-REQ-0001 — Supported-platform mapping completeness + + Scenario: ENV-VAR_HOST-ACC-0001 — Every shared canonical key has a Linux mapping + Given the shared canonical environment-variable keys + When the Linux mappings are loaded + Then every shared canonical key has a Linux mapping +``` + +--- + +## ENV-VAR_HOST-ACC-0002 + +Name: Every shared canonical key has a macOS mapping + +**Links:** + +- [ENV-VAR_HOST-REQ-0001](./env-var-host.spec.md#env-var_host-req-0001) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_HOST-FEAT-0001 — Environment variable host mappings + + Rule: ENV-VAR_HOST-REQ-0001 — Supported-platform mapping completeness + + Scenario: ENV-VAR_HOST-ACC-0002 — Every shared canonical key has a macOS mapping + Given the shared canonical environment-variable keys + When the macOS mappings are loaded + Then every shared canonical key has a macOS mapping +``` + +--- + +## ENV-VAR_HOST-ACC-0003 + +Name: Every shared canonical key has a Windows mapping + +**Links:** + +- [ENV-VAR_HOST-REQ-0001](./env-var-host.spec.md#env-var_host-req-0001) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_HOST-FEAT-0001 — Environment variable host mappings + + Rule: ENV-VAR_HOST-REQ-0001 — Supported-platform mapping completeness + + Scenario: ENV-VAR_HOST-ACC-0003 — Every shared canonical key has a Windows mapping + Given the shared canonical environment-variable keys + When the Windows mappings are loaded + Then every shared canonical key has a Windows mapping +``` + +--- + +## ENV-VAR_HOST-ACC-0004 + +Name: Home and work-directory declarations use provided values + +**Links:** + +- [ENV-VAR_HOST-REQ-0002](./env-var-host.spec.md#env-var_host-req-0002) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_HOST-FEAT-0001 — Environment variable host mappings + + Rule: ENV-VAR_HOST-REQ-0002 — Session-owned directory sources + + Scenario: ENV-VAR_HOST-ACC-0004 — Home and work-directory declarations use provided values + Given a supported platform mapping + When the mapping declares WORKDIR or a HOME family key + Then the declaration source is provided +``` diff --git a/src/environment/src/env_var/docs/env-var-host/env-var-host.spec.md b/src/environment/src/env_var/docs/env-var-host/env-var-host.spec.md new file mode 100644 index 0000000..b15ad0e --- /dev/null +++ b/src/environment/src/env_var/docs/env-var-host/env-var-host.spec.md @@ -0,0 +1,57 @@ +--- +title: Environment variables host mappings - SPEC +summary: Requirements for platform-specific environment-variable mappings. +tags: [environment, env-var, specification, spec, host, platform] +--- + +> [!IMPORTANT] +> Requirements in this specification use EARS notation. **SHALL** and **SHALL +> NOT** define mandatory behavior; **SHOULD** and **SHOULD NOT** define expected +> behavior that requires an explicit justification to deviate from; **MAY** +> defines optional behavior. +> +> These terms follow RFC 2119 and RFC 8174. + +## Requirements + +### ENV-VAR_HOST-REQ-0001 + +Name: Supported-platform mapping completeness + +**Links:** + +- [Intent](../env-var-intent.md): module intent. +- [ENV-VAR_HOST-ACC-0001](./env-var-host.acceptance.md#env-var_host-acc-0001) +- [ENV-VAR_HOST-ACC-0002](./env-var-host.acceptance.md#env-var_host-acc-0002) +- [ENV-VAR_HOST-ACC-0003](./env-var-host.acceptance.md#env-var_host-acc-0003) + +**Status**: + +- Doc status: Draft +- Implementation status: Implemented + +```text +The software SHALL declare every shared canonical environment-variable key in +every supported platform mapping. +``` + +--- + +### ENV-VAR_HOST-REQ-0002 + +Name: Session-owned directory sources + +**Links:** + +- [Intent](../env-var-intent.md): module intent. +- [ENV-VAR_HOST-ACC-0004](./env-var-host.acceptance.md#env-var_host-acc-0004) + +**Status**: + +- Doc status: Draft +- Implementation status: Implemented + +```text +The software SHALL resolve the WORKDIR and HOME declaration families from +provided values rather than from values imported from the host. +``` diff --git a/src/environment/src/env_var/docs/env-var-intent.md b/src/environment/src/env_var/docs/env-var-intent.md new file mode 100644 index 0000000..3973357 --- /dev/null +++ b/src/environment/src/env_var/docs/env-var-intent.md @@ -0,0 +1,91 @@ +--- +title: Environment variables intent +summary: Why Kraf resolves and projects environment variables through a declarative model. +tags: [environment, env-var, intent, security, projection] +--- + +## Problem + +Development environments inherit a large, implicit set of environment variables +from the host. Their names, formats, availability, and meaning vary across +platforms. Values may also come from personal preferences, project +configuration, organization policy, or the current Kraf session. + +When each tool or module reads the host environment directly, the resulting +behavior is difficult to understand, reproduce, audit, and evolve. It also +allows undeclared host state to reach managed processes by accident. + +## Intent + +This module should resolve environment variables through one declarative model +and produce an explicit projection for each managed process. + +The model must make it possible to: + +- normalize platform-specific aliases behind canonical declarations; +- combine values from Host, User, Organization, Project, and Session sources; +- evolve source loading and resolution rules without spreading environment logic + across consumers; +- make the environment received by a managed process explicit and reviewable. + +### Principles + +#### Static declarations + +Environment declarations are static capabilities. + +Declarations are embedded in source code. Plugin declarations are embedded in +plugin source code or immutable plugin metadata distributed with the plugin. A +declaration identifies an allowed variable and its behavior; it does not contain +the final runtime value. + +Dynamic sources may provide values for existing declarations. They must not +create new declarations, request undeclared host values, or expand the set of +variables that a process may receive. + +#### Security access + +Only the environment module may read raw environment values from the host. + +Other modules and plugins may obtain a resolved value only through a declaration +they own or explicitly declare as a dependency. This module must not expose an +operation that enumerates all host environment variables, nor arbitrary +string-based host lookups outside this module. + +#### Explicit projection + +Importing an alias and exporting a value are separate permissions. + +Knowing that a host alias exists does not authorize exporting it. Resolving a +value does not authorize projecting it. A managed process receives only the +canonical keys and export aliases explicitly permitted by declarations. + +This makes the projected environment an allowlist rather than an inherited copy +of the host environment. + +## Boundaries + +This module owns declaration, resolution, and projection of environment values. + +It does not: + +- create or manage process sessions; +- choose a terminal or launch a process; +- sandbox filesystem, network, permissions, or host processes; +- define every future source format or precedence rule. + +Session creation and process launch belong to the trap module. The trap provides +session-owned values, requests a resolved projection, and applies that +projection to its managed process. + +## Documentation + +- [Readme](../README.md): module overview. +- [Declarations](./env-var-declarations/env-var-declarations.spec.md): + declarations Specification. +- [Resolution](./env-var-resolution/env-var-resolution.spec.md): + resolution Specification. +- [Projection](./env-var-projection/env-var-projection.spec.md): + projection Specification. +- [Host mappings](./env-var-host/env-var-host.spec.md): + host mappings Specification. diff --git a/src/environment/src/env_var/docs/env-var-projection/env-var-projection.acceptance.md b/src/environment/src/env_var/docs/env-var-projection/env-var-projection.acceptance.md new file mode 100644 index 0000000..4af077a --- /dev/null +++ b/src/environment/src/env_var/docs/env-var-projection/env-var-projection.acceptance.md @@ -0,0 +1,84 @@ +--- +title: Environment variables projection - Acceptance +summary: Acceptance scenarios for projecting environment variables. +tags: [environment, env-var, acceptance, projection, gherkin] +--- + +## ENV-VAR_PROJECTION-ACC-0001 + +Name: Declared export alias is projected + +**Links:** + +- [ENV-VAR_PROJECTION-REQ-0001](./env-var-projection.spec.md#env-var_projection-req-0001) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_PROJECTION-FEAT-0001 — Environment variable projection + + Rule: ENV-VAR_PROJECTION-REQ-0001 — Explicit export authorization + + Scenario: ENV-VAR_PROJECTION-ACC-0001 — Declared export alias is projected + Given "EXAMPLE_KEY" is declared as an export alias + And "EXAMPLE_KEY" has a resolved value + When the software applies the projection to a managed process + Then the managed process receives "EXAMPLE_KEY" +``` + +--- + +## ENV-VAR_PROJECTION-ACC-0002 + +Name: Non-exportable resolved value is not projected + +**Links:** + +- [ENV-VAR_PROJECTION-REQ-0001](./env-var-projection.spec.md#env-var_projection-req-0001) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_PROJECTION-FEAT-0001 — Environment variable projection + + Rule: ENV-VAR_PROJECTION-REQ-0001 — Explicit export authorization + + Scenario: ENV-VAR_PROJECTION-ACC-0002 — Non-exportable resolved value is not projected + Given "EXAMPLE_KEY" has a resolved value + And "EXAMPLE_KEY" is not declared as an export alias + When the software applies the projection to a managed process + Then the managed process does not receive "EXAMPLE_KEY" +``` + +--- + +## ENV-VAR_PROJECTION-ACC-0003 + +Name: Export aliases receive the canonical resolved value + +**Links:** + +- [ENV-VAR_PROJECTION-REQ-0002](./env-var-projection.spec.md#env-var_projection-req-0002) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_PROJECTION-FEAT-0001 — Environment variable projection + + Rule: ENV-VAR_PROJECTION-REQ-0002 — Export value symmetry + + Scenario: ENV-VAR_PROJECTION-ACC-0003 — Export aliases receive the canonical resolved value + Given "HOME_TEMP" resolves to "/workspace/.tmp" + And "TMPDIR" is an export alias of "HOME_TEMP" + When the software resolves the declaration + Then "TMPDIR" resolves to "/workspace/.tmp" +``` diff --git a/src/environment/src/env_var/docs/env-var-projection/env-var-projection.spec.md b/src/environment/src/env_var/docs/env-var-projection/env-var-projection.spec.md new file mode 100644 index 0000000..3b67a5e --- /dev/null +++ b/src/environment/src/env_var/docs/env-var-projection/env-var-projection.spec.md @@ -0,0 +1,56 @@ +--- +title: Environment variables projection - SPEC +summary: Requirements for projecting resolved environment variables to managed processes. +tags: [environment, env-var, specification, spec, projection] +--- + +> [!IMPORTANT] +> Requirements in this specification use EARS notation. **SHALL** and **SHALL +> NOT** define mandatory behavior; **SHOULD** and **SHOULD NOT** define expected +> behavior that requires an explicit justification to deviate from; **MAY** +> defines optional behavior. +> +> These terms follow RFC 2119 and RFC 8174. + +## Requirements + +### ENV-VAR_PROJECTION-REQ-0001 + +Name: Explicit export authorization + +**Links:** + +- [Intent](../env-var-intent.md): module intent. +- [ENV-VAR_PROJECTION-ACC-0001](./env-var-projection.acceptance.md#env-var_projection-acc-0001) +- [ENV-VAR_PROJECTION-ACC-0002](./env-var-projection.acceptance.md#env-var_projection-acc-0002) + +**Status**: + +- Doc status: Draft +- Implementation status: Implemented + +```text +The software SHALL project only keys declared as export aliases by the active +mappings. +``` + +--- + +### ENV-VAR_PROJECTION-REQ-0002 + +Name: Export value symmetry + +**Links:** + +- [Intent](../env-var-intent.md): module intent. +- [ENV-VAR_PROJECTION-ACC-0003](./env-var-projection.acceptance.md#env-var_projection-acc-0003) + +**Status**: + +- Doc status: Draft +- Implementation status: Implemented + +```text +The software SHALL assign the declaration's resolved value to every export alias +the declaration produces. +``` diff --git a/src/environment/src/env_var/docs/env-var-resolution/env-var-resolution.acceptance.md b/src/environment/src/env_var/docs/env-var-resolution/env-var-resolution.acceptance.md new file mode 100644 index 0000000..515a17b --- /dev/null +++ b/src/environment/src/env_var/docs/env-var-resolution/env-var-resolution.acceptance.md @@ -0,0 +1,687 @@ +--- +title: Environment variables resolution - Acceptance +summary: Acceptance scenarios for environment-variable resolution. +tags: [environment, env-var, acceptance, resolution, gherkin] +--- + +## ENV-VAR_RESOLUTION-ACC-0001 + +Name: Import aliases are collected and deduplicated + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0001](./env-var-resolution.spec.md#env-var_resolution-req-0001) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0001 — Declared import dependency collection + + Scenario: ENV-VAR_RESOLUTION-ACC-0001 — Import aliases are collected and deduplicated + Given multiple declarations import the alias "SHELL" + When the software collects import dependencies + Then "SHELL" is collected once +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0002 + +Name: Fallback variable reference is collected + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0001](./env-var-resolution.spec.md#env-var_resolution-req-0001) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0001 — Declared import dependency collection + + Scenario: ENV-VAR_RESOLUTION-ACC-0002 — Fallback variable reference is collected + Given a declaration fallback references "$HOME" + When the software collects import dependencies + Then "HOME" is collected +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0003 + +Name: First available import alias is selected + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0002](./env-var-resolution.spec.md#env-var_resolution-req-0002) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0002 — First-found resolution + + Scenario: ENV-VAR_RESOLUTION-ACC-0003 — First available import alias is selected + Given a declaration imports "USER_LANGUAGE" before "LANG" + And both aliases provide a value + When the software resolves the declaration + Then the value of "USER_LANGUAGE" is selected +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0004 + +Name: Fallback is used when no import alias has a value + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0002](./env-var-resolution.spec.md#env-var_resolution-req-0002) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0002 — First-found resolution + + Scenario: ENV-VAR_RESOLUTION-ACC-0004 — Fallback is used when no import alias has a value + Given no import alias provides a value + And the declaration fallback is "C.UTF-8" + When the software resolves the declaration + Then the declaration resolves to "C.UTF-8" +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0005 + +Name: Non-empty path aliases are merged in declaration order + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0003](./env-var-resolution.spec.md#env-var_resolution-req-0003) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0003 — Path merge resolution + + Scenario: ENV-VAR_RESOLUTION-ACC-0005 — Non-empty path aliases are merged in declaration order + Given a declaration imports "BIN_A" before "BIN_B" + And "BIN_A" provides "/custom/bin" + And "BIN_B" provides "/usr/bin" + When the software resolves the declaration + Then the resolved value contains "/custom/bin" before "/usr/bin" +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0006 + +Name: Merge fallback is used when no path is available + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0003](./env-var-resolution.spec.md#env-var_resolution-req-0003) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0003 — Path merge resolution + + Scenario: ENV-VAR_RESOLUTION-ACC-0006 — Merge fallback is used when no path is available + Given no import alias provides a non-empty path value + And the declaration fallback is "/usr/share/man" + When the software resolves the declaration + Then the declaration resolves to "/usr/share/man" +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0007 + +Name: Tilde fallback expands from resolved home + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0004](./env-var-resolution.spec.md#env-var_resolution-req-0004) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0004 — Placeholder expansion + + Scenario: ENV-VAR_RESOLUTION-ACC-0007 — Tilde fallback expands from resolved home + Given "HOME" resolves to "/workspace" + And a declaration fallback is "~/.cache" + When the software resolves the declaration + Then the declaration resolves to "/workspace/.cache" +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0008 + +Name: Dollar fallback expands from a collected value + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0004](./env-var-resolution.spec.md#env-var_resolution-req-0004) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0004 — Placeholder expansion + + Scenario: ENV-VAR_RESOLUTION-ACC-0008 — Dollar fallback expands from a collected value + Given "HOME" has the collected value "/workspace" + And a declaration fallback is "$HOME/.cache" + When the software resolves the declaration + Then the declaration resolves to "/workspace/.cache" +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0009 + +Name: Unresolved placeholder remains literal + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0004](./env-var-resolution.spec.md#env-var_resolution-req-0004) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0004 — Placeholder expansion + + Scenario: ENV-VAR_RESOLUTION-ACC-0009 — Unresolved placeholder remains literal + Given a declaration fallback is "$UNKNOWN/.cache" + And "UNKNOWN" has no resolved value + When the software resolves the declaration + Then the declaration resolves to "$UNKNOWN/.cache" +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0010 + +Name: Empty first-found value is selected + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0002](./env-var-resolution.spec.md#env-var_resolution-req-0002) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0002 — First-found resolution + + Scenario: ENV-VAR_RESOLUTION-ACC-0010 — Empty first-found value is selected + Given a declaration imports "PRIMARY" before "SECONDARY" + And "PRIMARY" has the collected value "" + And "SECONDARY" has the collected value "fallback-value" + When the software resolves the declaration + Then the declaration resolves to "" +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0011 + +Name: Provided canonical value precedes fallback + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0005](./env-var-resolution.spec.md#env-var_resolution-req-0005) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0005 — Source precedence and absence + + Scenario: ENV-VAR_RESOLUTION-ACC-0011 — Provided canonical value precedes fallback + Given a provided declaration has no import aliases + And its canonical key has the collected value "/custom/tmp" + And its fallback is "/default/tmp" + When the software resolves the declaration + Then the declaration resolves to "/custom/tmp" +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0012 + +Name: Provided fallback is used when canonical value is absent + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0005](./env-var-resolution.spec.md#env-var_resolution-req-0005) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0005 — Source precedence and absence + + Scenario: ENV-VAR_RESOLUTION-ACC-0012 — Provided fallback is used when canonical value is absent + Given a provided declaration has no import aliases + And its canonical key has no collected value + And its fallback is "/default/tmp" + When the software resolves the declaration + Then the declaration resolves to "/default/tmp" +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0013 + +Name: Host declaration without aliases ignores its canonical collected value + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0005](./env-var-resolution.spec.md#env-var_resolution-req-0005) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0005 — Source precedence and absence + + Scenario: ENV-VAR_RESOLUTION-ACC-0013 — Host declaration without aliases ignores its canonical collected value + Given a host declaration has no import aliases + And its canonical key has the collected value "Linux" + And its fallback is "Darwin" + When the software resolves the declaration + Then the declaration resolves to "Darwin" +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0014 + +Name: Empty path values are ignored during merge + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0003](./env-var-resolution.spec.md#env-var_resolution-req-0003) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0003 — Path merge resolution + + Scenario: ENV-VAR_RESOLUTION-ACC-0014 — Empty path values are ignored during merge + Given a merge declaration imports "BIN_A" before "BIN_B" + And "BIN_A" has the collected value "" + And "BIN_B" has the collected value "/usr/bin" + When the software resolves the declaration + Then the declaration resolves to "/usr/bin" +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0015 + +Name: Merged paths use the current platform separator + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0003](./env-var-resolution.spec.md#env-var_resolution-req-0003) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0003 — Path merge resolution + + Scenario: ENV-VAR_RESOLUTION-ACC-0015 — Merged paths use the current platform separator + Given a merge declaration has two non-empty path values + When the software resolves the declaration + Then its paths are joined with the current platform path separator + And duplicate path entries are preserved +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0016 + +Name: Tilde expansion takes precedence and replaces only the first tilde + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0004](./env-var-resolution.spec.md#env-var_resolution-req-0004) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0004 — Placeholder expansion + + Scenario: ENV-VAR_RESOLUTION-ACC-0016 — Tilde expansion takes precedence and replaces only the first tilde + Given "HOME" has the collected value "/workspace" + And a declaration fallback is "~/$HOME/~" + When the software resolves the declaration + Then the declaration resolves to "/workspace/$HOME/~" +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0017 + +Name: Invalid dollar syntax remains literal + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0004](./env-var-resolution.spec.md#env-var_resolution-req-0004) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0004 — Placeholder expansion + + Scenario Outline: ENV-VAR_RESOLUTION-ACC-0017 — Invalid dollar syntax remains literal + Given a declaration fallback is "" + When the software resolves the declaration + Then the declaration resolves to "" + + Examples: + | fallback | + | $ | + | $/cache | + | ${HOME}/cache | +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0018 + +Name: Dollar expansion replaces only the first placeholder + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0004](./env-var-resolution.spec.md#env-var_resolution-req-0004) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0004 — Placeholder expansion + + Scenario: ENV-VAR_RESOLUTION-ACC-0018 — Dollar expansion replaces only the first placeholder + Given "HOME" has the collected value "/workspace" + And a declaration fallback is "$HOME/$HOME" + When the software resolves the declaration + Then the declaration resolves to "/workspace/$HOME" +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0019 + +Name: Pass-through forwards the first available value + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0006](./env-var-resolution.spec.md#env-var_resolution-req-0006) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0006 — Pass-through resolution + + Scenario: ENV-VAR_RESOLUTION-ACC-0019 — Pass-through forwards the first available value + Given a pass-through declaration imports "SystemRoot" + And "SystemRoot" has the collected value "C:\\Windows" + When the software resolves the declaration + Then the declaration resolves to "C:\\Windows" +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0020 + +Name: Pass-through absence resolves to an empty value + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0006](./env-var-resolution.spec.md#env-var_resolution-req-0006) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0006 — Pass-through resolution + + Scenario: ENV-VAR_RESOLUTION-ACC-0020 — Pass-through absence resolves to an empty value + Given a pass-through declaration imports "SystemRoot" + And "SystemRoot" has no collected value + When the software resolves the declaration + Then the declaration resolves to "" +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0021 + +Name: Unjoinable merged paths resolve to an empty value + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0003](./env-var-resolution.spec.md#env-var_resolution-req-0003) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0003 — Path merge resolution + + Scenario: ENV-VAR_RESOLUTION-ACC-0021 — Unjoinable merged paths resolve to an empty value + Given a merge declaration has paths that cannot be joined for the current platform + When the software resolves the declaration + Then the declaration resolves to "" +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0022 + +Name: Missing source and fallback resolve to an empty value + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0005](./env-var-resolution.spec.md#env-var_resolution-req-0005) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0005 — Source precedence and absence + + Scenario: ENV-VAR_RESOLUTION-ACC-0022 — Missing source and fallback resolve to an empty value + Given a host declaration has no import aliases + And the declaration has no fallback + When the software resolves the declaration + Then the declaration resolves to "" +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0023 + +Name: Empty provided canonical value precedes fallback + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0005](./env-var-resolution.spec.md#env-var_resolution-req-0005) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0005 — Source precedence and absence + + Scenario: ENV-VAR_RESOLUTION-ACC-0023 — Empty provided canonical value precedes fallback + Given a provided declaration has no import aliases + And its canonical key has the collected value "" + And its fallback is "/default/tmp" + When the software resolves the declaration + Then the declaration resolves to "" +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0024 + +Name: Resolved output preserves declaration and export order + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0007](./env-var-resolution.spec.md#env-var_resolution-req-0007) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0007 — Resolved output order + + Scenario: ENV-VAR_RESOLUTION-ACC-0024 — Resolved output preserves declaration and export order + Given "HOME_TEMP" resolves to "/workspace/.tmp" + And its export aliases are "TEMP", "TMPDIR", and "TMP" in that order + When the software resolves the declaration + Then the resolved keys are "HOME_TEMP", "TEMP", "TMPDIR", and "TMP" in that order + And each resolved key has the value "/workspace/.tmp" +``` + +--- + +## ENV-VAR_RESOLUTION-ACC-0025 + +Name: Collected keys are deduplicated and sorted + +**Links:** + +- [ENV-VAR_RESOLUTION-REQ-0001](./env-var-resolution.spec.md#env-var_resolution-req-0001) + +**Status**: + +- Doc status: Draft +- Verification status: Unknown + +```gherkin +Feature: ENV-VAR_RESOLUTION-FEAT-0001 — Environment variable resolution + + Rule: ENV-VAR_RESOLUTION-REQ-0001 — Declared import dependency collection + + Scenario: ENV-VAR_RESOLUTION-ACC-0025 — Collected keys are deduplicated and sorted + Given active mappings declare the import aliases "SHELL", "EDITOR", and "SHELL" + When the software collects import dependencies + Then the collected import keys are "EDITOR" and "SHELL" in that order +``` diff --git a/src/environment/src/env_var/docs/env-var-resolution/env-var-resolution.spec.md b/src/environment/src/env_var/docs/env-var-resolution/env-var-resolution.spec.md new file mode 100644 index 0000000..4c5603e --- /dev/null +++ b/src/environment/src/env_var/docs/env-var-resolution/env-var-resolution.spec.md @@ -0,0 +1,241 @@ +--- +title: Environment variables resolution - SPEC +summary: Requirements for resolving declared environment variables. +tags: [environment, env-var, specification, spec, resolution] +--- + +> [!IMPORTANT] +> Requirements in this specification use EARS notation. **SHALL** and **SHALL +> NOT** define mandatory behavior; **SHOULD** and **SHOULD NOT** define expected +> behavior that requires an explicit justification to deviate from; **MAY** +> defines optional behavior. +> +> These terms follow RFC 2119 and RFC 8174. + +## Requirements + +### ENV-VAR_RESOLUTION-REQ-0001 + +Name: Declared import dependency collection + +**Links:** + +- [Intent](../env-var-intent.md): module intent. +- [ENV-VAR_RESOLUTION-ACC-0001](./env-var-resolution.acceptance.md#env-var_resolution-acc-0001) +- [ENV-VAR_RESOLUTION-ACC-0002](./env-var-resolution.acceptance.md#env-var_resolution-acc-0002) +- [ENV-VAR_RESOLUTION-ACC-0025](./env-var-resolution.acceptance.md#env-var_resolution-acc-0025) + +**Status**: + +- Doc status: Draft +- Implementation status: Implemented + +```text +The software SHALL collect only import aliases and the first valid dollar +variable reference in a declaration fallback. + +The software SHALL deduplicate and lexicographically sort collected import and +export keys. +``` + +--- + +### ENV-VAR_RESOLUTION-REQ-0002 + +Name: First-found resolution + +**Links:** + +- [Intent](../env-var-intent.md): module intent. +- [ENV-VAR_RESOLUTION-ACC-0003](./env-var-resolution.acceptance.md#env-var_resolution-acc-0003) +- [ENV-VAR_RESOLUTION-ACC-0004](./env-var-resolution.acceptance.md#env-var_resolution-acc-0004) +- [ENV-VAR_RESOLUTION-ACC-0010](./env-var-resolution.acceptance.md#env-var_resolution-acc-0010) + +**Status**: + +- Doc status: Draft +- Implementation status: Implemented + +```text +The software SHALL resolve a declaration using first-found import mode to the +first available import alias in declaration order. A collected value is +available when it is present, including when its value is empty. + +WHEN: No import alias provides a value, + +THE SOFTWARE SHALL: resolve the declaration fallback. +``` + +--- + +### ENV-VAR_RESOLUTION-REQ-0003 + +Name: Path merge resolution + +**Links:** + +- [Intent](../env-var-intent.md): module intent. +- [ENV-VAR_RESOLUTION-ACC-0005](./env-var-resolution.acceptance.md#env-var_resolution-acc-0005) +- [ENV-VAR_RESOLUTION-ACC-0006](./env-var-resolution.acceptance.md#env-var_resolution-acc-0006) +- [ENV-VAR_RESOLUTION-ACC-0014](./env-var-resolution.acceptance.md#env-var_resolution-acc-0014) +- [ENV-VAR_RESOLUTION-ACC-0015](./env-var-resolution.acceptance.md#env-var_resolution-acc-0015) +- [ENV-VAR_RESOLUTION-ACC-0021](./env-var-resolution.acceptance.md#env-var_resolution-acc-0021) + +**Status**: + +- Doc status: Draft +- Implementation status: Implemented + +```text +The software SHALL resolve a declaration using merge import mode by ignoring +empty imported values, splitting each remaining value into paths using the +current platform semantics, and joining the resulting paths in declaration order +using the current platform path separator. + +The software SHALL NOT deduplicate path entries during merge resolution. + +WHEN: No import alias provides a non-empty path value, + +THE SOFTWARE SHALL: resolve the declaration fallback. + +WHEN: Joining the collected paths cannot produce a valid string for the +current platform, + +THE SOFTWARE SHALL: resolve the declaration to an empty string. +``` + +--- + +### ENV-VAR_RESOLUTION-REQ-0004 + +Name: Placeholder expansion + +**Links:** + +- [Intent](../env-var-intent.md): module intent. +- [ENV-VAR_RESOLUTION-ACC-0007](./env-var-resolution.acceptance.md#env-var_resolution-acc-0007) +- [ENV-VAR_RESOLUTION-ACC-0008](./env-var-resolution.acceptance.md#env-var_resolution-acc-0008) +- [ENV-VAR_RESOLUTION-ACC-0009](./env-var-resolution.acceptance.md#env-var_resolution-acc-0009) +- [ENV-VAR_RESOLUTION-ACC-0016](./env-var-resolution.acceptance.md#env-var_resolution-acc-0016) +- [ENV-VAR_RESOLUTION-ACC-0017](./env-var-resolution.acceptance.md#env-var_resolution-acc-0017) +- [ENV-VAR_RESOLUTION-ACC-0018](./env-var-resolution.acceptance.md#env-var_resolution-acc-0018) + +**Status**: + +- Doc status: Draft +- Implementation status: Implemented + +```text +WHEN: A fallback contains a tilde and a non-empty collected `HOME` value is +available, + +THE SOFTWARE SHALL: replace the first tilde with that value. + +WHEN: A non-empty collected `HOME` value is available, + +THE SOFTWARE SHALL: give tilde expansion precedence over dollar expansion. + +WHEN: A fallback contains a tilde but no non-empty collected `HOME` value is +available, + +THE SOFTWARE SHALL: leave the tilde unchanged and evaluate a dollar +placeholder when one is present. + +A dollar placeholder is the first dollar sign followed by one or more ASCII +letters, digits, or underscores. + +The software SHALL replace the first occurrence of that placeholder with the +collected value whose key matches its name, including an empty value. + +WHEN: A dollar sign has no valid placeholder name or a dollar placeholder +has no collected value, + +THE SOFTWARE SHALL: preserve it literally. +``` + +--- + +### ENV-VAR_RESOLUTION-REQ-0005 + +Name: Source precedence and absence + +**Links:** + +- [Intent](../env-var-intent.md): module intent. +- [ENV-VAR_RESOLUTION-ACC-0011](./env-var-resolution.acceptance.md#env-var_resolution-acc-0011) +- [ENV-VAR_RESOLUTION-ACC-0012](./env-var-resolution.acceptance.md#env-var_resolution-acc-0012) +- [ENV-VAR_RESOLUTION-ACC-0013](./env-var-resolution.acceptance.md#env-var_resolution-acc-0013) +- [ENV-VAR_RESOLUTION-ACC-0022](./env-var-resolution.acceptance.md#env-var_resolution-acc-0022) +- [ENV-VAR_RESOLUTION-ACC-0023](./env-var-resolution.acceptance.md#env-var_resolution-acc-0023) + +**Status**: + +- Doc status: Draft +- Implementation status: Implemented + +```text +WHEN: A declaration without import aliases and with source `Provided` has a +collected canonical value, including an empty value, + +THE SOFTWARE SHALL: resolve the declaration to that value. + +WHEN: That provided canonical value is absent, + +THE SOFTWARE SHALL: resolve the declaration fallback. + +The software SHALL resolve a declaration without import aliases and with source +`Host` to its fallback without reading a collected value for its canonical key. + +WHEN: The selected source and fallback provide no value, + +THE SOFTWARE SHALL: resolve the declaration to an empty string. +``` + +--- + +### ENV-VAR_RESOLUTION-REQ-0006 + +Name: Pass-through resolution + +**Links:** + +- [Intent](../env-var-intent.md): module intent. +- [ENV-VAR_RESOLUTION-ACC-0019](./env-var-resolution.acceptance.md#env-var_resolution-acc-0019) +- [ENV-VAR_RESOLUTION-ACC-0020](./env-var-resolution.acceptance.md#env-var_resolution-acc-0020) + +**Status**: + +- Doc status: Draft +- Implementation status: Implemented + +```text +The software SHALL resolve a declaration using pass-through import mode to the +first available import alias in declaration order without applying a fallback. + +WHEN: No import alias provides a value, + +THE SOFTWARE SHALL: resolve the declaration to an empty string. +``` + +--- + +### ENV-VAR_RESOLUTION-REQ-0007 + +Name: Resolved output order + +**Links:** + +- [Intent](../env-var-intent.md): module intent. +- [ENV-VAR_RESOLUTION-ACC-0024](./env-var-resolution.acceptance.md#env-var_resolution-acc-0024) + +**Status**: + +- Doc status: Draft +- Implementation status: Implemented + +```text +The software SHALL emit resolved declarations in active mapping order. + +The software SHALL emit, for each declaration, the canonical key first, followed +by its export aliases in declaration order, all with the same resolved value. +```