An account here does exactly one job — it lets the engine say whose device is asking. Sign in now sits in the top bar of every page, and the pairing page asks for it before it shows you anything at all. The screens below are photographed off a running engine.
An account exists here for one reason: so the engine can tell whose device is asking. A service that only ever answers you has nothing to ask about, and never does.
Each Office pane carries a Settings card of the same shape — which engine this pane talks to, and whether this device is paired to it.
With DINNO_AUTH_MODE unset the gate runs off, every route is open, and that card
never asks you for anything.
Nothing asks you to sign in, and nothing asks you to pair. The pane, the panel and the service are all on one machine, so the service takes every caller at its word.
It answers several people. Before it does work for a plugin it has to know whose plugin that is, and that is the whole job of an account here.
Not a licence, not a profile, not a settings store. It is a name a device can be attributed to — and it is separate from your Windows account.
DINNO_PAIR_DEV_USER set. That is a developer bypass, fenced five ways: the variable, a
loopback caller, a process with no site sign-in, no reverse proxy in front, and enforcement not yet on. It
cannot function in a deployment.It is on every page now, top right beside the engine status — and it appears only when the engine actually has a provider.
Sign-in used to live only on /pair/ — which meant the one control you need before you can pair anything was reachable only from the page that refuses to work without it. It is now in the chrome of every page.
The slot is rendered from /pair/me, never from the build. An engine deployed with no
provider shows nothing there, because a Sign in button that answers 501 is worse than no
button.
It used to show the code form first, to everybody, so the refusal arrived only after the code had been read off another screen and typed in. The gate comes first now: sign in, and you land straight back here.
The form below it is hidden in the markup, not merely by script, so a page opened with JavaScript broken shows the explanation rather than a form that cannot submit.
One door — /pair/signin — and a gate in front of it that reads
/pair/me rather than guessing.
/pair/signin would
answer 501 and one line of plain text — site sign-in is not configured on this engine — so
the page reads that ahead of time, and says instead that until a provider is set up, pairing works only
from the machine running the engine.Not your Windows one — not while the engine is its own provider.
When the engine is its own provider you land on /idp/ — work e-mail, password, and back to
the page you came from. The session lasts ten hours and slides while you use it, so an ordinary working
day is one sign-in. Behind an external provider it is the usual redirect out and back, and the site
session is eight hours instead.
It is separate from your Windows account, and the page says so in its own first line. Unless the engine has been pointed at the company directory, the password you set here is a Dinno password and nothing else. Signing in is always a navigation you chose, never a redirect fired out of a background request, so nobody is bounced away mid-call.
Once per plugin per machine, about twenty seconds, and the only moment in this product where a browser window is part of the job. The pages are real and live here: Pair a device and My devices.
Settings → This device → Pair this device. The engine answers with an eight-character code and a countdown. Its alphabet contains no I, O, 0 or 1, so there is nothing to misread.
The code lives ten minutes and works once.
On /pair/, where you are signed in. Normally you type nothing: the plugin opens
the page with the code in the URL fragment, which never leaves the browser — not to the engine,
not to a log, not to a Referer header.
Typing it stays possible when the browser is on a different machine from the plugin.
Not “approve this code”, but the plugin type and the device's own label, read back out of the engine's store rather than out of the page in front of you.
If those two lines do not match the thing on your desk, the answer is No, cancel.
To that one device, and the plugin picks it up within a few seconds — there is nothing to copy back. Your password is never typed into the pane or the panel. The plugin never sees it and could not use it if it did.
Pairing, once. After that the plugin renews on its own.
My devices lists every plugin you have paired with this engine — what kind it is, the label it gave itself, when it was paired and when it was last seen — and revokes any one of them in a single press.
Marks the pairing revoked and kills the device's current refresh token outright, so it cannot renew. It is not reversible and does not need to be — the plugin simply asks to pair again. Do it when a laptop is handed on, reimaged or lost.
Under require, at once. The gate reads the pairing out of the store on every protected
call, so the device is refused on its next call rather than keeping the hours it was already given. A
pairing revoked anywhere stays revoked: when two instances of the engine write at once, the merge
always errs that way.
warn, revoking does not reach the device. Nothing is refused at
request time at all: the gate writes the revoked pairing to the log and serves the call anyway, and because
a plugin only refreshes after a 401, it never even asks to renew. A device revoked while the
engine is in warn keeps working until the mode changes. That is the measuring stage behaving
exactly as designed — but it means warn is not a security control.One value on the engine — DINNO_AUTH_MODE — decides whether any of this is
enforced. It is set where the engine is deployed. Nothing in your plugin changes it.
warn never reaches the device: the check runs,
the answer is written down, and the call is served regardless.require is
safe — and pairing during this window is real and worth doing.401 and a machine-readable reason, which the plugins turn into their re-pair flow. The
panel stops being quiet and says the engine now requires this device to be paired.off and logged as an error at startup. A typo
must not lock the field out, but it must not read as enforcement either, so /healthz
reports the effective mode and never what the environment literally said.require the site itself stays open. The gate protects by default
and opens a named list: the site pages, /healthz, the downloads, /pair,
/idp, /mcp, the two Office task panes, and the guides' figures and this site's
own. It has to be that
way — a sign-in page behind a sign-in is a locked door with the key inside.The engine can host its own directory, and there is no sign-up form in it. Every account starts as an invitation from someone already in. When the engine is its own provider, the user store is empty and a bootstrap address is configured, it creates one invitation for that address and writes it to a file beside the store.
Never to the log: an enrolment code is a credential, and logs are read by more people and kept for longer than anyone intends. Open it once, then delete the file.
/idp/#code=… — single-use, and it expires after
seven days. The code sits after the #, so the browser never sends it to the engine and
it cannot land in a request log; the page removes it from the address bar as soon as it has read it. Older
links in the ?code= form still work.Everything after the first screen is the same whichever way it goes.
engineThis process is the provider. The directory, the invitations, the passwords and the sign-in page are all its own. No client id and no secret are needed — the site and the provider are the same process, so there is nobody to prove anything to.
Entra's v2.0 endpoint in practice, so its tokens carry an object id. The engine's own directory is not loaded at all. It needs an app registration to exist — a client id and a tenant — which is the part IT provisions.
engine-oidcBuilt, and deliberately not the default. The engine is still the provider, but the site reaches it through a real OpenID Connect round trip instead of reading its cookie. The proven cookie path stays in use until this one has earned the swap.
DINNO_SITE_AUTHORITYChooses the engine's own provider —
engine or engine-oidc.DINNO_SITE_CLIENT_ID
and DINNO_ENTRA_TENANT_ID are both set, and has no sign-in at all when they are not./healthzNames which one is answering — engine,
engine-oidc, external or none.DINNO_SITE_AUTHORITY is not pointed at the
engine's own provider. Then the password is theirs and the engine never sees one at all.Each of these is a real edge of the account work today, named rather than left to be discovered.
POST /idp/invite exists — the person's
work e-mail in, the link back once, to the caller, and never logged — but nothing on this site puts a
button in front of it. Inviting someone is an API call today./pair/me first; that page does not yet.warn is not a security control. A device revoked while the engine is in
warn keeps working until the mode changes.DINNO_PAIR_DEV_USER, a
loopback caller, a process with no site sign-in, no reverse proxy in front, and enforcement not yet on.
It cannot function in a deployment.One to link a plugin to your account when the engine asks whose it is, and one to take it away again.