5.9 KiB
Development Policy
This document gives developers and LLM coding agents the concrete workflow for
changing weatherapi safely. Architecture invariants are defined in
docs/policy/architecture.md.
Repository Layout
| Path | Purpose |
|---|---|
cmd/weatherapi |
executable composition root |
internal/app |
read use cases, repository port, current-conditions model |
internal/adapters/inbound/httpapi |
route definitions, query binding, handlers |
internal/adapters/inbound/httpapi/presenter |
response payload shaping |
internal/adapters/outbound/postgres |
SQL reads and row mapping |
templates |
text response templates |
docs |
current documentation, policy, internals, integrations, roadmap |
examples |
copyable config and request examples |
Build and Test Commands
Build:
go build ./cmd/weatherapi
Run all tests:
go test ./...
Focused tests:
go test ./internal/app
go test ./internal/adapters/inbound/httpapi
go test ./internal/adapters/inbound/httpapi/presenter
go test ./internal/adapters/outbound/postgres
Private module access is required for feedapi and weatherfeeder downloads.
If tests fail because Go cannot fetch a private module, fix module access before
treating package tests as behavior failures.
Coding Conventions
- Keep
cmd/weatherapithin. - Keep application use cases independent of HTTP, SQL, renderers, and templates.
- Keep query validation in the HTTP adapter.
- Keep unit conversion, rounding, timezone presentation, and payload copy behavior in presenters.
- Keep SQL text, row structs, null handling, and UTC normalization in the Postgres adapter.
- Prefer small focused changes over broad refactors.
- Preserve contextual error wrapping in repository and runtime code.
Dependency Policy
Current direct dependencies are:
feedapifor config, DB registry, endpoint definitions, renderers, middleware, templates, and HTTP runtime;weatherfeederfor canonical model and standards types;github.com/lib/pqfor the Postgres driver.
Do not add dependencies for small conveniences. New dependencies need a clear adapter or domain purpose and should not leak through application boundaries unless they are the explicit boundary contract.
Adding or Changing Endpoints
- Add or update the
Servicemethod ininternal/adapters/inbound/httpapiif the handler needs a new application read. - Add or update the application repository port in
internal/app. - Implement the read in the Postgres adapter if needed.
- Add the endpoint definition and binder in
internal/adapters/inbound/httpapi. - Add presenter behavior in
presenterinstead of shaping payloads in handlers. - Add or update text templates when
format=textshould be supported. - Add endpoint tests for registration, query validation, formats, errors,
data: null, and representative payload behavior. - Update
docs/api.mdand examples when the public HTTP contract changes.
Changing Query Parameters
- Update binder functions and endpoint tests together.
- Preserve strict unknown-parameter rejection unless the route explicitly allows a new parameter.
- Keep timezone parsing limited to route families that support it.
- Keep precision range validation aligned with presenter rounding support.
- Update
docs/api.mdfor public query behavior changes.
Adding Config Fields
Config shape is loaded by feedapi. When weatherapi starts using a new config
field:
- update runtime composition or the relevant adapter;
- update
docs/config.md; - update examples under
examples/if operators need to set it; - add config/runtime tests where practical;
- avoid committing real credentials or private infrastructure details.
Adding CLI Flags
The executable currently supports only -config. If adding a flag:
- keep parsing in
cmd/weatherapi; - avoid putting business logic in
cmd; - document precedence with environment variables if applicable;
- update
docs/cli.md; - add tests when flag behavior is not trivial.
Changing Repository Reads
- Keep SQL in
*_queries.go. - Keep row DTOs in
*_rows.go. - Keep mapping/null handling in
*_mapper.go. - Return
nil, nilfor missing latest parent rows. - Normalize timestamps to UTC in mappers.
- Preserve child ordering from stored index columns.
- Update
docs/internal/postgres-repository.mdanddocs/integrations/weatherfeeder-postgres.mdwhen table or column assumptions change.
Changing Presenters or Templates
- Copy input values before conversion, rounding, or timezone changes.
- Preserve nil pointer and
omitemptybehavior. - Keep text-template helper fields out of JSON/XML when they are not public API fields.
- Check
templates/*.txt.tmplfor field references. - Update presenter tests and endpoint text tests.
- Update
docs/api.mdwhen response shape changes.
Updating Examples
Examples must be copyable, valid, and free of secrets.
- Config examples belong under
examples/config.*.yml. - HTTP examples belong in
examples/requests.http. - Do not include unimplemented routes.
- Re-run YAML syntax checks or config loading tests when config examples change.
Documentation Checklist
When behavior changes, update the canonical doc in the same change:
- README for project orientation and shortest useful command;
docs/api.mdfor public HTTP behavior;docs/config.mdfor YAML config;docs/cli.mdfor executable flags and environment variables;docs/operations.mdanddocs/troubleshooting.mdfor operator behavior;docs/internal/for implementation boundaries;docs/integrations/for external storage/runtime contracts;docs/roadmap/only for unimplemented work.
Do not describe unimplemented behavior outside docs/roadmap/.