Repository navigation
Releases: CodexSploitx/uniora
Release list
v1.1.0
What's Changed
- Release 1.1.0: row-level security by team (is_team_member, is_team_manager) by @CodexSploitx in #117
- docs(claude): read and keep session.md by @CodexSploitx in #118
Full Changelog: v1.0.0...v1.1.0
v1.0.0
What's Changed
- Release 0.15.0: RLS owner bypass docs, doctor RLS check, Next.js security update by @CodexSploitx in #114
- fix(deps): systeminformation 5.33.18 (high advisory blocking the 0.15.0 release) by @CodexSploitx in #115
- Release 1.0.0: first stable release by @CodexSploitx in #116
Full Changelog: v0.14.1...v1.0.0
v0.14.1
What's Changed
- chore: Apache-2.0 license and OSS Scanner enrolment files by @CodexSploitx in #100
- feat(site): redesign the landing with the official brand, gold lasers and EN/ES by @CodexSploitx in #101
- fix(site): stamp css/js URLs with the build (cache busting) by @CodexSploitx in #102
- chore(deps): Bump actions/setup-node from 7.0.0 to 7.1.0 by @dependabot[bot] in #91
- chore(deps): Bump actions/deploy-pages from 4 to 5 by @dependabot[bot] in #88
- chore(deps): Bump actions/upload-pages-artifact from 3 to 5 by @dependabot[bot] in #89
- chore(deps-dev): Bump eslint-config-next from 16.3.8 to 16.4.0 by @dependabot[bot] in #96
- chore(deps): Bump @tabler/icons-react from 3.48.0 to 3.49.0 by @dependabot[bot] in #95
- chore(deps): Bump express from 5.2.1 to 5.3.0 by @dependabot[bot] in #94
- chore(deps): Bump nodemailer from 10.0.15 to 10.1.0 by @dependabot[bot] in #93
- chore(deps): Bump next from 16.3.8 to 16.4.0 by @dependabot[bot] in #98
- chore(deps): Bump actions/configure-pages from 5 to 6 by @dependabot[bot] in #90
- chore(deps-dev): Bump smtp-server from 3.19.17 to 3.19.23 by @dependabot[bot] in #92
- chore(deps): Bump @base-ui/react from 1.8.0 to 1.9.0 by @dependabot[bot] in #99
- chore(deps): Bump shadcn from 4.21.1 to 4.22.0 by @dependabot[bot] in #97
- chore(deps-dev): Bump jsdom from 30.1.1 to 30.1.3 by @dependabot[bot] in #47
- chore(release): 0.14.1 by @CodexSploitx in #103
Full Changelog: v0.14.0...v0.14.1
v0.14.0
What's Changed
- docs: add the uniora-release skill (versioning and publishing) and keep uniora-api-sync about APIs only by @CodexSploitx in #85
- security audit: close trustedProxyHops/homoglyph/TeamService-power gaps, warn on policies.* collision, patch vitest RCE advisories by @CodexSploitx in #86
- chore(release): 0.14.0 by @CodexSploitx in #87
Full Changelog: v0.13.0...v0.14.0
v0.13.0
What's Changed
- docs: la skill uniora-api-sync exige la documentación de uso de cada cambio de API by @CodexSploitx in #83
- feat(features): store the kill switch's reason and return it per organization by @CodexSploitx in #84
Full Changelog: v0.12.0...v0.13.0
v0.12.0
What's Changed
- docs: skill uniora-api-sync — mantener siempre actualizadas las APIs de UNIORA by @CodexSploitx in #81
- feat(server): perfiles por la API HTTP (PUT /v1/profiles, perfil en lecturas de miembros, ownerProfile) y release 0.12.0 by @CodexSploitx in #82
Full Changelog: v0.11.0...v0.12.0
v0.11.0
Merge pull request #80 from CodexSploitx/claude/sharp-lamport-ytb3fr feat(profiles): store name, email and avatar per identity, search by them, and release 0.11.0
v0.10.0
0.10.0 - 2026-10-11
Includes new migrations: Postgres 0043, 0044 and 0045, SQLite 0028, 0029 and 0030 (run uniora migrate). They only add tables: the API credentials (uniora_api schema in Postgres, uniora_api_* tables in SQLite), the shared rate-limit buckets (uniora_api.rate_limits) and the webhook endpoints and deliveries (uniora_webhooks schema, uniora_webhook_* tables). Nothing existing changes.
Added
@uniora/server: UNIORA as its own self-hosted API. Your backends call it over HTTP with an API key; your auth provider stays in your project. Node http with no framework. Keys (uniora_sk_…) are stored as SHA-256, compared in constant time and never cached; a client has scopes and an organization list, and every route has exactly one scope. Rate limits per key, concurrency caps, body/time limits, slow-client timeouts and a failed-authentication throttle. Strict input (unknown fields refused), shaped output, application/problem+json errors with stable codes and never an internal message. It refuses to start without migrations, and off loopback without TLS or a declared TLS proxy. /healthz, /readyz, read-only mode, JSON logs that never carry a key.
Decisions and reads (check, check:batch, authorize with session/context/stepUp, snapshots; organizations, members, roles, permissions, features, teams, audit log).
Delegated changes on behalf of an end user (Uniora-Actor-* headers, actor:assert scope): members and roles, teams, policies and invitations. The access, team and policy services apply their rules to that user, over a guarded storage, and every audit entry carries metadata.via = { apiClientId, keyId, requestId } inside the hash chain. If-Match/ETag for optimistic concurrency.
Sign-up: POST /v1/organizations creates an organization with its first Owner; an Idempotency-Key makes a retry safe (the ids are derived from the client and the key, so the organization itself is the record).
Invitations: create, resend, revoke, and the preview/accept flow your server relays.
API credentials in core (createApiCredentialService, authenticateApiKey, storage for memory, Postgres and SQLite with a shared conformance suite): clients, keys (two active at once, for rotation), audit entries without secrets.
createAuditContextStorage: stamps every audit entry written through a storage with a reserved via object.
@uniora/client: a typed client generated from the route table, with timeouts, retries only where they cannot repeat a change, an automatic Idempotency-Key, paginate(), and createRemoteEngine(), an AuthorizationEngine over HTTP so the Express and Next guards work unchanged (fails closed; a test compares it with the local engine).
CLI: uniora server clients|keys|start.
Studio: an API clients section: create clients with scopes grouped by category and presets, create keys (shown once), rotate, revoke, disable; the new audit actions in the activity feed.
Documentation: guides/server.md, and guides/server-api.md and guides/openapi.json, generated from the route table; every example in the reference is executed against a real server in CI and the files are diffed, so they cannot go stale. Design: design/0001-uniora-server.md.
Audit action names: api_client.created|updated|disabled|enabled, api_key.created|revoked, webhook_endpoint.created|updated|enabled|disabled|secret_rotated|deleted, webhook_delivery.requeued.
@uniora/server: verified end users. actorTokens lists the identity providers whose tokens the server believes (issuer, audience, pinned algorithms, JWKS or secret, optional subject claim, lifetime cap and acrLevels); a delegated call can send Uniora-Actor-Token instead of asserting the actor, under the new actor:verified scope, and requireVerifiedActors refuses asserted actors altogether so a leaked key cannot impersonate anybody. Decisions accept the token too: authorize takes the session facts (auth_time, amr, acr) from what the provider signed. No algorithm confusion, keys only from the configuration, a JWKS cache that cannot be made to hammer the provider, 401 actor_token_invalid for every refusal.
@uniora/server: platform administration over the API. /v1/platform/... (15 operations: platform roles and members, listing and suspending organizations, support access), scope platform:admin on a client with every organization, always the operator's own verified token from a platform.providers provider, and a step-up rule read from that token (auth_time recent, amr with mfa, optional assurance level): 428 platform_step_up_required otherwise. Platform audit entries carry via.
@uniora/server: machine tokens. machineTokens accepts OAuth 2.0 client_credentials access tokens from your own identity provider in Authorization: Bearer, mapped subject → API client. The client's scopes and organizations are the ceiling; the token's scope only narrows. Disabling the client cuts the machine off at once. @uniora/client takes accessToken (a token or a function renewed per attempt).
Webhooks. @uniora/core: WebhookStorage (memory, SQLite, PostgreSQL, shared conformance suite), createWebhookService, Standard-Webhooks signing and verifyWebhook, URL and IP policy (parseWebhookUrl, isPublicIp). @uniora/server: a dispatcher that turns outbox events into per-endpoint deliveries, signs them, retries with backoff (Retry-After honoured), rotates secrets with a grace period, parks the hopeless as dead and disables an endpoint that keeps failing; the HTTP client only reaches public addresses (checked on every delivery against what the name resolves to), never follows a redirect and reads a few KB. uniora webhooks create|list|show|update|enable|disable|rotate-secret|delete|deliveries|requeue|test|run.
A rate limit shared between instances (sharedRateLimit): one token bucket per API key in the credential storage, leased in small chunks so the database is touched once per lease; falls back to per-process limiting if the storage fails.
uniora.config.mjs server section: uniora server start takes tokens, machine tokens, platform, webhooks, invitations, limits and the shared limiter from the config file (flags win).
The access, team, policy and invitation services take outbox: true to enqueue an event for every change; createPlatformAuditContext; ApiPrincipal.credential.
Studio: a Webhooks section (create, edit, enable/disable, rotate the signing secret with a grace period, delete, latest deliveries, send a dead delivery again; the secret is shown once), and the platform:admin and actor:verified scopes in the API clients screen.
Fixed
Three independent security reviews of the server were fixed. In the request pipeline: /readyz shared one probe between callers (it was an unauthenticated way to exhaust the database pool); only our own error codes become a client error (a driver's SQLITE_BUSY or ERR_INVALID_URL used to answer 400 with its code); If-Match: "0" is a 400, not a 500; slow-client timeouts are enforced when configured (Node checked every 30 s); the TLS-proxy guard is per listener and accepts HTTPS and a list; graceful shutdown no longer waits for keep-alive connections; a failure after a 503 timeout is logged; a throwing logger cannot crash the process; requests are routed on the raw path (no //x/v1/..., dot segments or %2e%2e); an IPv6 client is throttled by its /64; impossible dates (02-30, T24:00) are refused; ?proto= is reported; [::1] and 127.999.0.1 are told apart. In the routes and the domain: the in-memory storage let a role id be reused (it could replace the Owner role or another tenant's role); callers no longer choose the id of roles, teams or team memberships; unregistered permission keys are 404 permission_not_found on every backend (SQLite leaked SQLITE_CONSTRAINT_FOREIGNKEY); the invitation permission check runs before anything about roles and teams is revealed; the reserved identity providers are matched case-insensitively; delivery errors scrub the invitation token however a sender echoes it; page sizes can no longer silently truncate; declared bounds match the domain's; engine.onDecision is refused by the server. Client, CLI and Studio hardening from the third review. Reviews of the new surfaces (platform, machine tokens, webhooks) were fixed too: platform organizations can be paged; a machine token with no scope claim gets none (unless the provider opts in) and a subjectClaim other than sub requires requireClaims; support access needs an explicit supportGrantablePermissions; a suspended operator cannot keep a grant opened in a race; a burst against a receiver that blinked no longer switches a feed off and does not lose events; an event id that is not a valid header, a name server that never answers and a 2xx that never ends can no longer stall the dispatcher; the invitee's address no longer reaches an event through a sender's error; verifyWebhook refuses a non-numeric tolerance; the SSRF list also covers the Azure WireServer, SIIT and local-use NAT64 addresses and names with a trailing dot.
createMemoryStorage().organizations.create replaced an existing organization when the id was repeated; it now rejects it like the databases do.
v0.9.0
Merge pull request #75 from CodexSploitx/claude/policies-phase-1-6x4amw chore(release): 0.9.0
v0.8.0
What's Changed
- Anti-escalada al dar roles en la organización (AccessAdminService) by @CodexSploitx in #66
- fix(postgres): suspender con fecha de fin a pocos ms ya no falla de forma intermitente by @CodexSploitx in #70
- chore(release): 0.8.0 by @CodexSploitx in #71
Full Changelog: v0.7.0...v0.8.0