TSEC / Evaluate it
Evaluate TSEC in an afternoon
For the engineer or architect who has been handed this and asked for a verdict. It is time-boxed, it runs entirely in your own cluster, and it ends with a section telling you how to attack the thing and what should happen when you do. No account, no sales call, and nothing about your evaluation reaches us.
On this page
What you will have at the end
A working deployment in your own cluster where:
- a downstream application performs a real OIDC authorization-code login with PKCE;
- the login step is a flow you drew, not a configuration page you filled in;
- the first sign-in requires a second factor and the second does not, because the device was bound;
- and you can open the run log and read exactly which signals matched, what they weighed and which rule decided — for that specific session.
If you get to the end of step 4 and that last point isn't true, we have failed the evaluation and you should tell us so.
Before you start
You need: a Kubernetes cluster you can install into (kind, minikube, k3s or a real one), kubectl, helm 3.8 or newer for OCI support, and a browser. Postgres comes with the chart; point it at your own if you prefer.
Budget about four hours. Roughly 30 minutes to a running stack and the rest spent on the parts that actually tell you something.
Registry access. Images and the chart are published to GitHub Container Registry. If a pull returns 401 or 403, that is on us, not on your setup — email sales@tricaso.com and we will sort access out.
The builder needs a licence key. The authoring console is read-only without one, so an evaluation that includes building a flow needs a key from us. The runtime does not check a licence and never will, so anything you publish keeps running regardless. Ask for an evaluation key when you ask for registry access.
The walkthrough
1 Install the chart ~15 min
Generate a master key first. The chart will not render without one:
openssl rand -base64 32
helm upgrade --install tsec oci://ghcr.io/tricasollc/charts/tsec \
--version 26.10.0 \
--namespace tsec --create-namespace \
--set secret.masterKey="$(openssl rand -base64 32)" \
--set secret.databasePassword="$(openssl rand -base64 24)"
That brings up the runtime, the builder and Postgres. The OIDC server
(tsecAuth), the login front-end (tsecIdp), the SDK harness and the
mock user store all default to off — you turn on only what you are
assessing. We enable two of them in step 3.
One thing worth noticing while it comes up: that master key is not optional and not
defaulted. The chart refuses to render without it and rejects the old
CHANGE_ME_… placeholder outright, and every service independently refuses to
start on a known, blank or short key. One secret signs admin tokens and identity
assertions and encrypts the secret store, so a guessable value means no security at all —
we would rather fail your install than hand you a facade.
Running in namespace tsec, and the builder reachable on a port-forward. Migrations apply on startup; no manual database step.2 Run your first expedition ~20 min
Port-forward the builder and sign in with the bootstrap admin. Open the seeded expedition —
a START → SCREEN → SCREEN → COMPLETE login — and run it with the in-app
Try it harness.
Then change something: add a DECISION node that branches on a field, and
publish. Publishing creates an immutable, content-hashed version; the previous one stays
exactly where it was.
The thing to understand here is the division of labour. The runtime decides what happens
next and returns data; your application decides what it looks like. There are no TSEC
screens shipped into your UI. Expressions are scoped — session,
field, nodes.<id>.output, response,
device, risk, env — so what a node can read is
bounded and legible.
3 Put a real OIDC client in front of it ~30 min
Enable the authorization server and the login front-end, and the mock user store so you have somebody to sign in as:
helm upgrade tsec oci://ghcr.io/tricasollc/charts/tsec \
--version 26.10.0 --namespace tsec --reuse-values \
--set tsecAuth.enabled=true \
--set tsecIdp.enabled=true \
--set mockUsers.enabled=true
mockUsers is a test stand-in, not a product. In a real deployment your
directory stays where it is and the flow reaches it with an API-call module.
Check discovery, then register a client and drive a normal authorization-code login with PKCE:
curl -s https://<your-auth-host>/.well-known/openid-configuration | jq .
You will get the endpoints you expect — /oauth2/authorize,
/oauth2/token, /oauth2/jwks, /userinfo — because this
is Spring Authorization Server underneath, not a homegrown implementation. PKCE with
S256 is required, not optional. The id_token is signed RS256 and verifiable
against the published JWKS.
The point of this step: the login behind that standards-compliant flow is the expedition from step 2. Change the flow, and every downstream application's login changes, with no redeploy of anything.
4 Bind a device and read the decision ~30 min
This is the step that tells you whether the product is real. Add device intelligence to the
login flow: a device assessment node, a DECISION that routes on the result, a
TOTP step on the risky branch, and a bind node on success.
Then sign in twice from the same browser.
The first sign-in should challenge you for a second factor and, on success, bind the device to the account. The second should recognise the device and skip the challenge. That is adaptive step-up doing the only thing anyone actually wants from it: less friction for the people you already recognise, without lowering the bar for anyone else.
Now open the run log for both sessions. You should be able to see which signals matched, what each contributed, which rule fired and what the resulting decision was. Compare the two runs side by side. If you cannot reconstruct why the second login skipped the factor, the explainability claim on our homepage is not true and you should hold us to it.
5 Try to break it ~45 min
Most vendor evaluation guides stop before this part. Here is what we expect you to try and what should happen. If any of these behaves differently in your install, that is a finding and we want it.
Forge a weak master key
Install with --set secret.masterKey=CHANGE_ME_TO_A_32_BYTE_BASE64_KEY, or a
short string, or none at all. Expected: the chart refuses to render, and if
you bypass that, every service refuses to start with an explicit error. Overriding it
requires setting an opt-in flag by hand, which is deliberately an audit trail rather than a
default.
Tamper with a continuation token
Capture the continuation token mid-flow, flip a byte, and resubmit. Then try replaying a valid one after the expedition version has been republished. Expected: rejection in both cases — the token is HMAC-protected, and a revision guard stops a session continuing against a definition that has changed underneath it. Also check the idle and lifetime timeouts; they default to 15 minutes and 1 hour.
Point an outbound call at your metadata service
Author an API-call node targeting http://169.254.169.254/latest/meta-data/, then
try 127.0.0.1, then an internal RFC 1918 address.
Expected: blocked. Loopback, link-local, cloud-metadata and private ranges
are refused by default; reaching an internal host requires an explicit allowlist entry. A
Kubernetes NetworkPolicy is available as a second layer, and we would rather you ran it.
Replay a signed agent request
If you are assessing the automated-client detection, capture a validly signed Web Bot Auth request and replay it. Expected: rejected by nonce replay protection. Then try spoofing a known agent's user-agent string without a signature — expected: it classifies as a hint, not as proof, and the builder told you that when you wired the node.
Verify the audit chain, then break it on purpose
Publish an expedition and change a secret, then run the chain verifier against the
database. Now go into Postgres and edit one audit_event row — change an
actor, a timestamp, anything — and run it again.
Expected: exit 0 the first time, and the second time a non-zero exit
naming the first sequence number that no longer validates. Deleting a row should be
caught too. The verifier reads the chain directly and does not go through the
application, which is the entire point: it has to be trustworthy when the app, or
whoever operates it, is not.
Try to read a secret back out
Store an API credential, then attempt to retrieve it through the builder or its API. Expected: you cannot. The secret store is write-only to the console and AES-256-GCM encrypted at rest; flows reference secrets without ever returning them.
Brute force things
Hammer the admin login, then a TOTP verification. Expected: admin login
locks out with a Retry-After, and a locked account is detected before the
password is checked, so it is not a timing oracle for whether a username exists. TOTP has
its own configurable attempt and lockout policy with admin unlock.
The admin consoles have no second factor yet. Sign-in is password plus
lockout. The builder can change authentication logic, so treat it as a privileged
administrative surface: private ingress, VPN or service mesh, never public. The chart
defaults its service to ClusterIP for exactly this reason. Admin MFA is in
active development.
Request rate limiting at the edge is yours today. The runtime does not yet implement first-class per-identifier throttling on expedition execution, so put rate limiting on your ingress for the public endpoints. We would rather tell you that than let you find it in a load test.
What this does and doesn't prove
If the afternoon went well, you have established: that TSEC installs and runs in your environment with no dependency on us; that a visually authored flow can drive a standards-compliant OIDC login; that device binding measurably reduces step-up for recognised devices; that risk decisions are reconstructable after the fact; and that several specific attacks fail in the way the documentation claims.
You have not established: behaviour under production load, operational cost over a year, upgrade friction across several releases, or anything about our ability to support you. Those need a longer pilot and some conversations.
Before you write your recommendation, read what TSEC cannot do yet. It is a straight list, including the gaps most likely to block a regulated deployment. The one to check against your own control requirements first: the tamper-evident audit trail and its export cover administrative actions today, but not yet end-user authentication events from the runtime. If something there is a hard requirement, it is better in your report now than discovered in month three.