Skip to content

The portal

The portal is where contracts and implementations live for other people to use. It is optional: a task coming from a directory in your own repository, resolved by path, needs no portal at all. That is how a worker is written before it is published.

When there is one, it holds two things: the catalogue, and who may write to it.

Terminal window
export OREN_REGISTRY=https://your-portal

Or, in the project, .oren/config.json — which gets committed when a team shares the same catalogue. See Installation.

The portal is for resolving, not for running. After oren install, nothing touches the network again: it is oren.lock that guarantees a run does not depend on the portal being up. See Reproducibility.

Terminal window
oren login
Open in your browser: https://your-portal/dispositivo
and enter the code: WDJB-MJHT
waiting for authorisation…
✓ signed in as you

This is the device flow (RFC 8628): the CLI shows a short code, you authenticate in the browser, and the CLI waits for approval. The CLI never sees your password — that is what allows a password manager, a second factor and a federated account, none of which fit in a terminal prompt.

What stays on your machine is a revocable token, in ~/.oren/credenciais.json with mode 600. One per registry, so machines talking to different portals do not get confused.

If whoever hosts the portal configured one, the sign-in screen shows a button for it — and only then. A portal with no provider shows only the password form.

Any OpenID Connect provider works; it is configuration, not code:

spring.security.oauth2.client.provider.oidc.issuer-uri=https://idp.example/realms/acme
spring.security.oauth2.client.registration.oidc.client-id=oren-portal
spring.security.oauth2.client.registration.oidc.client-secret=...
spring.security.oauth2.client.registration.oidc.scope=openid,email,profile
spring.security.oauth2.client.registration.oidc.client-name=Sign in with Acme

The identity is the (issuer, subject) pair from the token, not the e-mail: sub is stable and opaque, while an e-mail changes when someone changes surname, team or domain.

If the e-mail already has a local account here, the provider’s identity is linked to it automatically only when the provider states it verified the address. Otherwise you sign in with your password once and link it from your account page — a provider that does not verify addresses would otherwise let anyone who registered your e-mail there into your account here.

Local accounts keep working either way. Combining both — a password and a provider on the same account — is supported, and managed under Account → Sign-in methods. That is also where the link refused above is completed: sign in with your password, then link the provider from there, where owning the account has already been proven by the session.

Unlinking is refused when it is the only way left in. An account created by the provider has no password, and there is no recovery path — the portal sends no e-mail.

Two alternatives, when the browser is not at hand:

Terminal window
oren login --token # paste a token created in the interface
echo $TOKEN | oren login --token

In CI you use neither: OREN_TOKEN with a token issued beforehand.

The CLI never asks for a password. That path existed and was removed: with SSO in the portal, a federated account has no password to type.

Publishing requires membership in an organisation, with role publicador or admin. Its namespace is what appears in every reference: techlite/analyze-commits.

An account and an organisation are different things. Creating the account techlite does not create the organisation techlite — whoever tries to publish without it gets organizacao.nao_encontrada.

The organisation is created in the interface, under Account → Organisations. Whoever creates it becomes admin.

Role What it can do
leitor see the organisation’s private catalogue
publicador publish new versions
admin on top of publishing, manage who joins

The namespace is immutable. It appears in every oren.yaml that references a task of yours, and renaming would break all of them.

A task can have maintainers. When it does, only they publish it — even other publishers of the organisation.

It restricts, never grants: whoever does not publish in the organisation does not start publishing by becoming a maintainer. And having no maintainer means no restriction, not the opposite — otherwise the first run of that rule would lock every task that already exists.

It also serves to reserve: assigning a maintainer to a task that has no version yet guarantees nobody publishes the v1 in the right team’s place.

Terminal window
oren publish ./my-worker --dry-run # what would go out
oren publish ./my-worker

The directory needs a task.yaml, and implementations come from impl.yaml or from impl-<variant>/impl.yaml.

The contract always goes first: an implementation is only accepted if the contract it satisfies already exists in the catalogue.

Implementations with build: are refused — whoever consumes it would receive a reference to a directory that does not exist on their side. Publish the image and swap it for image:. See Publishing.

Three things, all because of whoever already depends on it:

A published version is immutable. There is no --force and no republishing. To fix one, bump metadata.version and publish again. It is what lets oren.lock promise that the same pipeline runs the same code.

Published is not deleted, it is deprecated. A deprecated version stays resolvable and keeps delivering the same content; the CLI only warns when it is used.

Private can become public; the other way, no. A private task is visible only to the organisation. Making it public is a decision with no way back — removing it later would break every pipeline that started referencing it. The database refuses the inverse operation, not just the interface.

Terminal window
oren token list
oren token revoke <id>

The plain value appears once, at issue time, and never again — the server keeps only the hash. The list shows the prefix, the description and the last use, which is how a token forgotten in an old runner is found.

Revoking is immediate and permanent. oren logout is a different thing: it forgets the local credential and leaves the token valid on the server.

The portal is a jar and a Postgres. Same software, not a cut-down edition — nothing leaves your network, and a private task stays private because the server is yours.

It serves everything (interface and API) under a configurable prefix, so it can live alongside other applications behind the same proxy:

server.servlet.context-path=/oren