This document provides essential information for AI agents working on the spelunk codebase.
spelunk is a Go library designed to extract secrets from various storage backends (Kubernetes, HashiCorp Vault, local files, environment variables, etc.).
- CRITICAL: Never git commit: unless explicitly instructed by the user, you must NEVER execute a
git commitautonomously. If you are unsure, ask the user. - Never leave this repository:
- All your "read" and "write" operations and all your tools should only be ever applied to this repo and its subdirectories
- Never access any of the files on the rest of this system
Before diving into the code, read ARCHITECTURE.md. It details:
- Core Concepts:
Spelunker,SecretCoord,SecretSource, andSecretModifier. - Execution Flow: How
DigUporchestrates fetching and modifying secrets. - Extensibility: How to implement new Sources and Modifiers.
Track the evolution of the project in CHANGELOG.md. It follows Keep a Changelog and Semantic Versioning.
The project uses the following tools for development and maintenance:
- Go: Language (v1.26+)
- Task: Task runner (replaces Makefiles)
- GolangCI-Lint: Linter (configured with
gci,gofmt,gofumpt,goimports,golines,swaggo) - Glow: Markdown renderer (for README)
- ASDF: Version manager (see
.tool-versions) - Pkgsite: For local documentation preview
All development tasks are defined in Taskfile.yaml. Always use task instead of direct go commands when possible.
| Command | Description |
|---|---|
task build |
Build the project |
task test |
Run all tests (alias for test.full). Supports -- <path> to test specific directories |
task test.full |
Run all tests with race detection and coverage. Supports -- <path> |
task test.short |
Run short tests (skips integration tests). Supports -- <path> |
task test.ci |
Run tests with coverage profile for CI. Supports -- <path> |
task lint |
Run linter |
task lint-fix |
Run linter and automatically fix issues |
task fmt |
Format code |
task run -- <args> |
Run the project (passes args to go run .) |
task dependencies.update |
Update and tidy Go modules |
task tools.plugins |
Install all necessary asdf plugins |
task tools.update |
Update all tools in .tool-versions to the latest available version via asdf |
task tools.install |
Install all tools pinned in .tool-versions via asdf |
task vuln |
Run govulncheck for vulnerability scanning |
task doc.serve |
Run local godoc server (pkgsite) and open in browser |
The project's CI pipeline (.github/workflows/ci.yaml) is driven entirely by task commands. This ensures that what you run locally matches what runs in CI.
- Build:
task build - Test:
task test.ci(generatescoverage.outused for step summary) - Lint & Format:
task lint-fix&&task fmt - Security Check:
task vuln
spelunker.go: Core logic for theSpelunkerstruct andDigUpmethod.types/: Core types and interfaces.coordinates.go:SecretCoordtype and parsing logic.source.go:SecretSourceinterface definition.modifier.go:SecretModifierinterface definition.errors.go: Common error definitions (ErrSecretNotFound, etc.).
builtin/: Built-in implementations.source/plain/:plain://source implementation.source/file/:file://source implementation.source/env/:env://source implementation.source/base64/:base64://source implementation.modifier/base64/:b64modifier implementation (Base64 encoding).modifier/base64_encoder/:b64ealias formodifier/base64/.modifier/base64_decoder/:b64dmodifier implementation (Base64 decoding).
plugin/: External plugins (opt-in).modifier/jsonpath/:jpmodifier implementation (JSONPath extraction).modifier/tomlpath/:tpmodifier implementation (TOML JSONPath extraction).modifier/xpath/:xpmodifier implementation (XPath extraction).modifier/yamlpath/:ypmodifier implementation (YAML JSONPath extraction).source/aws/:aws://source implementation (AWS Secrets Manager).source/azure/:az://source implementation (Azure Key Vault).source/gcp/:gcp://source implementation (Google Cloud Secret Manager).source/kubernetes/:k8s://source implementation (integration tested with Testcontainers).source/vault/:vault://source implementation (HashiCorp Vault KV).source/1password/:op://source implementation (1Password).source/bitwarden/:bw://source implementation (Bitwarden Secrets Manager). Note: currently untested due to lack of test environment.source/keeper/:kp://source implementation (Keeper Secrets Manager). Note: currently untested due to lack of test environment.
examples/: Example implementations (e.g.,kong/,viper/,urfave-cli/,basic/).docs/: Documentation assets (images, logos).options.go: Functional options for configuringSpelunker.doc.go: Package-level documentation.Taskfile.yaml: Task definitions..tool-versions: ASDF tool versions..golangci.yaml: Linter configuration..github/workflows/ci.yaml: CI configuration.
- Framework: Use testify (
require,assert) for all tests. - Scope: Use
spelunk_testpackage for black-box testing (e.g.,spelunker_test.go,types/coordinates_test.go). - Integration Tests: Use Testcontainers for Go for integration tests (e.g., Kubernetes, Vault, AWS, Azure, GCP). Use
testcontainers.CleanupContainerfor resource management. Useif testing.Short() { t.Skip("...") }to skip integration tests in short mode. - Execution: Run tests with
task test. You can test a specific directory by passing its path after--(e.g.,task test -- ./plugin/source/1password). - Linting: Ensure code passes
task lintbefore finishing. - Test Data: Use
testdata/directories for file-based tests. - Test Utilities: Use
internal/testutilfor reusable test mocks likeMockSource.
- Naming: Follow standard Go conventions (CamelCase, short variable names where appropriate).
- Error Handling: Wrap errors with context using
fmt.Errorf("...: %w", err). - Imports: Group standard library imports separately from third-party imports.
- Interfaces: Define interfaces where they are used (consumer-side), but
SecretSourceandSecretModifierare defined intypes/for clarity and reuse. - Type Safety: Ensure types implement expected interfaces with compile-time checks (e.g.,
var _ types.SecretSource = (*SecretSourceFile)(nil)). - JSON Marshaling:
SecretCoordimplementsencoding.TextUnmarshaler, allowing direct use injson.Unmarshal. - Markdown:
- Heading: always have an empty line before and after each heading
- Lists: Always use only one space between the number/dot and the text
- Code and quote blocks: Always place an empty line before and after each code or quote block
Based on CONTRIBUTING.md:
- Small and Steady: Keep changes small and focused.
- Sole Responsibility: You are responsible for every line of code.
- Know Your Code: Understand every design decision.
- Modifiers Application Order:
SecretCoord.Modifiersis a slice of key-value pairs ([][2]string). Modifiers are applied in the exact order they appear in the connection string URI. Duplicate keys are allowed and preserved. - Path Extractor Behaviors (
jp,yp,tp,xp):- These modifiers return the first element if the path matches a list.
- Expressions are compiled before querying to separate syntax errors from match errors.
- Floats (JSON/YAML/TOML): Converted to string without scientific notation and minimal necessary precision (e.g.
1.50000->1.5). - Nulls: Returns an error if the result is explicitly
null.
- Whitespace Trimming: By default,
Spelunkertrims whitespace from retrieved secrets after applying modifiers. This can be disabled viaWithoutTrimValue()option. - SecretCoord Parsing:
SecretCoord.Locationincludes both Authority (userinfo/host) and Path.- If a URI contains userinfo (e.g.,
plain://user:pass@host), it is correctly preserved inLocation.
- Trailing Slashes in URIs:
- For
k8s://andvault://, a trailing slash in the path instructs the source to return the entire secret data map as a JSON object instead of a specific key. - For
aws://,az://, andgcp://, trailing slashes are automatically stripped and ignored.
- For
- Error Types:
SecretCoordparsing returns specific errors (e.g.,ErrSecretCoordHaveNoType). Tests should check for these usingerrors.Is. - Dependencies: Ensure you have the correct Go version (1.26) as specified in
go.mod. - Integration Tests with Testcontainers: In case of integration test hangs, check for orphaned Docker containers. Use
testcontainers.CleanupContainereffectively to ensure resources are managed.