The management UI
A Vue 3 single-page application (tagshape-ui-management-web) — the only part of the product that is not C#. It
is a client of the account, library set and audit APIs and holds no state of its own beyond the session.
Signing in
The UI does not authenticate anyone itself. An unauthenticated visitor is sent to the
auth UI, which runs the provider round-trip and drops an x-tagshape-auth
cookie. A background service renews the token before it expires, which is why the token also travels as a cookie
rather than a header alone.
The UI reads the permission catalogue from GET /permissions and its own permissions from the JWT, and hides what
the caller cannot use. That is presentation, not enforcement — every one of these pages is calling an endpoint
that checks the same permission server-side.
Pages
| Route | Page | Needs |
|---|---|---|
/ | Home — panes summarising the library and recent activity | Varies by pane |
/librarysets | Library sets list | VariableList |
/librarysets/:id | One library set, its variables and their values | VariableRead |
/librarysets/new | Create a library set | VariableCreate |
/taggroups | Tag groups list | TagGroupList |
/taggroups/:id | One tag group and its tags | TagGroupRead |
/tags | All tags across groups | TagList |
/variables | All variables across sets | VariableList |
/variablepreview | Resolve a set of tags and see which value wins | VariableRead |
/librarysets/import | Import a library file | BatchProcessingImport |
/users | Users list | UserList |
/users/:id | One account, its groups and its API keys | UserRead |
/groups | Groups list | GroupList |
/groups/:id | One group, its permissions and its members | GroupRead |
/organisations | Organizations list | OrganizationList (global) |
/organisations/:id | One organization — providers, branding, patterns | OrganizationRead (global) |
/audit | The audit log, filtered and paged | AuditList |
/profile | Your own account and your API keys | JWT only |
Notable pages
Variable preview
Pick library sets and tags, and see what a consumer would be handed. It calls
GET /variablevalues/preview, so each variable comes back as the whole winning value — its tags, whether it is
sensitive, and its hint.
This is the fastest way to diagnose an unexpected value: the tags on the winner tell you whether the problem is a mistagged value or a tag you forgot to ask for. See Resolution.
Library import
A file picker and a Monaco editor for reviewing the JSON before it is sent, plus a replace toggle. It reports the same summary the API returns, including what a replacing import deleted. See Importing a library.
Group
Permissions are offered by category, read from GET /permissions. The page uses the same catalogue's dependency
graph to keep a group from being saved with a permission that would do nothing — rather than keeping its own copy
of the graph, which would eventually disagree with the server's.
Permissions the caller cannot grant are shown but not editable, which matches the server's behaviour of preserving them on save.
Organization
Identity providers, logo and custom CSS. The Check credentials button calls
POST /organizations/identityproviders/check, which tries the credentials against the provider without saving
them — so a mistyped secret is found here rather than at somebody's login.
The custom CSS editor is a Monaco instance. Rules are filtered against an allow-list rather than injected wholesale.
Profile
Your own account, your linked identities, and your API keys. Creating a key is the one place the key itself is
ever shown — copy it then, because only its hash is stored. The never-expiring option appears only if you hold
ProfileNeverExpiresApiKey.
Audit
Paged and filtered against POST /filter. Entries whose before and after state you may not read are shown with
the state withheld rather than hidden, so you can see that something happened even where you may not see what.
Sensitive values in the UI
Sensitive values render as a masked input with a reveal control. Where the caller lacks VariableReadSecrets
there is nothing to reveal — the API returned an empty value — and the hint is shown instead. See
Sensitive values.
Running it locally
cd src/tagshape-ui-management-web
yarn install
yarn serve
Under the Aspire host it is started as ui-management with its API references wired up. See
Architecture.