Released v1

This commit is contained in:
Steve Cliff
2026-02-12 10:37:19 +00:00
commit b07572fed5
77 changed files with 19518 additions and 0 deletions
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-02-11
@@ -0,0 +1,43 @@
## Context
pcli currently authenticates to the Planka API using two mechanisms:
1. **Bearer token**`Authorization: Bearer <jwt>` header on every request
2. **OIDC mode** — Bearer token + `httpOnlyToken` cookie sent together
Both rely on session-based JWTs obtained externally. The `Client` struct carries both `Token` and `HttpOnlyToken` fields, and the `Do()` method conditionally attaches the cookie. The CLI exposes `PLANKA_TOKEN`, `--token`, `PLANKA_HTTP_TOKEN`, and `--http-token`.
Planka now supports user-level API keys authenticated via the `x-api-key` header. This is simpler, long-lived, and eliminates the dual-mode complexity.
## Goals / Non-Goals
**Goals:**
- Replace all authentication with a single `x-api-key` header
- Simplify the `Client` struct and constructor
- Rename env var to `PLANKA_API_KEY` and flag to `--api-key`
- Remove all OIDC/httpOnlyToken support
**Non-Goals:**
- Supporting both old and new auth simultaneously (no transition period)
- API key management (creation/rotation/deletion) via pcli
- Any changes to API endpoint paths or request/response formats
## Decisions
### Decision 1: Use `x-api-key` header directly
**Choice**: Set `x-api-key: <key>` header instead of `Authorization: Bearer <key>`.
**Rationale**: This is the header format documented by Planka for API key auth. Using the standard Planka format ensures compatibility.
**Alternatives considered**: Using `Authorization: Bearer <api-key>` — rejected because Planka's API key auth specifically uses the `x-api-key` header.
### Decision 2: Clean break, no backward compatibility
**Choice**: Remove `PLANKA_TOKEN` and `--token` entirely, replace with `PLANKA_API_KEY` and `--api-key`.
**Rationale**: Supporting both old and new env vars adds complexity for no real benefit. This is a CLI tool where users control their own environment. A clean break with clear error messages is simpler.
**Alternatives considered**: Supporting both `PLANKA_TOKEN` and `PLANKA_API_KEY` with deprecation warnings — rejected as unnecessary complexity for a CLI tool.
### Decision 3: Single field on Client struct
**Choice**: Replace `Token` + `HttpOnlyToken` fields with a single `APIKey` field.
**Rationale**: API key auth has no secondary credential. One field, one header, one code path.
## Risks / Trade-offs
- **Breaking change for all users** → Mitigated by clear naming (`PLANKA_API_KEY`) and error message that tells users what's needed. Users must generate an API key in Planka before upgrading.
- **API key shown only once at creation** → Not a pcli concern, but worth noting in README that users should store their key securely.
@@ -0,0 +1,31 @@
## Why
Planka now supports user-level API key authentication. The current pcli authentication uses session-based JWT tokens (via `Authorization: Bearer <token>`) with an optional OIDC httpOnlyToken cookie path. API keys are simpler, long-lived, and eliminate the need for multiple auth modes. Replacing the current auth with API key auth simplifies both the codebase and the user experience.
## What Changes
- **BREAKING**: Replace `Authorization: Bearer <token>` header with `x-api-key: <key>` header on all API requests
- **BREAKING**: Rename environment variable `PLANKA_TOKEN``PLANKA_API_KEY`
- **BREAKING**: Rename CLI flag `--token``--api-key`
- Remove `PLANKA_HTTP_TOKEN` environment variable support
- Remove `--http-token` CLI flag
- Remove `HttpOnlyToken` field from the `Client` struct and all OIDC cookie logic
- Simplify `NewClient` constructor to accept only base URL, API key, and logger
## Capabilities
### New Capabilities
(none)
### Modified Capabilities
- `api-client`: Authentication header changes from `Authorization: Bearer` to `x-api-key`. Client struct drops `HttpOnlyToken` field. `NewClient` signature simplifies. OIDC cookie logic removed.
- `cli-commands`: Root command global flags change: `--token``--api-key`, `--http-token` removed. Environment variable changes: `PLANKA_TOKEN``PLANKA_API_KEY`, `PLANKA_HTTP_TOKEN` removed.
## Impact
- **Code**: `client/client.go` (struct, constructor, `Do()` method), `cmd/root.go` (flags, env vars, client init)
- **Users**: All existing users must update their environment variables and any scripts from `PLANKA_TOKEN` to `PLANKA_API_KEY` and generate an API key in Planka
- **Dependencies**: No dependency changes
- **API**: No Planka API endpoint changes — only the authentication mechanism used by pcli changes
@@ -0,0 +1,35 @@
## MODIFIED Requirements
### Requirement: Base HTTP client
The system SHALL provide a base HTTP client that sends requests to the Planka API. The client SHALL construct URLs by joining the configured base URL with the API path. The client SHALL attach an `x-api-key: <key>` header to every request. The client SHALL send and receive JSON (`Content-Type: application/json`). The client SHALL accept a `*slog.Logger` and log every request at DEBUG level with method, path, status code, and duration. The client SHALL log errors at WARN level.
#### Scenario: Successful API request
- **WHEN** the client sends a request to a valid endpoint
- **THEN** the response body SHALL be returned as parsed JSON
- **AND** the request SHALL include the `x-api-key` header
- **AND** a DEBUG log entry SHALL be emitted with method, path, status, and duration
#### Scenario: API returns error status
- **WHEN** the API responds with a 4xx or 5xx status code
- **THEN** the client SHALL return an `APIError` containing the HTTP status code and response message
- **AND** a WARN log entry SHALL be emitted
#### Scenario: Network failure
- **WHEN** the HTTP request fails due to a network error (connection refused, timeout, DNS failure)
- **THEN** the client SHALL return a Go error wrapping the underlying network error
### Requirement: Authentication from environment
The system SHALL read `PLANKA_URL` from the environment to determine the API base URL. The system SHALL read `PLANKA_API_KEY` from the environment to determine the API key. Global flags `--url` and `--api-key` SHALL override the corresponding environment variables. Flag values SHALL take precedence over environment variables.
#### Scenario: Auth from environment variables
- **WHEN** `PLANKA_URL` and `PLANKA_API_KEY` are set in the environment
- **AND** no `--url` or `--api-key` flags are provided
- **THEN** the client SHALL use the environment variable values
#### Scenario: Flag overrides environment
- **WHEN** `--url` or `--api-key` flags are provided
- **THEN** the flag values SHALL take precedence over environment variables
#### Scenario: Missing configuration
- **WHEN** neither the environment variable nor the flag is set for URL or API key
- **THEN** the system SHALL print an error message and exit with code 1
@@ -0,0 +1,22 @@
## MODIFIED Requirements
### Requirement: Root command and global flags
The system SHALL provide a root command `pcli` that serves as the entry point. The root command SHALL register global flags: `--format` (string, default `json`, values `json` or `table`), `--url` (string, overrides `PLANKA_URL`), `--api-key` (string, overrides `PLANKA_API_KEY`), and `--log-level` (string, default `warn`, values `debug`, `info`, `warn`, `error`). The root command SHALL initialize the logger based on `--log-level` and configure it to write structured JSON to stderr. The root command SHALL validate that URL and API key are available (from flags or environment) before executing any subcommand.
#### Scenario: Display help
- **WHEN** `pcli` is run with no arguments or `--help`
- **THEN** the system SHALL display usage information listing all resource subcommands and global flags
#### Scenario: Invalid format flag
- **WHEN** `--format` is set to an unsupported value
- **THEN** the system SHALL print an error and exit with code 1
#### Scenario: Log level controls output
- **WHEN** `--log-level=debug` is set
- **THEN** DEBUG-level log entries SHALL appear on stderr
- **AND** stdout SHALL contain only the command's data output
#### Scenario: Missing API key
- **WHEN** neither `PLANKA_API_KEY` environment variable nor `--api-key` flag is provided
- **THEN** the system SHALL print an error indicating `PLANKA_API_KEY` must be set via `--api-key` flag or `PLANKA_API_KEY` environment variable
- **AND** the system SHALL exit with code 1
@@ -0,0 +1,20 @@
## 1. Client Authentication
- [x] 1.1 Rename `Token` and `HttpOnlyToken` fields to single `APIKey` field in `Client` struct in `client/client.go`
- [x] 1.2 Update `NewClient` constructor to accept `(baseURL, apiKey string, logger *slog.Logger)` — remove `httpOnlyToken` parameter
- [x] 1.3 Replace `Authorization: Bearer` header with `x-api-key` header in `Do()` method
- [x] 1.4 Remove OIDC cookie logic (`httpOnlyToken` cookie attachment) from `Do()` method
## 2. CLI Flags and Environment Variables
- [x] 2.1 Rename `flagToken` to `flagAPIKey` and `flagHttpToken` removal in `cmd/root.go`
- [x] 2.2 Replace `--token` flag with `--api-key` flag and remove `--http-token` flag in `cmd/root.go`
- [x] 2.3 Replace `PLANKA_TOKEN` env var lookup with `PLANKA_API_KEY` in `PersistentPreRunE`
- [x] 2.4 Remove `PLANKA_HTTP_TOKEN` env var lookup from `PersistentPreRunE`
- [x] 2.5 Update error message to reference `PLANKA_API_KEY` and `--api-key`
- [x] 2.6 Update `NewClient` call site in `PersistentPreRunE` to match new constructor signature
- [x] 2.7 Remove OIDC-related debug log line (`oidc_mode` slog field)
## 3. Documentation
- [x] 3.1 Update `README.md` authentication section to reference `PLANKA_API_KEY` and `--api-key`