Sanitized allowlisted snapshot of private source 0acd276fb3423405daf7fff26dedc92b8281e2bd. Adds organization, team, invitation, resource hierarchy, scoped access, and audited break-glass foundations while preserving Preview 1. AI-Assistance: OpenAI Codex assisted implementation, testing, security review, and release preparation. Signed-off-by: Cole Speelman <crspeelman@gmail.com>
This commit is contained in:
@@ -9,6 +9,8 @@ analytics ──> requestlog ──> requestmeta
|
||||
abuse ─────────────────────> requestmeta
|
||||
authhttp ──> websec ───────> requestmeta
|
||||
authhttp ──> auth <───────── authsqlite
|
||||
organizations <───────────── authsqlite
|
||||
access <──────────────────── authsqlite
|
||||
```
|
||||
|
||||
An ordinary `net/http` application composes whichever branches it needs.
|
||||
@@ -19,6 +21,12 @@ Storage and reporting surfaces are interfaces so an application can retain its
|
||||
existing database and user interface while replacing one implementation at a
|
||||
time.
|
||||
|
||||
Authentication establishes one user identity and session. Organizations own
|
||||
projects, environments, and services; teams group organization members; scoped
|
||||
access resolves roles against that hierarchy. Existing `auth` roles remain a
|
||||
platform-level compatibility surface and do not implicitly grant access to an
|
||||
organization's data. Emergency access is a separate, expiring, audited grant.
|
||||
|
||||
The package model is developed from explicit threat and data contracts, not by
|
||||
moving an existing application's internals into a shared directory. See
|
||||
[ADOPTION.md](ADOPTION.md), [GETTING_STARTED.md](GETTING_STARTED.md), and the
|
||||
|
||||
@@ -17,13 +17,15 @@ install an imagined framework lifecycle around it.
|
||||
| Users, credentials, permissions, and sessions | `auth` | Roles, permissions, login UX, and account policy |
|
||||
| Secure browser cookies around `auth` | `authhttp` | Login routes, redirects, pages, and authorization decisions |
|
||||
| SQLite persistence for `auth` | `authsqlite` | Database placement, backup, migration approval, and recovery |
|
||||
| One account across organizations and teams | `organizations`, `authsqlite` | Invitation UX, organization naming, and lifecycle policy |
|
||||
| Organization-scoped authorization | `access`, `authsqlite` | Role definitions, resource ownership, and route enforcement |
|
||||
| Aggregate projections over request records | `analytics` | Collection policy, access control, report UI, and retention |
|
||||
|
||||
The packages are ordinary Go imports. Pin the current preview and verify its
|
||||
module checksum:
|
||||
|
||||
```bash
|
||||
go get gamertan.com/web/requestmeta@v0.1.0-preview.1
|
||||
go get gamertan.com/web/requestmeta@v0.1.0-preview.2
|
||||
go mod verify
|
||||
```
|
||||
|
||||
@@ -78,3 +80,7 @@ Deeper tutorials for accounts, analytics, and persistent abuse policy will be
|
||||
written after multiple application migrations have validated those seams. The
|
||||
preview documentation describes demonstrated contracts rather than prescribing
|
||||
an unfinished application framework.
|
||||
|
||||
See [Organizations and scoped access](ORGANIZATIONS.md) before storing tenant
|
||||
data. In particular, do not interpret a platform role as permission to inspect
|
||||
an organization's records.
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ import "gamertan.com/web/requestmeta"
|
||||
and request the containing module at an exact version:
|
||||
|
||||
```bash
|
||||
go get gamertan.com/web/requestmeta@v0.1.0-preview.1
|
||||
go get gamertan.com/web/requestmeta@v0.1.0-preview.2
|
||||
```
|
||||
|
||||
Only imported packages are compiled and linked. The packages nevertheless
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<!-- SPDX-License-Identifier: MPL-2.0 -->
|
||||
|
||||
# Organizations and scoped access
|
||||
|
||||
One `auth.User` may belong to many organizations without creating another
|
||||
credential or browser session. Organizations own projects; projects own
|
||||
environments; environments own application services. Teams are optional groups
|
||||
of active organization members.
|
||||
|
||||
`organizations.Service` creates those resources and issues digest-backed,
|
||||
expiring, single-use invitations. Acceptance verifies that the authenticated
|
||||
user's normalized email matches the invitation before activating membership.
|
||||
Applications own invitation pages, email or out-of-band delivery, organization
|
||||
deletion policy, and account recovery.
|
||||
|
||||
`access.Service` evaluates a permission against a complete resource scope:
|
||||
|
||||
```go
|
||||
decision, err := accessService.Authorize(ctx, principal.User.ID, access.Scope{
|
||||
OrganizationID: organizationID,
|
||||
ProjectID: projectID,
|
||||
EnvironmentID: environmentID,
|
||||
ServiceID: serviceID,
|
||||
}, "telemetry.read")
|
||||
```
|
||||
|
||||
A binding at organization scope covers its descendants. A narrower binding
|
||||
covers only its matching branch. The repository resolves team membership; a
|
||||
handler must never accept caller-supplied team identifiers as authority.
|
||||
|
||||
Platform roles in `auth.Principal` remain useful for installation health,
|
||||
account administration, and other explicitly global operations. They do not
|
||||
grant organization-data access. If an operator must inspect tenant data during
|
||||
an incident, use a reasoned break-glass grant. It expires within one hour and
|
||||
creates an append-only audit event in the same transaction.
|
||||
|
||||
The SQLite adapter namespaces all tables, enforces organization membership and
|
||||
resource ancestry before accepting a binding, and keeps invitations and
|
||||
sessions as digests. Applications remain responsible for database backup,
|
||||
filesystem ownership, retention, and presenting audit history to organization
|
||||
owners.
|
||||
@@ -10,7 +10,9 @@ selected storage adapters are trusted.
|
||||
Controls include explicit proxy trust, bounded parsing, cryptographic request
|
||||
and session identifiers, digest-only session storage, Argon2id passwords,
|
||||
constant-time comparisons, same-origin and CSRF primitives, fail-closed storage
|
||||
errors, and separate safe/sensitive analytics projections.
|
||||
errors, separate safe/sensitive analytics projections, organization-scoped
|
||||
bindings, single-use invitation digests, and short-lived audited break-glass
|
||||
grants.
|
||||
|
||||
Unsafe methods without an exact Origin or trustworthy same-origin Fetch
|
||||
Metadata fail the origin check. Authentication middleware fails closed when its
|
||||
@@ -22,6 +24,12 @@ configured reverse proxy, authorize application routes automatically, encrypt a
|
||||
compromised host, or decide how long an operator may lawfully retain personal
|
||||
request evidence.
|
||||
|
||||
Applications must pass the authenticated user and requested resource hierarchy
|
||||
to `access.Authorize`; possessing a platform-level `auth` role does not bypass
|
||||
that decision. Team membership is resolved by the repository rather than
|
||||
accepted from request input. Break-glass access lasts at most one hour and is
|
||||
not a substitute for ordinary role policy.
|
||||
|
||||
Local storage adapters assume the parent directory and host account are trusted.
|
||||
They reject a symlink at the configured final path and apply private file modes,
|
||||
but they do not defend against a concurrent privileged actor replacing path
|
||||
|
||||
Reference in New Issue
Block a user