Umbrella development plan

Status: 0.10.1 released. Each release ships only when its tests pass on Linux and macOS, and every number on this site comes from recorded test results.

Decisions made

  • One program. A single aftermarket binary with a subcommand per tool. A tool gets its own binary only if it proves it needs one.
  • One repository. The code lives at github.com/aftermarket-dev/aftermarket, written in Go.
  • One rule style. Every tool uses the same YAML when: block to match traffic. The actions after it belong to each tool.
  • Open source. Apache 2.0.
  • A real test case. The old-client, new-API customer example from the introduction is the fixture the first releases are tested against.

0.1.0: AfterPatch (released)

A reverse proxy with YAML repair rules. It matches on method, path, query, headers, status code and content type. It can set or remove headers, rewrite paths, and rename, copy, set or delete JSON fields in requests and responses. It also has a dry-run mode, an audit log with secrets removed, a command that checks a rule file, and a command that runs a rule against a saved request and response.

The tests aim at the main promise, which is that a rule repairs one thing and breaks nothing else. Traffic no rule matches must come out byte for byte. Broken, oversized, compressed and chunked bodies must pass through safely. A slow or dead upstream must produce a clean error. And the example client must fail without its rule and work with it.

0.2.0: AfterAPI (released)

An aftermarket adapt command for bigger translations. Each old endpoint is written in terms of the new one: path and query parameters move into the new URL, request and response bodies are rebuilt from small templates, status codes and error bodies are mapped, and headers can be renamed. Credentials are never touched. A request or response that can’t be translated safely passes through exactly as it was sent.

The test is an old client’s full test suite of twelve checks. It passes against the old service, fails every check against the new one, and passes every check against the new one through adapt. AfterAPI stays a subcommand of the same program, since the code gave no reason to split it out. Fan-out, where one old call needs several new ones, is left for later.

0.3.0: AfterTest and AfterDiff (released)

aftermarket record is a proxy that changes nothing and saves each exchange as a fixture case. Credential headers and query keys are always blanked, and a config file can add more headers, query keys and JSON fields. aftermarket replay sends those fixtures to two versions of a service, compares status, headers and JSON by meaning, and lists every difference. It sends only reads unless told otherwise.

The test is the whole loop on the customer-api example. The old client’s twelve checks are recorded against v1. Replayed against v2 directly, all twelve answers differ. Replayed against v2 through adapt, all twelve are the same.

0.4.0: AfterConfig (released)

aftermarket config changes a vendor’s config file through an overlay, without ever editing the file. Each change can name the value it expects to find, so when an upgrade changes that value, apply stops and says where, instead of quietly overriding what the vendor changed. It reads JSON, YAML and .env files, writes the result to a separate file in one step, and never writes the vendor’s file.

The test is a vendor config at 1.0 and 1.1 with an overlay of seven changes. On 1.0 all seven apply. On 1.1, which changed two of those defaults itself, apply stops at exactly those two lines and writes nothing.

0.5.0: AfterHook (released)

aftermarket hook watches places that change but never tell anyone: a file, a folder, an HTTP endpoint, or a command’s output, which is how it watches a SQLite table through the sqlite3 command. Each change goes out as a signed webhook. Events wait in a state file and are retried until delivered, in order, across restarts, and a repeat keeps its id so a receiver can drop it. The first check sets a baseline quietly, a file still being written waits, and values under secret-looking keys go out as REDACTED.

The tests aim at four promises. Every change gives exactly one event, counted against random changes. Nothing is lost while the receiver is down or across restarts. A source that didn’t change by meaning sends nothing. A half-written file is never reported.

0.6.0: AfterGuard (released)

aftermarket guard stands in front of an HTTP app that can’t protect itself. Rules use the same when: block, plus client address ranges and credentials, and a request no rule allows is refused. API keys and Basic logins are kept as hashes, rate limits and failed logins are limited per address in a table of fixed size, and any request that could be read two ways gets 400. A written threat model came first, and lists what AfterGuard defends against and what it doesn’t.

The tests aim at six promises: nothing ambiguous gets through, a denied request never reaches the app, allowed traffic passes byte for byte, limits hold and memory stays bounded, a client can’t choose its identity or address, and no secret reaches a log.

0.7.0: TOML for AfterConfig (released)

aftermarket config reads and writes TOML 1.0 files, the format of many newer tools. Changes are made on the vendor’s own lines, so comments, layout and every line the overlay doesn’t name stay byte for byte, and values keep their TOML type: a date stays a date and a float stays a float. When a change can’t be made on the lines, the file is written again from its values, still exactly right but without comments. AfterHook watches TOML files field by field too.

The test is the same vendor upgrade as in 0.4.0, written in TOML with comments and arrays of tables. On 1.0 exactly seven lines differ from the vendor’s file. On 1.1 apply stops at the same two lines. Random changes to generated files, and a fixed set of 22 changes to a file written by hand in every TOML spelling, check that every result reads back with exactly the intended values.

0.8.0: AfterSchema (released)

aftermarket schema keeps an old app’s SQL working after its SQLite database moved to a new schema. schema diff lists every change between two schemas and marks what breaks old readers. A mapping file describes each old table in terms of the new tables, and schema compat turns it into views, written to one .sql file to review and apply. schema check compiles the old queries against the new schema with the views, and schema test runs every old read on both databases and compares the rows exactly. Databases are only ever read, through the sqlite3 program. Views serve reads; writes through them, an apply step, PostgreSQL and MySQL are not part of this release.

The test is a shop app at 1.0 and 2.0 with a dozen old report queries. Only 1 of the 12 compiles on 2.0 alone. With the views, all 12 compile and give the same rows as on 1.0, and a map mistake such as forgetting that 2.0 keeps totals in cents fails half of them.

0.9.0: AfterBridge (released)

aftermarket bridge serves an old app’s CSV exports and SQLite files as a read-only JSON API. A source is one CSV file, the newest file in a folder by name, a SQLite table or one fixed query, with typed, renamed and hidden columns. Each is read into a snapshot in memory and read again when its file changes; a file still being written, cut off or broken is never served, and the last good version stays. Lists page and filter by exact match, single rows are found by key, and only GET and HEAD are answered. Nothing in a request reaches SQL or the file system.

The test is an old shop app’s nightly orders exports and its inventory database. The tests rewrite an export in pieces while requests run, and every answer is one complete version; random values of every type read back exactly; and a recorder in front of sqlite3 shows that requests never start it.

0.10.0: live shadow mode for AfterDiff (released)

aftermarket shadow is replay on live traffic. It serves every request from the current service, the primary, unchanged, and once the answer has gone out it sends a copy to the new version, the candidate, and compares the two with replay’s comparison and ignore rules. Differences go into a report in replay’s format, rewritten as it grows. The candidate can never slow down or break the primary path: copies go through a bounded queue that drops and counts them when it’s full, with their own timeout, and a sampling rate can cut the share copied. The record config picks the traffic and keeps listed values out of the report.

The tests aim at four promises: answers are byte for byte the same with and without shadowing; a candidate that is down, slow, hanging or failing adds no wait and changes no answer; differences found live match what replay reports on the same traffic; and no credential reaches the report.

0.10.1 fixes five bugs an independent review found in shadow mode: copies cut off at stop listed as candidate errors, gzip headers compared differently from replay, a running report that only moved after a copy, answers outside when: missing from the counts, and a proxy credential sent on to the candidate.

After that

The next tool gets picked by what users actually need, not by filling in names. Nothing is planned yet; it is decided with the owner.

Afterlife and AfterTrace stay research for now. Afterlife will only ever replace documented APIs. AfterInstall, AfterDocs, AfterMock, AfterDeploy, AfterUpgrade and AfterPlugin are ideas, and listing them here isn’t a promise to build them.