<!--
  Sync Impact Report
  Version change: 1.1.0 → 1.1.1
  Modified principles: None
  Added sections: N/A
  Modified sections:
    - Dependency Governance — Removed `github.com/miekg/dns` from
      Currently Approved External Dependencies (replaced by
      `golang.org/x/net/dns/dnsmessage` in feature 001)
  Removed sections: N/A
  Templates requiring updates:
    - .specify/templates/plan-template.md — ⚠ pending (Constitution Check
      section references "[Gates determined based on constitution file]";
      will be populated when /speckit.plan runs against this constitution)
    - .specify/templates/spec-template.md — ✅ no updates required
    - .specify/templates/tasks-template.md — ✅ no updates required
  Follow-up TODOs: None
-->

# ekdns Constitution

## Core Principles

### I. System File Safety

The hosts file is a critical operating system resource. Corruption or
data loss in this file disables all local name resolution and can render
a machine unusable without manual intervention.

- The tool MUST NOT truncate, zero-out, or partially overwrite the hosts
  file at any point during its operation.
- All writes to the hosts file MUST use an atomic pattern: write complete
  content to a temporary file in the same directory, then rename over the
  original.
- A backup of the current hosts file MUST be created before any
  modification is committed.
- If any step in the write pipeline fails, the original hosts file MUST
  remain unmodified.

**Rationale**: This tool exists to solve DNS reliability problems. If it
introduces a new failure mode — destroying the hosts file — it is worse
than the problem it solves.

### II. Standard Library First

The Go standard library MUST be the first choice for all functionality.
External dependencies introduce supply-chain risk, version conflicts,
and maintenance burden that are disproportionate for a small,
single-purpose utility.

- All functionality MUST be implemented using the Go standard library
  unless a documented technical justification proves it insufficient.
- When an external dependency is genuinely required, it MUST come from
  one of the following approved sources:
  - `golang.org/x/*` (official Go extended libraries)
  - `dev.emberkom.com/*` (Emberkom internal libraries)
- Any other external dependency MUST have a written justification in the
  code review or commit message explaining: (a) what standard library
  alternative was considered, (b) why it was insufficient, and (c) what
  the external dependency provides that the stdlib does not.
- Dependencies MUST be audited when upgraded to ensure no new transitive
  dependencies from unapproved sources are introduced.

**Rationale**: A single-binary CLI tool that modifies a system file must
have a minimal and auditable dependency tree. Every external package is
an attack surface and a maintenance liability.

### III. Go 1.20 Compatibility

This tool MUST compile and run correctly with Go 1.20. This version
ceiling exists to maintain compatibility with legacy systems that cannot
run newer Go runtimes.

- The `go.mod` file MUST specify `go 1.20` as the language version.
- No language features, standard library APIs, or dependency versions
  exclusive to Go 1.21 or later are permitted.
- Build and test pipelines MUST use Go 1.20 as the primary toolchain
  version to catch compatibility issues early.
- If a dependency releases a version that requires Go 1.21+, the tool
  MUST pin to the last Go 1.20-compatible release of that dependency.

**Rationale**: The target deployment environments include older systems
where upgrading the Go toolchain or OS is not feasible. Pinning the
version ensures the tool remains deployable everywhere it is needed.

### IV. Idiomatic Error Handling

Errors MUST flow upward through return values. Functions MUST NOT
terminate the process, call `os.Exit`, or invoke global exit helpers
except at the top-level `main` function.

- Every function that can fail MUST return an `error` value.
- Callers MUST inspect returned errors and either handle them, wrap them
  with additional context, or propagate them upward.
- The `main` function is the only location permitted to call `os.Exit`
  or print a fatal error and terminate.
- Platform-specific code (build-tagged files) MUST return errors to the
  caller rather than terminating directly.
- Errors presented to the user MUST include enough context to understand
  what operation failed and why (e.g., file path, hostname, DNS server).

**Rationale**: Internal `os.Exit` calls make code untestable, prevent
cleanup logic from running, and cause execution to continue past error
points when deferred. Centralizing exit decisions in `main` produces
predictable, debuggable control flow.

### V. Simplicity and Single Purpose

This tool does one thing: update the local hosts file with DNS entries
resolved from a specified DNS server. Every design decision MUST favor
the simplest approach that satisfies the requirement.

- The tool MUST remain a single-binary CLI with no external
  configuration files, services, or daemons.
- Features MUST be justified by a concrete user need, not speculative
  future use. YAGNI (You Aren't Gonna Need It) applies.
- Dead code, unused exports, and speculative abstractions MUST be
  removed. If code is not called, it does not belong in the repository.
- The CLI interface MUST remain straightforward: subcommand + flags.
  No interactive prompts, no TUI, no config file parsing.

**Rationale**: Complexity is the enemy of reliability. A tool that
modifies a critical system file must be small enough to reason about
completely and audit quickly.

### VI. Test-Driven Development

All new and refactored code MUST be developed using a test-driven
development (TDD) approach. Tests are not an afterthought — they are
the specification that drives implementation.

- Tests MUST be written before the implementation code they verify.
  The Red-Green-Refactor cycle is mandatory: write a failing test,
  write the minimum code to make it pass, then refactor.
- Every exported function and every function with non-trivial logic
  MUST have corresponding test coverage.
- Functions that interact with external resources (filesystem, DNS,
  network) MUST be designed to accept interfaces or parameters that
  enable testing with fakes, stubs, or in-memory implementations.
  Direct calls to OS-level I/O from business logic are prohibited.
- Platform-specific code MUST have tests that verify the function
  contract (correct return values, correct error conditions) on each
  supported platform.
- Test files MUST follow Go conventions: `*_test.go` in the same
  package as the code under test.
- `go test ./...` MUST pass with zero failures before code is merged.

**Rationale**: This tool modifies a critical system file. Untested code
is untrustworthy code. TDD ensures that every behavior is verified,
every error path is exercised, and regressions are caught immediately.
It also enforces the interface-based design required by Principle IV
(idiomatic error handling) and makes the codebase safe to refactor.

## Dependency Governance

This section codifies the external dependency policy from Principle II
into an auditable process.

| Source | Status | Condition |
|--------|--------|-----------|
| Go standard library | Always permitted | N/A |
| `golang.org/x/*` | Permitted | Must solve a problem stdlib cannot |
| `dev.emberkom.com/*` | Permitted | Must solve a problem stdlib cannot |
| All other sources | Prohibited by default | Requires written justification, code review approval, and an entry in this table |

### Currently Approved External Dependencies

None. All external functionality is provided by `golang.org/x/net/dns/dnsmessage` (covered by the `golang.org/x/*` blanket approval above).

## Development Standards

- **Formatting**: All Go source files MUST be formatted with `gofmt`.
  No exceptions.
- **Vet/Lint**: `go vet` MUST pass with zero findings before code is
  merged. Additional linting (e.g., `staticcheck`) is encouraged.
- **Testing**: All new and refactored code MUST have test coverage
  written before the implementation (TDD). Functions that interact with
  the filesystem or DNS MUST be designed to accept interfaces or
  parameters that allow testing with fakes/stubs. `go test ./...` MUST
  pass with zero failures before merge. See Principle VI for the full
  TDD policy.
- **Build tags**: Platform-specific code MUST use Go build tags
  (`//go:build windows`, etc.) and MUST implement identical function
  signatures across all supported platforms.
- **Commit messages**: Follow conventional commit format
  (e.g., `fix:`, `feat:`, `refactor:`, `docs:`).

## Governance

This constitution is the authoritative source of project standards for
ekdns. It supersedes informal conventions, ad-hoc decisions, and
prior practices that conflict with its contents.

- **Amendment process**: Any change to this constitution MUST be
  documented with a version bump, a rationale for the change, and an
  update to the Sync Impact Report at the top of this file.
- **Versioning policy**: This constitution follows semantic versioning.
  MAJOR for principle removals or redefinitions, MINOR for new
  principles or materially expanded guidance, PATCH for clarifications
  and non-semantic refinements.
- **Compliance review**: All pull requests and code reviews MUST verify
  that changes comply with the principles defined here. Violations MUST
  be resolved before merge, or the constitution MUST be amended first.
- **Dependency audits**: When dependencies are added or upgraded, the
  reviewer MUST verify compliance with Principle II and the Dependency
  Governance table above.

**Version**: 1.1.1 | **Ratified**: 2026-03-03 | **Last Amended**: 2026-03-04
