Skip to content
kc@kumarChandrachooda.com:~$ cd /design-system/account && read --section="01 account-page" 0%
KC Design System — Transit / Flow

Change here for everything.
Account.

The transit style sets the system as a timetable in design-system-transit.css: Schibsted Grotesk, extra-bold and tight, a route line under the chrome, chips with line roundels and cards hung from a coloured rule. Same components, same markup — read off the platform board.

Reading in an unnamed pair — transit / flow Browse all 8 →

01

Account page & identity card

The page behind /account (_AccountChassis, _SectionIdentity): a sticky rail and one card per section, both generated from one list read three times — for the rail, for the cards, and for the tally at the foot that says how many sections have content and how many are absent. The identity card leads: the monogram in the badge's tone, the name, the mono line, the byline when a profile exists, the role pill on the trailing edge. And the outcome line, done or refused and a sentence, which falls under the cards when its own section has gone.
One list, three renderings. The page's sections are one list, read once for the rail, once for the cards and once for the tally at the foot, so the smallest page on the site cannot ship a link to a heading that is not in the document. A section whose predicate is false is absent, not empty, and the tally is where the absence is legible.
The identity card: the monogram, the name, the mono line, the byline when a profile exists, and the role badge on the trailing edge. The avatar takes the badge's tone, so the square at the top of the page and the pill in the role panel four sections down cannot disagree about what somebody is.
02

Credentials & sessions

Every way to be you and every place you are (_SectionCredentials, _CredRow, _SectionSessions): a credential row is a glyph square, the provider and one mono line, with a .kc-mini that is never disabled to stand in for the server's check; a session row is a dot, the device and place, and either current or a revoke, with one control to revoke every other device.
Every way to be you, and every place you are. A credential is a two-letter glyph, the provider and one mono line; its Remove is never disabled when the server would refuse, because the count happens where the write happens and the refusal comes back as a sentence. A session row is a dot, the device and place, and either current or a Revoke.
03

Role & the grant disagreement

The role section places the role panel and draws nothing of its own but one paragraph (_SectionRole, .kc-account__disagree): for the person whose grant says one thing and whose site says another, both answers, and the clock named as the thing between them.
The section places the component; it does not draw a second one. The panel is Chrome › Roles & grants. What is the host's own is the paragraph under it, for the one person whose two questions have two answers: what was granted, and what the site acts on.
04

Danger zone, export & delete

Leaving, in the order the docket insists on (_SectionDanger, _SectionExport, _SectionDelete): the frame that says what goes, the export with what it does not hold struck through, then the deletion card — a ledger of what is deleted now beside what stays on the site, a typed phrase matched on the server, and the action buttons .kc-abtn--danger and --ghost --sm. Export first, then delete.
Export first, then delete, in that order. The frame says what leaving takes with it, holds the export, and the deletion card comes after it: a ledger of what is deleted now beside what stays on the site, a typed phrase checked on the server, and the action buttons — .kc-abtn--danger and a small ghost Cancel.
05

Settings & preferences

/settings, the one Account page built for somebody signed out (_SettingsHead, _SettingsGroup, _PrefRow, _SettingsPreview): six preferences in three groups, one row each — label and reason left, control right — and the control is segmented, not a chip row: one box, hairline dividers, the current value filled solid ink, every option a submit button carrying its own value.
Six preferences, three groups, no JavaScript. One preference is one row — label and reason on the left, the control on the right, a hairline under each — and the control is segmented: one box, the options divided by hairlines, the current one filled solid ink. Every option is a submit button carrying its own value, so pressing one is the whole interaction.

Settings

How this site behaves for you.

Six choices about reading, and nothing about who you are. Nothing on this page can change what you are permitted to do — that is the rule that decides what is allowed to appear here, and it is why this page works signed out.

These six live in this browser. When this site gains a sign-in, the same six follow the account instead — so a choice made on a laptop is already made on a phone.

Appearance

Theme

The design system already carries a dark surface at #202020. This says which one you want, rather than leaving it to whatever the operating system was set to.

Code blocks

Dark blocks in a light page are a legitimate and common preference, and the reverse is equally so. Match follows whatever the theme above resolves to.

Reading

Motion

The resume is a slideshow, and for a vestibular-sensitive visitor that deck is the CV. This is the one preference on this page that somebody can need before they have any reason to have an account, which is why the page answers signed out.

Type size

The article column is one measure, and 125% is the difference between reading it and not. Three sizes rather than a slider, because a measure that can be set to anything can be set to something the column cannot hold.

Density

The same column at 112% wants tighter leading. Density is the second half of type size rather than an independent taste, which is why it sits beside it.

Mail

Series email

There is exactly one message this site sends: a note when a series a reader is part-way through gains a part. Opt-in, off by default, and it is the only preference here that will ever need an address to act on.

What the choices do

The article column is one measure. Type size decides whether it is a comfortable one; density decides how tightly the lines sit inside it. Both take effect on this paragraph as soon as they are pressed.

PreferenceCatalog.TryFind(key, out var pref)
    && pref.Permits(value)

Theme and the series email have no effect to show here: one is the site-wide surface, which this wave does not restyle, and the other is a message that has nothing to send yet. Both are stored, and both are in the cookie above.

06

Sign-in card

One screen for both doors and no separate registration (_SignInCard): kicker, title, the provider doors, the rule, the email field and its ghost link button, the aside; then what the server did, in the gate under the card, in a tone that is not an error unless something failed.
One screen, every door, and no separate registration. A first sign-in and a thousandth are the same request. Each provider is a form rather than a link — a GET challenge is a URL an image tag can fire — and a door this deployment has no registration with is drawn, disabled, because it is part of the screen. What the server did lands in the gate under the card.
07

Invitation card

The invited person's half of an invitation (_InviteCard): a centred card naming who invited whom, the role in the role panel's own pill, one button, and the note that the grant arrives with the account. A refusal is a sentence, because the link was good enough to reach the card.
The invited person's half. A centred card on a public page: the inviter named, the role in the role panel's own pill, one button, and the note that accepting creates the account with the grant already attached. A link that reached the card but cannot be accepted gets a sentence, never a status code.
You have been invited

Write the guest series on queues

Kumar invited lee@example.com to join as Author

Accepting creates the account with the grant already attached. Nothing to approve afterwards, and nothing to wait for.

invite · single use · expires in 6 days

You have been invited

Write the guest series on queues

Kumar invited lee@example.com to join as Author

invite · single use · expires in 6 days

08

Account switcher

The development door, a permanent feature of this app on one laptop (_SwitcherCard, _SwitcherRow, _SwitcherPanes): a card of seeded people, each row the monogram, the name and why they exist, the grant pill on the right; the owner armed by one press and taken by a second; and the evidence panes that show what the principal answers. The specimen emits no form: on the real screen every row is a sign-in.
A card of people you can be, on one laptop. Each row is the person's monogram, their name and why they are seeded, with the grant pill on the right edge — the grant, not the resolved role, and the disagreement said under the row when the two differ. The owner's row is armed by a first press and taken by a second. On the real screen every row is a form; here none is.

Development bypass

Who would you like to be?

Six viewers. Pick one and this browser is signed in as them, with a real session, until you sign out or it expires. There is no password because nobody is authenticating you — the account id is the whole assertion, and the only thing keeping that acceptable is that this door exists on one laptop and in no deployment.

  • The grant says Pass; the principal answers Reader. They disagree because the expiry is checked at the point the capability is spent, not written into a column by a job that has not run. Selecting this row gives you Reader — which is the whole reason this person is in the seed.

POST /account/switch/leave · the real sign-out, all four steps

The four downstream reads

Everything downstream is supposed to read ICurrentPrincipal and be unable to tell which source filled it. Here are the four, with what each computes for you right now. Change viewer above and read them again.

  1. SiteNavigation.Build(IUrlHelper, app, section) does not read the principal yet

    Web/Services/SiteNavigation.cs:70 — appends a RailApp row per app this deployment has.

    6 rows, 3 of them mounts - the same answer for every viewer

    It takes an app name and no viewer, deliberately: it runs on a page the edge caches.

  2. AccessPolicies.Owner -> OwnerRequirementHandler reads ICurrentPrincipal

    Web/Filters/AccessPolicies.cs:126 — decides whether this request may enter the Control Room.

    the requirement fails - every route under /control answers 404

    It reads the seam, so it cannot tell which source filled it.

  3. WorkshopController.Move -> DraftStateMachine.Evaluate does not read the principal yet

    Web/Areas/Workshop/Controllers/WorkshopController.cs:497 — the actor a draft transition is judged as.

    TransitionActor.Author - hard-coded, for every caller

    The defect SPEC 06 names rather than a principle it illustrates.

  4. GET /api/session -> SessionCapabilities reads ICurrentPrincipal

    Web/Areas/Workshop/Controllers/SessionController.cs:105 — the three booleans the rail reveals its mounted rows from.

    workshop=false, control=false, identity=true

    Null AccountId is the only null on a SiteViewer that means something: the Guest.

consumers shown
4
reading ICurrentPrincipal
2
naming __Host-kc.session
0

Zero is the number that made the deletion cheap, and it was collected on. Every consumer here reaches the viewer through ICurrentPrincipal or SiteViewer, or does not reach it at all — and both of those survived the bypass being deleted untouched, which is exactly what BY4 measured. Two of the four do not read the principal yet and each row says why; that is the honest state of this estate rather than the docket's fixture, and it does not weaken the zero. They cannot name a cookie whose name is a file-scoped constant they are not permitted to see.

This counter is a summary and the COMPILER is the authority now. It counts declarations on four rows. The real check used to be a solution-wide search for the cookie name, run by somebody who remembered to; SessionCookie.cs put the literal on a file-scoped type instead, which turns the convention into a build error. That is the one place this wave's arrangement is strictly better than the one it restored.

What /api/session answers for you

Three booleans from three separate predicates — a stored grant that can lapse, a computation over configuration, and whether there is a session at all. They are what the spine rail reveals its rows from, and they are safe on a page a cache may hand to somebody else because they say what you may do rather than who you are.

workshop
false
control
false
identity
true

What it deliberately does not carry

The viewer record the server resolved for this request. It is on this page because this page is private, behind a gate that 404s, in a process the public cannot reach, on a response marked no-store. It is not on that endpoint for the same reasons in reverse.

accountId
acct_01SPECDAN0
display
Dan Kovac
role
Reader
expires
null
isBypass
false

isBypass is false here, and it is false on purpose. This pane used to say the opposite: the bypass source answered true even when it established nobody, and the banner was driven by that flag. There is no bypass source now — SessionPrincipalSource passes IsBypass: false as a literal, with the comment “its one legitimate reader is the banner that says a bypass answered, and a bypass did not”. The session you are holding is a real one. The banner above is driven by ISwitcherDoor instead, so it is on whenever the door EXISTS rather than whenever somebody has chosen — which is the property the old sentence was protecting, held by a stronger mechanism.

Markup

As rendered on the page behind this — captured, not transcribed.