Contract Authoring · Lesson 03 of 04
Effects, identities, services, and environments
Declare what a task writes, reads from the network, or depends on externally so Ota can reason about its safety and reproducibility.
Learning objectives
- Add an
effectsblock to a task - Declare an external service dependency
- Explain why environment variables must be declared, not inferred
Prerequisites
Effects make material behavior reviewable. Requirements describe what execution needs; effects describe what it may change or contact. Environment declarations name required inputs without turning ota.yaml into a secret store.
Name writes, network, and external state
Use writes for durable repository paths, network with a network_kind for connectivity posture, adapter_state for provider-managed local state, and external_state for out-of-repository mutation such as database, hosted-service, or container-engine state.
From Ota v1.6.27, typed effect declarations can additionally separate a canonical non-secret resource binding, a reusable consequence definition, and the exact task attachment. That declaration makes review truth more precise; it does not verify provider state, authorize execution, or establish positive refusal assurance.
The execution-disabled PostgreSQL adapter binds the contract invocation origin and repository-relative effective working directory into its application plan. On Unix it opens every effective-cwd and migration-root component relative to a retained repository descriptor without following symlinks. Repo-level ota run and non-dry-run repo-level ota up perform one closure-wide typed preflight before command-scoped replay-input policy loading, agent/crossing/sandbox admission, workflow-environment artifact rendering, or durable-log preparation. Proof paths invoking repo-level ota up inherit that boundary; dry-run and other read-only command diagnosis remain outside the ordering claim.
A contract-owned effect-refusal canary can now challenge one exact task or workflow origin without starting execution. It passes only when the eligible realization is denied by an explicit matching typed rule. Generic safety, readiness, authority, runtime, sandbox, or fallback refusal is not equivalent evidence. This remains a negative control, not provider mutation, receipt/archive evidence, or positive assurance.
tasks: integration: command: exe: cargo args: [nextest, run, --test, integration] requires_services: [postgres] requirements: env: [DATABASE_URL] effects: network: true network_kind: integration_test external_state: [database]resource_bindings: production_primary: kind: database provider: postgresql namespace: authority: dns:example.org tenant: platform environment: production effect_definitions: production_schema_migration: kind: database_schema_mutation action: apply_migration_set resource: engine: postgresql target_ref: production_primary schema: public bounds: migration_set: root: migrations content_identity: sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef start_state: any_within_set tasks: db:migrate: action: kind: database_schema_mutation effect: production_schema_migration effects: declared: [production_schema_migration]Secrets remain externally supplied
The contract should declare required variable names and supported env sources, never secret values. Compatibility environment declarations remain externally supplied. A governed secret_requirements recipient is different: current command admission refuses before setup or execution while protected provider-binding truth is unavailable, and an ambient value with the same name cannot satisfy it.
The public admission projection is negative evidence only: provider availability is not_checked, provider contact and delivery are not_attempted, and execution has not started. Real ota up may retain its ordinary blocked execution receipt with execution_attempted: false; that failure record is not a positive secret-delivery receipt. Provider-backed injection, secret-delivery archives, and assurance remain unproved.
Canonical terminology
Evidence boundary for this lesson
Establishes
- The worked examples establish the lesson's canonical Ota distinctions for its stated scope.
Does not establish
- Reading the lesson does not validate a repository, execute its tasks, or establish organizational acceptance.
Knowledge check
Why should ota.yaml declare a secret name but not its value?
The contract declares the requirement and scope. The local shell, CI provider, or supported adapter supplies the value so repository truth does not become secret storage.