Skip to content
Back to skills

Dotkernel Evolution Pattern

ASecurity

Use whenever a change would break something a client already depends on in a Dotkernel project — renaming or removing a field, parameter, route or template variable; changing a type, status code or response shape; making an optional field required; deprecating or deleting an endpoint — or when someone proposes a /v2, a version prefix, a version header, or "versioning the API". Also use when working with ResourceDeprecation, Sunset and Link headers, or the deprecation middleware.

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 7, 2026
developmentgophpapifrontenddocumentation

Works with

  • cli
  • api

Security analysis

A100/100

Scanned November 7, 2026

npx -y skills add dotkernel/dotboost --skill dotkernel-evolution-pattern --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Dotkernel Evolution Pattern?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Dotkernel Evolution Pattern
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/dotkernel-dotkernel-evolution-pattern/badge)](https://www.skillsdirectory.com/skills/dotkernel-dotkernel-evolution-pattern)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: dotkernel-evolution-pattern
description: >
  Use whenever a change would break something a client already depends on in a Dotkernel
  project — renaming or removing a field, parameter, route or template variable; changing a
  type, status code or response shape; making an optional field required; deprecating or
  deleting an endpoint — or when someone proposes a /v2, a version prefix, a version header, or
  "versioning the API". Also use when working with ResourceDeprecation, Sunset and Link headers,
  or the deprecation middleware.
---

# Evolution pattern, not versioning

```text
Applies to
  Projects:  - Dotkernel API
             - Dotkernel Admin
             - Dotkernel Frontend
             - Dotkernel Light
  Packages:  - none
```

Dotkernel prefers evolving one codebase over maintaining parallel versions. Breaking changes are
announced ahead of time and removed on a published date. Full rewrites and `/v2/` prefixes are a
last resort reserved for architectural change.

**Default answer to "should we add /v2?": no.** Propose an evolution path first. Escalate to
versioning only for genuinely architectural change (a different protocol or response paradigm),
and say explicitly that you are recommending an exception.

Scope note: the mechanics below (Sunset headers) are an API concern. In a templated project the same
*thinking* applies to route URLs, query parameters and anything a bookmark, integration or email
link depends on — but the announcement channel is a redirect and a changelog entry, not a header.

## Decision table

| Change | Approach |
| --- | --- |
| Fix a typo in a parameter name | Accept both for a period, deprecate the old. Versioning is overkill. |
| Add a response field | Just add it — additive changes are non-breaking. |
| Add a request parameter | Make it **optional** with a safe default. |
| Richer behaviour for richer input | Branch on the payload: old shape → old behaviour, new shape → enhanced. |
| Remove a field, change a type, tighten validation | Breaking. Deprecate with a sunset date, keep the old path until then. |
| Remove an endpoint or route | Deprecate with a sunset date; afterwards it answers 410 Gone (API) or permanently redirects (templated), and 404s once removed. |
| Move a page to a new URL (templated) | Serve it at the new URL and permanently redirect the old one straight away — the redirect is what keeps bookmarks and email links working. |
| Rework one endpoint fundamentally | A `v2` for **that endpoint only**, never the whole project. |
| A different response paradigm entirely | Genuine versioning. |

Old and new coexist for a reasonable window. The sunset date is a promise — do not shorten it
silently.

## Marking a deprecation (API-style projects)

Class-level attribute on the handler:

```php
#[ResourceDeprecation(
    sunset: '2099-01-01', // placeholder — use the real, future date agreed for this window
    link: 'https://docs.dotkernel.org/…/api-evolution/',
    deprecationReason: 'Replaced by GET /book/{id}/detail.',
    rel: 'sunset',
    type: 'text/html',
)]
class GetBookResourceHandler extends AbstractHandler
```

Mechanics:

- The deprecation middleware reflects the handler after dispatch and adds `Sunset:` and `Link:`
  response headers.
- Once the sunset date has passed, the middleware throws `ExpiredException` before the handler
  runs, and the endpoint answers `410 Gone` as problem details.
- `sunset` must be a valid date or the attribute constructor throws. It must also be in the
  future: a past date deprecates and kills the endpoint in the same change.
- If `link` is omitted, the middleware falls back to the documentation URL in
  `application.versioning` config.

Resulting response:

```http
HTTP/1.1 200 OK
Sunset: 2099-01-01
Link: https://docs.dotkernel.org/…;rel="sunset";type="text/html"
```

## Obligations that come with a deprecation

The attribute compiling is not "done". Also:

1. Mark the operation `deprecated: true` in the module's `OpenAPI.php` and name the replacement.
2. Update the documentation page describing the change and the recommended client update.
3. Note it in `CHANGELOG.md` (only if the user asks you to touch the changelog).
4. Add or extend a test asserting the `Sunset` header.
5. Keep the old path working until the sunset date. **Do not delete in the same change.**
6. Announce through the channels the project actually uses — headers, docs, release notes,
   newsletter — early enough for third-party developers to plan.

After sunset the endpoint already answers 410, so removal is a clean-up, not an emergency. Remove
the handler, its route, its authorization entry, its presentation metadata and its documentation
block in one later change: a removed endpoint should 404, not 500.

## Anti-patterns to flag

- `/v2/...` route groups, `?version=2`, or versioned media types added to a codebase that has
  chosen evolution.
- Renaming a response field in place "because the old name was wrong".
- Making an existing optional field required.
- Narrowing an enum or tightening a validator on a live route with no sunset window.
- Changing a success status code (200 → 204) on a live endpoint.
- Changing a route URL in a templated project without a permanent redirect from the old one.

If asked to do one of these, do it only after stating the breaking-change consequence and
offering the evolution alternative.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.