Skip to Content
Product guidePortfolio

Portfolio

Where: Portfolio, at the very top of the sidebar (#/portfolio).

Portfolio is the view for whoever answers for the workspace. It asks three questions about the changes that reached your platform repos: how many there were, how many policy checked, and how many a named person approved. It names every change behind a gap, with a link to its PR, and then shows where each Application is exposed, which runtimes are past or near their end of life, and which standards are in force.

Who sees it: workspace owners. Other roles don’t see the sidebar item, and the screen says The portfolio is for workspace owners. Today every member of a workspace is an owner (see Team), so everyone in the workspace sees it.

What you see

  • Last 30 days (the default) or Last 90 days. These are the only two windows.
  • An Application picker, shown when the workspace has two or more Applications. All applications sums across every platform repo; picking one narrows the cards and lists to that Application’s platform repo.
  • Export PDF downloads the view you’re looking at, for the same window and the same Application filter. See The PDF.

The three cards

Under Changes to your platform repos, last N days:

CardWhat it counts
ChangesEvery pull request merged into the default branch of your platform repo (or repos) in the window, whoever opened it: TruStacks, a person on your team, or a bot.
Checked by policyChanges with a TruStacks policy verdict on record (allow or deny).
Approved by a named personChanges approved in your git host by a person who is not a bot, and not only the person who wrote or merged it.

Checked by policy is only knowable for changes TruStacks opened, because only those carry a verdict TruStacks recorded. A policy check that errored judged nothing, so it doesn’t count. When every change in the window came from TruStacks, the card reads N of M. When any change was opened outside TruStacks, the card reads Checked: N of the M TruStacks opened and says how many changes were opened outside TruStacks: whether policy checked those isn’t visible, because it needs your platform repo’s CI result. On GitHub, reading that result needs the checks: read permission on the TruStacks GitHub App, which it doesn’t have. The card never claims coverage across changes it can’t see.

Approved by a named person sorts each change into one of three groups:

  • Approved: at least one approver who is a person, and not the author or the person who merged it.
  • Self-approved: a person wrote the change, and the only approvals came from that person or from whoever merged it. Self-approval is counted on its own. It is never counted as approved, and never as unapproved.
  • No approval recorded: no approval in the git host, or approved only by a bot. An approval given somewhere else, in a meeting or a ticket, doesn’t show in the git host, so the screen says no approval recorded, not nobody approved.

A self-approved or unapproved change that a person on your team has since reviewed in TruStacks moves to its own line, reviewed after merge (see Record a review after merge). It is never counted as approved. The card then reads, for example, 0 of 2 approved by a named person, with 1 reviewed after merge and 1 with no approval recorded listed under it.

Two rules apply to every approval:

  • Bots never count as a person. Dependabot, Renovate, GitHub Apps (including TruStacks’ own), GitLab project and group token users and the Azure DevOps build service are all treated as bots.
  • A person approving a change TruStacks opened is a named approval. The agent wrote that change, so nobody is approving their own work. This holds even when the same person approved and merged it, and even on Azure DevOps and GitLab, where the git host lists the owner of the token TruStacks used as the change’s author. TruStacks uses its own record of who wrote the change, not the host’s author field. This is agents propose, policy decides, humans approve, counted.

With no platform repo connected, the cards are replaced by No platform repo is connected, so there are no changes to count, with a link to Applications. Zero changes there means nothing to count, not a clean record.

The gaps behind the numbers

Under the cards, each gap is a named list. A list appears only when it has something in it:

  • Self-approved
  • No approval recorded
  • Reviewed after merge
  • Opened by TruStacks, no policy verdict on record: the policy check errored or never ran for these.

Each entry shows the PR title, the repo and PR number, who merged it, when, the reason it is in the list, and Open the PR.

Record a review after merge

Every entry under Self-approved and No approval recorded has a Record a review after merge button. It is for a change that shipped without a named person’s approval, when someone on your team has since looked at it and wants that on the record under their own name. Like the rest of Portfolio, it is for workspace owners.

The form asks for:

  • What you reviewed, and why it’s acceptable (required): 10 to 1,000 characters, in your own words. It starts empty.
  • Outcome (optional): No concerns or Follow-up needed. It starts at Not stated.
  • Link (optional): an http(s) URL, for example a ticket or a follow-up PR.

TruStacks records you as the reviewer, from your sign-in, and the time; neither can be set in the form. The change then moves to Reviewed after merge, which lists each review: who, when, the outcome, the reason and the link, beside the git host’s own verdict on the change.

What a review after merge is not:

  • Not an approval. A reviewed change is never counted under Approved by a named person. The review came after the change shipped, and the screen says so.
  • Not a correction. The change’s own record, including the git host’s verdict, stays as it was. Each review is stored on its own.
  • Not editable. A review can’t be edited or deleted, and each person can record one review of a change. A change approved by a named person can’t be reviewed this way.

All N changes, with who approved them opens a table of every change in the window: the change (a TruStacks icon marks the ones TruStacks opened), when it merged and who merged it, the named approvers, the approval group, and the policy column (Checked, No verdict, or Not visible yet for a change opened outside TruStacks). For a change TruStacks opened, the policy column links to its proposal.

Exposure

One row per Application, read from its latest weekly snapshot:

ColumnWhat it shows
ApplicationLinks to the Application.
OwnerThe owner team, or the owner email, set on the Application’s Owner card. No owner when neither is set.
TierThe maturity tier and coverage percent, with the trend: flat since a date when coverage hasn’t moved for two weeks or more, or the change in points over the window (+N pts in 30 days). Not scored yet when the Application has no snapshot.
Image scanning, Secret scanning, SAST / SCAWhether each tooling category is covered.
Tests in CI, Pinned actionsWhether each practice is in place.
Prod gateWhether production promotion is manual.
RuntimeThe most urgent detected runtime and its support status: past end of life, security fixes end a date, supported or end of life unknown, plus how many other services there are. Not recorded or None detected when there is nothing to show. Every service is listed under Runtimes.

The scanning, practice and prod gate cells use one legend:

MarkMeaning
✓verified
~claimed, not verified
✗missing (also partial, and claimed, but not found)
—not applicable: the Application has no prod cluster
?not recorded

A missing value is shown as not recorded, never as fine. Verified, claimed and missing are never blended; see Maturity for how each is decided.

Draft the fix

Some scanning cells carry a Draft the fix button. It is the same gap remediation as Draft pipeline PR on the Maturity page.

  1. You choose the tool. The button opens Draft the fix: <category>, a list of the tools TruStacks can add for that category, with the recommended one pre-selected. It says: Merging this PR declares <tool> for <category> in your Stack file and adds its CI step. Cancel drafts nothing.
  2. The crew opens one pull request that adds the tool’s step to the workflow your service actually calls and declares the tool in environment-profile.yaml. The PR names who chose the tool, by display name, never by email.
  3. Policy checks it, and a person on your team reviews and merges it. Nothing merges on its own.

A fix is scoped: it changes nothing but that workflow, only by adding to it, plus the one entry in your Stack file. See What a fix changes. Once the request is sent, the cell reads Fix in progress → view.

The button appears on a cell only when all of these hold:

  • The cell is a tooling category (Image scanning, Secret scanning, SAST / SCA) that is missing, partial, or claimed but not found.
  • The Application’s latest snapshot comes from a finished gap analysis of its own platform repo, which lists that category as an open gap and recommends a tool for it.
  • Once your runners have reported which tools they can add, at least one tool for that category is on every active runner.
  • At least one of the Application’s services has a finished analysis.

If any of these is missing, the cell has no button. A fix that is offered can still stop once it runs, for example when the service has no CI workflow or calls several platform workflows; see when a fix stops.

A fix already on record

Once a fix has been drafted, the cell shows where the newest one stands. This comes from TruStacks’ record of the run, not from the page, so leaving Portfolio and coming back shows the same thing:

The cell readsWhat it meansDraft the fix offered again
Fix in progress → viewThe crew is working on it. The link opens the run.No
Fix PR open → review, and See the runThe pull request is open. The first link opens the PR in your git host, the second the run.No
Fix mergedSomeone on your team merged it. The cell adds that it reads verified once TruStacks sees the step and the tool is declared in environment-profile.yaml.No
Fix failed → viewThe run ended in an error.Yes
Fix stalled → viewThe run was still queued or running after 15 minutes, so it is treated as lost.Yes
Fix PR closed → viewThe PR was closed without merging.Yes
Last fix opened no PR → viewThe run finished without opening a PR, for example because there was nothing to change.Yes

Once the category is covered, a merged or closed fix is no longer shown.

One fix per gap at a time. While a fix for a category is in progress, TruStacks refuses a second one for the same gap, whether it is asked for from Portfolio, from Maturity or from a tab that was left open. The cell then shows the run already going. A run still in progress after 15 minutes no longer blocks a new one.

Merging the pull request is the claim: it declares the tool you chose. The category then reads claimed, not verified, until a gap analysis finds the tool’s pinned step in your platform repo’s workflow. When the PR couldn’t declare the tool, it says so and gives the lines to add yourself. See After you merge.

Some cells never get the button:

  • Practices (Tests in CI, Pinned actions, Prod gate). Declaring a practice is your attestation, not something the crew writes for you.
  • Runtimes. There is no governed fix flow for upgrading a runtime, and the DevOps Engineer doesn’t upgrade runtimes.
  • Claimed cells (~). A claim that isn’t verified yet doesn’t need a new pipeline step; what it lacks is verification.
  • A platform repo shared by two Applications. The fix is built from the platform repo, so it could land on the other Application. Neither gets the button.

Runtimes

One row per service, most urgent first: past end of life, then security fixes only (soonest end first), then detected with an unknown end of life, then not detected, then supported.

Each runtime is detected by the Code Reviewer from the service’s repo. It is read by the model, not verified. TruStacks checks it against the endoflife.date data bundled with the Control Plane.

A summary above the table leads with what needs action, for example 1 service runs a runtime past end of life (dotnet 6): no more security fixes, or 2 services are on a runtime that gets security fixes only (…); the first loses them in 12 days.

The End of life column reads:

StatusMeaning
past end of life (with the date)No more security fixes.
security fixes end a dateStill patched for security, nothing else.
supportedInside its supported window.
end of life unknownDetected, but not found in the end-of-life data.
not detected yetThe service has no finished analysis.
not recorded yetThe Application’s snapshot doesn’t record runtimes, or there is no snapshot.

A service TruStacks couldn’t detect is listed and counted, never dropped and never shown as supported.

Standards

Rules in force, as your runners last reported them:

  • TruStacks constitution: how many rules, and whether its signature was verified (signature verified, signature not verified, or signature status not reported).
  • Your own rules: none in force, the number in force from a signed bundle with its signature status, or the number read from your platform repo. Rules read from the platform repo are unsigned by design: your repo’s review is the trust anchor. See Add your own rule.
  • If no runner has reported yet, the panel says the rules in force aren’t known. It never says there are none.
  • If your runners report different rules, the panel says so and shows the newest report.

Per Application, every practice the latest gap analysis scored, with the same marks as Exposure. The headline reads N of M scored applications meet every practice, verified. Only verified counts as met: a claimed practice is counted on its own (N claimed, not verified), never as met. An Application with no snapshot reads Not scored yet.

The PDF

Export PDF renders the current view, for the same window and Application filter, as a printable PDF. Like the screen, it is for workspace owners only.

Page one is the change-control summary, headed Change control · changes to your platform repos: the three cards (including the reviewed after merge line) and every change behind a gap, with links to the PRs, a Reviewed after merge · N section with each review’s reviewer, date, outcome, reason and link beside the git host’s verdict, then the full change table. It is written to be usable as evidence of change control, for example for SOC2 CC8.1 (change management). It is evidence for your auditor to weigh, not a certification. Exposure, Runtimes and Standards follow.

The PDF uses the screen’s wording, including what it can’t see:

  • When any change was opened outside TruStacks, the policy card reads Checked: N of the M TruStacks opened, never N of all.
  • No approval recorded, never nobody approved.
  • Self-approved is its own line, never counted as approved.
  • Reviewed after merge is its own line too, never counted as approved.
  • The bot rule is stated on the page.
  • A runtime with no detection, or an unknown end of life, is printed as such, never as supported.

The response carries an X-TruStacks-Content-Sha256 header with the PDF’s SHA-256, as the audit report PDF does, so a forwarded copy can be checked against what the Control Plane produced.

What to do here

  • Open the Self-approved and No approval recorded lists first. Each entry links to the PR, so you can ask the person who merged it. Once someone has looked at it, Record a review after merge puts that on the record under their name, without counting it as approved.
  • If Checked by policy reads N of the M TruStacks opened, the rest of your changes reached the platform repo without going through TruStacks. Whether your CI checked them is a question for your CI, not this screen.
  • Use Last 90 days for a quarter’s view, and the Application picker to look at one platform repo at a time.
  • In Exposure, a ✗ or ~ points at a gap you can close; the Application’s gap analysis and Maturity say what closing it takes. A red runtime is past its end of life; see Runtimes for every service.
  • On a tooling gap with Draft the fix, click it, choose the tool, and the crew opens the pull request. When the cell reads Fix PR open → review, review and merge it; merging declares the tool. If it reads Fix failed → view, open the run to see why before drafting it again.
  • When an auditor asks for change-control evidence, pick the window and Application and click Export PDF.

How it connects

  • Changes TruStacks opened are proposals; their verdicts come from the rules in force.
  • The tier, coverage and cell statuses come from Maturity, snapshotted weekly.
  • The owner is set on each Application’s page in Applications.

Beta limits

  • Policy checks on changes opened outside TruStacks aren’t counted. On GitHub that needs the App’s checks: read permission. On Azure DevOps and GitLab, TruStacks doesn’t use pipeline status for this.
  • Approvals only come from the git host. An approval given anywhere else isn’t seen.
  • Exposure, Runtimes and per-Application practices are as fresh as the current week’s snapshot.
  • Runtimes are detected, not verified. The Code Reviewer reads them from the repo.
  • The change table lists at most 2,000 changes per window. When a window holds more, it shows the newest and says so.
Last updated on