feat(contracts): initial implementation (v1.0.0)

Introduces code.nochebuena.dev/einherjar/contracts — the zero-dependency
foundation of the Einherjar framework. Defines the interfaces and minimal
types consumed by every starter. Zero external dependencies. Zero Einherjar
dependencies. Nothing is above it in the dependency graph.

lifecycle:
- Component — OnInit, OnStart, OnStop three-phase lifecycle hooks

observability:
- Level (LevelCritical=0, LevelDegraded); zero value is the safe default
- Checkable — HealthCheck, Name, Priority
- Identifiable — ModulePath, ModuleVersion; implemented by all starters to
  surface module identity and version in the startup banner

logging:
- Logger — Debug, Info, Warn, Error, With, WithContext

errs:
- CodedError — ErrorCode() string; satisfied by core/xerrors.Err
- ContextualError — ErrorContext() map[string]any; satisfied by core/xerrors.Err

security:
- Identity value type — UID, TenantID, DisplayName, Email; NewIdentity, WithTenant
- Permission (int64), MaxPermission=62, PermissionMask — Has, Grant
- PermissionProvider — ResolveMask(ctx, uid, resource) (PermissionMask, error)
- SecurityBag value type — immutable request-scoped security context; carries
  Identity and arbitrary typed attributes (hardware IDs, grant codes, etc.);
  With copies the attribute map on every call to preserve receiver-invariant behaviour
- NewSecurityBag, Identity, WithIdentity, Get, With
- SetBagInContext / BagFromContext — full bag context storage
- SetInContext / FromContext — backed by SecurityBag; all four cross-function
  combinations (SetInContext+BagFromContext, SetBagInContext+FromContext) are valid

One file per type; CT-6 enforced by compliance test AST walk.
This commit is contained in:
2026-05-29 15:43:08 +00:00
commit 098a2098f8
31 changed files with 2230 additions and 0 deletions

1
.gitea/CODEOWNERS Normal file
View File

@@ -0,0 +1 @@
* @einherjar/CoreDevelopers @einherjar/Agents

View File

@@ -0,0 +1,70 @@
## Summary
<!-- One or two sentences: what does this PR do and why? -->
---
## Type of change
- [ ] Bug fix — non-breaking change that resolves an issue
- [ ] New feature — non-breaking addition of functionality
- [ ] Breaking change — alters existing behavior or public API
- [ ] Documentation update
- [ ] Refactor — no functional change, no new API surface
- [ ] Test improvement
---
## Description
<!--
Provide enough context for a reviewer who was not in the room:
- What problem does this solve?
- What approach did you choose, and why?
- Were there alternatives you considered and rejected?
- Any known limitations or follow-up work?
-->
---
## Testing
- [ ] I added or updated tests that cover my changes
- [ ] All tests pass locally — `go test ./...`
- [ ] No formatting issues — `gofmt -l .` produces no output
- [ ] No vet warnings — `go vet ./...` is clean
---
## Checklist
- [ ] At most one exported type per non-test `.go` file (CT-6)
- [ ] No new external dependencies added without prior discussion in an issue
- [ ] Public API changes are reflected in `CHANGELOG.md`
- [ ] Breaking changes include a migration note in the PR description above
---
## Contributor License Agreement
> **This PR will not be merged until the CLA comment is present.**
Before a Maintainer reviews your code, you must post the following text **as a comment on this PR** — not here in the description. PR description checkboxes can be silently toggled by anyone; a comment is a timestamped, author-attributed record that cannot be quietly removed.
**Copy and post this exact text as a PR comment:**
---
> I have read the Einherjar Contributor License Agreement (CLA.md) and I agree to all its terms.
> I confirm this Contribution is my original work. I grant the Maintainers the rights described
> therein, including the right to relicense, and I retain ownership of my copyright.
> This agreement covers all future Contributions I submit to any Einherjar repository under
> this account.
---
First time contributing? Read [CLA.md](../CLA.md) for the full agreement before posting the comment.
If you are contributing on behalf of a company, an authorized representative of that company must post the comment.
<!-- Thank you for contributing to Einherjar. For those who come after. -->