feat(14-01): sunscreen redacting slog handler installed by every generated main
- Wrap redacts sensitive keys at any depth and scrubs Bearer, sk- and x-api-key shapes - InstallDefault is the first statement of the generated run; hello main regenerated - surf test pins that recovered panics echo no credential - sunscreen README, root modules row and the logging docs page
This commit is contained in:
63
modules/sunscreen/README.md
Normal file
63
modules/sunscreen/README.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# sunscreen
|
||||
|
||||
Credential-redacting slog handler that keeps API keys, tokens and passwords out of application logs.
|
||||
|
||||
`import "git.golem15.com/golem15/summercms/modules/sunscreen"`
|
||||
|
||||
## Overview
|
||||
|
||||
`sunscreen` wraps any `log/slog` handler and rewrites every record before it is written: values of sensitive attribute keys become `[REDACTED]`, and credential shapes inside messages and string values are scrubbed. It is the SummerCMS counterpart of a Monolog tap that a WinterCMS application wires into its log channels to scrub contexts and messages. Every application `main` that `summer build` generates calls `sunscreen.InstallDefault(os.Stderr)` as its first statement, so the default logger, the standard `log` package and every plugin that falls back to `slog.Default` log through it from the start.
|
||||
|
||||
## Features
|
||||
|
||||
- Sensitive keys (`sunscreen.RedactedKeys`): `api_key`, `apikey`, `authorization`, `bearer`, `password`, `secret`, `token`, `webhook_secret`, `admin_password`, `openai_api_key`, `anthropic_api_key` and `perplexity_api_key`, compared case-insensitively at any group depth. The value of such an attribute becomes `sunscreen.Redacted`, whatever its kind.
|
||||
- Scrub patterns (`sunscreen.Scrub`): `Bearer <token>` becomes `Bearer [REDACTED]`, `sk-` followed by 20 or more key characters (dashed keys included) becomes `sk-[REDACTED]`, and `x-api-key: <value>` becomes `x-api-key: [REDACTED]`. The Bearer and x-api-key matches are case-insensitive.
|
||||
- Applied to the record message, string values, error values, byte slices and the formatted text of any other value; maps with string keys, such as `http.Header`, are redacted key by key.
|
||||
- `slog.LogValuer` values are resolved before redaction, groups are walked recursively, and attributes added with `WithAttrs` are redacted before they reach the wrapped handler.
|
||||
- `sunscreen.InstallDefault` builds a fresh text handler instead of wrapping the existing default, whose output goes through the `log` package that `slog.SetDefault` redirects back into the new handler.
|
||||
|
||||
## Usage
|
||||
|
||||
The generated `main` already installs it:
|
||||
|
||||
```go
|
||||
func run(args []string, out io.Writer) error {
|
||||
sunscreen.InstallDefault(os.Stderr)
|
||||
cfg, err := compass.Load("config")
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
To redact another handler, for example a JSON handler in a custom binary, wrap it:
|
||||
|
||||
```go
|
||||
logger := slog.New(sunscreen.Wrap(slog.NewJSONHandler(os.Stderr, nil)))
|
||||
logger.Error("vendor call failed", "api_key", key, "err", err)
|
||||
// {"level":"ERROR","msg":"vendor call failed","api_key":"[REDACTED]","err":"..."}
|
||||
```
|
||||
|
||||
Redaction is a safety net, not a licence: log ids and outcomes, never request bodies, tokens or arguments that carry them.
|
||||
|
||||
## API reference
|
||||
|
||||
| Identifier | Description |
|
||||
|------------|-------------|
|
||||
| `sunscreen.Wrap` | Returns a `slog.Handler` that redacts every record and every `WithAttrs` attribute before the wrapped handler sees it. Wrapping a sunscreen handler again returns it unchanged. |
|
||||
| `sunscreen.InstallDefault` | Makes a redacting text handler writing to the given writer the process default logger. |
|
||||
| `sunscreen.Scrub` | Replaces the Bearer, `sk-` and `x-api-key:` credential shapes in a string. |
|
||||
| `sunscreen.Redacted` | The replacement text, `[REDACTED]`. |
|
||||
| `sunscreen.RedactedKeys` | Returns a copy of the attribute keys whose values are always redacted. |
|
||||
|
||||
## Dependencies
|
||||
|
||||
- SummerCMS modules: none.
|
||||
- Third-party: none.
|
||||
- Standard library: `context`, `fmt`, `io`, `log/slog`, `reflect`, `regexp`, `slices`, `strings`.
|
||||
|
||||
## Testing
|
||||
|
||||
```sh
|
||||
go test ./modules/sunscreen/...
|
||||
```
|
||||
|
||||
The tests log through the handler into a buffer and need no external services.
|
||||
Reference in New Issue
Block a user