import type { Metadata } from "next";

export const metadata: Metadata = {
    title: "Platform",
    description: "How Vantage fits together: a control plane you run, one agent per server, and a single outbound connection between them.",
};

export default function PlatformPage() {
    return (
        <>
            <section className="rail band band--open">
                <span className="tag">Platform</span>
                <h1 style={{ fontSize: "var(--s-3)", margin: "0.8rem 0 1rem", maxWidth: "19ch" }}>How the pieces fit together.</h1>
                <p className="lede">Three moving parts: a control plane you run, an agent on each server, and one outbound connection between them.</p>

                <div className="split" style={{ marginTop: "3rem" }}>
                    <div>
                        <h2 style={{ fontSize: "var(--s-2)", maxWidth: "18ch" }}>The agent never listens.</h2>
                        <div className="prose" style={{ marginTop: "1rem" }}>
                            <p>
                                Every agent dials out to the control plane over gRPC with TLS. Nothing needs an inbound port, nothing needs a static address, and a machine behind NAT is no different
                                from one with a public IP.
                            </p>
                            <p>
                                Key state is polled on a 30-second interval, because 30 seconds is fine for access control and polling is simple to reason about. Everything that should not wait
                                running a step, opening a console, applying updates is pushed down a bidirectional command stream the agent holds open.
                            </p>
                        </div>
                    </div>

                    <div className="specs specs--flush">
                        <div className="spec">
                            <span className="spec__k">POLL</span>
                            <div>
                                <h3>SyncKeys, every 30s</h3>
                                <p>The desired key set for this server. Unchanged state means no disk write at all.</p>
                            </div>
                        </div>
                        <div className="spec">
                            <span className="spec__k">PUSH</span>
                            <div>
                                <h3>Command stream</h3>
                                <p>Generate a key, run a step, apply updates, update the agent, clean up a workspace.</p>
                            </div>
                        </div>
                        <div className="spec">
                            <span className="spec__k">REPORT</span>
                            <div>
                                <h3>Inventory and checks</h3>
                                <p>Metrics every 30 seconds, a full hardware snapshot every 15 minutes, and monitor results as they complete.</p>
                            </div>
                        </div>
                    </div>
                </div>
            </section>

            <section className="rail band">
                <span className="tag">Write path</span>
                <h2 style={{ fontSize: "var(--s-2)", marginTop: "0.7rem", maxWidth: "24ch" }}>The file is never half-written.</h2>
                <div className="split split--even" style={{ marginTop: "2rem" }}>
                    <p className="prose">
                        The agent computes the desired <code>authorized_keys</code> content, compares it to what is on disk, and stops there if nothing changed. When it does need to write, it writes a
                        temporary file in the same directory and renames it over the real one. A machine that loses power mid-write keeps the file it had.
                    </p>
                    <pre className="code">
                        <i>// agent poll, simplified</i>
                        {"\n"}
                        desired := client.SyncKeys(serverID, token){"\n"}
                        current := keys.ReadAuthorizedKeys(){"\n\n"}
                        <b>if</b> !keys.StateChanged(current, desired) {"{"}
                        {"\n    "}
                        <i>// nothing to do</i>
                        {"\n    "}
                        <b>return</b> nil{"\n"}
                        {"}"}
                        {"\n\n"}
                        keys.WriteAuthorizedKeys(desired){"\n"}
                        <i>// write .tmp, os.Rename(), chmod 0600</i>
                    </pre>
                </div>
            </section>

            <section className="rail band">
                <span className="tag">Tenancy and identity</span>
                <h2 style={{ fontSize: "var(--s-2)", marginTop: "0.7rem", maxWidth: "22ch" }}>Instances are the boundary.</h2>
                <div className="caps">
                    <article className="cap">
                        <span className="cap__k">Isolation</span>
                        <h3>Scoped at the query</h3>
                        <p>
                            Every server, key, workflow, monitor and secret belongs to an instance, and every lookup is filtered by it. Uniqueness constraints are enforced by the database, not by
                            application logic.
                        </p>
                    </article>
                    <article className="cap">
                        <span className="cap__k">Roles</span>
                        <h3>Owner, admin, member</h3>
                        <p>Members operate the fleet. Admins and owners manage people, identity settings and the secrets read token.</p>
                    </article>
                    <article className="cap">
                        <span className="cap__k">Identity</span>
                        <h3>Local or OIDC, per instance</h3>
                        <p>Sign in with email and password, or connect your own provider. Each instance configures its own issuer and client.</p>
                    </article>
                    <article className="cap">
                        <span className="cap__k">Sessions</span>
                        <h3>Server-side, 24 hours</h3>
                        <p>Cookies carry an opaque identifier and nothing else. Session bodies live in Redis, so losing it signs everyone out and costs no durable data.</p>
                    </article>
                </div>
            </section>

            <section className="rail band">
                <span className="tag">What we do not build</span>
                <h2 style={{ fontSize: "var(--s-2)", marginTop: "0.7rem", maxWidth: "22ch" }}>The scope is the feature.</h2>
                <div className="specs" style={{ maxWidth: "70ch" }}>
                    <div className="spec">
                        <span className="spec__k">NOT A PROXY</span>
                        <div>
                            <h3>We are never in the SSH path</h3>
                            <p>Vantage assigns keys; your client connects straight to the box. If our control plane is down, your SSH still works.</p>
                        </div>
                    </div>
                    <div className="spec">
                        <span className="spec__k">NO CUSTODY</span>
                        <div>
                            <h3>Private keys stay put by default</h3>
                            <p>Keys generated on a server stay on it unless you explicitly upload the private half, and anything stored is encrypted with a key only your deployment holds.</p>
                        </div>
                    </div>
                    <div className="spec">
                        <span className="spec__k">NO PER-USER</span>
                        <div>
                            <h3>Root, not every account</h3>
                            <p>Vantage manages one file per server. Per-user key management is a different product with a different failure mode.</p>
                        </div>
                    </div>
                    <div className="spec">
                        <span className="spec__k">NO PLUGINS</span>
                        <div>
                            <h3>An agent you can read in an evening</h3>
                            <p>A few thousand lines of Go with no extension system. Auditability beats extensibility on a binary that runs as root.</p>
                        </div>
                    </div>
                </div>
            </section>
        </>
    );
}
