System
· little-sister {{ version }}
{# Server-seeded, same contract as the dashboard's stamp (ADR-0005):
this page doesn't navigate on its own, so it always says from when
the information below actually is. Under the kiosk layout the slim
line already carries it — there must be exactly one #status-updated
on the page, because that is what the poller looks for. #}
{% if layout != 'kiosk' %}
updated {{ rendered_at }}
{% endif %}
{% include '_system_info.html' %}
{# The registered check types and who answers for each. A type may come from
a separately released package (ADR-0051), so this is the only place an
operator can read which code — and which version — is behind a `type:`
name in their YAML. Always shown: there are always the built-ins, and the
point is the comparison between them and everything else.
Split, though. The types this configuration runs come first; the rest
fold into a disclosure, because on a small deployment they are most of
the card and none of the question being asked. They stay reachable
because a registered-but-unused type is the proof a freshly installed
plugin took — see `_type_roster`, which owns the reasoning. #}
{%- macro type_table(rows) %}
| Type | Module | Version | From |
{% for origin, count in rows %}
{#- "used by", because a bare count under a type name
reads as something the *package* brought — two
checks shipped — when it is the opposite: how many
checks in this deployment's configuration name this
type. A package contributing one type to two checks
is the ordinary case, so the ambiguous phrasing was
wrong most of the time. -#}
{{ origin.type_name }}
{%- if count %} used by {{ count }} check{{ 's' if count != 1 else '' }}{% endif %} |
{#- The loaded path under the module name, because the
version beside it is the installed metadata's claim:
a source copy earlier on the path shadows an
installed distribution of the same name, and then
the version is answering for code that is not
running. Exactly the case somebody reads this table
to diagnose, so the table shows both. -#}
{{ origin.module }}
{% if origin.path %} {{ origin.path }}{% endif %} |
{% if origin.version %}{{ origin.version }}{% else %}—{% endif %} |
{% if origin.builtin %}built-in{% elif origin.distribution %}{{ origin.distribution }}{% else %}source{% endif %} |
{% endfor %}
{%- endmacro %}
Check types
{% if types_in_use %}
{{ type_table(types_in_use) }}
{% if types_folded %}
{#- The count belongs in the summary: a closed disclosure has to say
what it is hiding, or an operator looking for a type they cannot
find has no reason to open it. #}
{{ types_folded | length }} more registered type{{ 's' if types_folded | length != 1 else '' }}, unused by this configuration
{{ type_table(types_folded) }}
{% endif %}
{% else %}
{#- Nothing to split against (no engine, or no checks) — and that is
the moment the roster matters most, so it is shown whole. #}
{{ type_table(types_folded) }}
{% endif %}
{# What is installed beside the library. A package reaches this instance
through four seams and the tables below are each about one of them, so
until this card the *version* of a package that registers no check type
was unreadable from the running instance — see `_registering_packages`.
One row per installation, not per contribution: the loaded path and the
release belong to the package, and printing them on every slot row would
say the same thing twice for a package that fills two. Absent when
nothing but the library registered anything. #}
{% if packages %}
Packages
{#- Two columns, not three. The loaded path is the longest thing
on this page — an absolute site-packages path, most of it
the same prefix on every row — and a column of its own left
it a narrow ribbon breaking at the hyphen in "site-packages"
while squeezing everything either side of it. Under the name
it gets the table's whole width, which is what a path that
long needs to stay readable. -#}
| Package | Registers |
{% for row in packages %}
{#- The import name is what every other table on this
page prints, so it leads; the distribution and
version sit beside it because that pair is what an
operator compares against what they installed. A
package with no installed metadata is a copy on the
path — the shadowing case, worth saying out loud. -#}
{{ row.origin.package }}
{% if row.origin.distribution %}· {{ row.origin.distribution }} {{ row.origin.version }}{% else %}· source{% endif %}
{%- if row.origin.path %} {{ row.origin.path }}{% endif %} |
{#- Each registration is one fact and must not break
across lines: "slot reason.actions" split after
"slot" reads as two entries, and the column is
narrow enough for that to happen. The list still
wraps *between* items — that is what the breaks
are for. -#}
{%- for item in row.registers %}
{{ item }}{% if not loop.last %} {% endif %}
{%- endfor %} |
{% endfor %}
{% endif %}
{# The extension seams (ADR-0034 / ADR-0035), outside #system-info because
they are decided at import time and never move while the process runs —
re-fetching them on the ~10s poll would say nothing new. Shown only when
something registered, so a deployment with no extensions has no section
rather than an empty one. Registration is import-order sensitive and each
of its failures is a log warning, so the running instance has to be able
to answer "did my extension take?" without anyone opening a log file. #}
{% if slot_fillers or extra_aspects %}
Extensions
{% if slot_fillers %}
| Slot | Package | Template | Context | From |
{% for filler in slot_fillers %}
{{ filler.slot }} |
{{ filler.package }} |
{{ filler.template }} |
{% if filler.context %}provider{% else %}—{% endif %} |
{#- Which kind: a dependent package's registration, or
the library's own declarative action list, which
fills the same slots through the same seam
(ADR-0038). Worth naming, because an operator
looking here after adding a config action needs to
see the difference between "mine" and "theirs". -#}
{% if filler.builtin %}built-in{% else %}extension{% endif %} |
{% endfor %}
{% endif %}
{% if extra_aspects %}
{#- Each name with the package that registered it: the name alone
says the file is *declared*, which is not the question when the
file is misbehaving. An owner is absent only where the caller
could not be inferred, and then nothing is claimed. #}
Registered configuration aspects:
{% for name, owner in extra_aspects %}config/{{ name }}{% if owner %} ({{ owner }}){% endif %}{% if not loop.last %}, {% endif %}{% endfor %}
{% endif %}
{% endif %}
{# The effective Content-Security-Policy (ADR-0048 §7). Always shown, unlike
the extensions card above: there is always a policy, and the reason to
print it is that a source may come from a *package* — a request blocked
inside somebody else's code is undebuggable from here unless the page says
who asked for each origin. The header name is part of the answer: a
Report-Only policy reports and blocks nothing. #}
Content-Security-Policy
{{ csp_header }}
| Directive | Sources |
{% for directive, sources in csp_directives %}
{{ directive }} |
{%- for source in sources %}
{{ source.value }}
({{ source.by }})
{%- if not loop.last %} {% endif %}
{%- endfor %}
|
{% endfor %}
{% include '_page_end.html' %}