Introduction
natPortal, as a client portal and hub to all NAT services, makes NAT’s services available through a web client. Originally an events and hackathon registration platform, natPortal’s scope has expanded to become a website for the majority of NAT’s business and communications.
As a client portal, the natPortal frontend interacts with loosely coupled services and infrastructure maintained and served by NAT’s technical staff.
The purpose of this document is to describe the underlying and design philosophy of natPortal, and serve as a reference for its development and direction.
Design and Architecture
natPortal is a platform serving all of NAT’s backends. These include backends for Snipe-IT (inventory management), Moodle (education platform), and natPass (event participant management and tracking system) and may expand to include more services.
As such, natPortal is closely related to a microservices architecture, in which the natPortal application interacts with multiple decoupled systems to fulfill its own requirements.
Requests and permissions are handled by ZITADEL, a self-hosted authentication platform managed by NAT. Users with more advanced roles will have further capabilities than those with basic roles. These roles include administrators, staff, and volunteers.
Requests to natPortal’s APIs are checked against their user’s respective role in ZITADEL.
natPortal Stack
This section will only describe and justify the major technologies within natPortal excluding the technologies for systems external to, but critical to, natPortal.
Bun
Bun is a JavaScript runtime with a TypeScript adapter. Bun is also a package manager. Bun is chosen for its speed and efficiency in both deployment and development.
Vite
Vite is a frontend build tool known for its speed and extensibility. Vite performs Hot Module Replacement (HMR) in development and building for deployment.
SvelteKit
SvelteKit is a full-stack web framework known for being highly performant and configurable. As a full-stack framework, we use SvelteKit as a server-side renderer and routing solution for the frontend of natPortal.
FastAPI
FastAPI is a Python backend framework known for simplicity. As a Python framework, we expect student volunteers, which will make up the majority of the natPortal development team, to be capable of developing efficiently under this framework. FastAPI handles asyncronicity similarly to JS frameworks, as an ASGI-compliant framework. Despite being a Python framework, we expect its performance to be highly sufficient for traffic in the thousands, due to its thin abstraction over uvicorn, a low-level Python framework.
PostgreSQL
PostgreSQL was the same DBMS chosen for the previous natPortal. We choose PostgreSQL for its simplicity, reliability, extensibility, and maturity.
Logging and Error Handling
All of natPortal’s API requests are logged with a shared schema containing the ID attached to the request, the time, the API route, and method. For simplicity and ease of analysis, logs are stored in a JSON format. natPortal uses the Pino library to return and store highly configurable logs.
Logs will be stored only on the backend, for a maximum of 2 weeks. Logs of events requiring administrator privileges may be stored indefinitely, due to their relatively lesser volume.
In an effort to protect the security of natPortal, detailed logs will not be provided to the user in production. A generic message including a status code may be returned.
Errors such as navigating to or accessing unauthorized routes (administrator dashboard, APIs) will return a 404 error. Navigations will send the user to a 404 page.
Errors such as failing to perform an action in the UI (button presses, inputs, form submissions) will display a small failure message with error code 500, allowing the user to try again.
If the backend is incapacitated, the user should be navigated to a 500 page. In no other circumstance should the user be navigated to a 500 page.
Security
We use the Code PKCE Flow to authenticate the user. natPortal plans to later refactor the app into a progressive web app.
Look at this please. https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps-09#name-attacks-on-the-implicit-flo
We use this library https://authjs.dev/concepts/oauth#further-reading
sequenceDiagram participant U as User Browser participant S as SvelteKit<br>(Public Client) participant Z as ZITADEL participant F as FastAPI<br>(Confidential Client) Note over S: 1. Initiate Login U->>S: Clicks "Login" S->>S: Generates code_verifier<br>and code_challenge S->>U: Store verifier (httpOnly cookie)<br>Redirect to ZITADEL with challenge Note over Z: 2. User Authentication U->>Z: Authenticates (User sees ZITADEL UI) Z->>U: Redirect to SvelteKit with auth code Note over S, F: 3. Code Exchange U->>S: Arrives at callback route with code S->>F: POST /api/token<br>(Code + code_verifier + redirect_uri) Note over F: 4. Secure Token Handling F->>F: Validates consistency<br>(redirect_uri, verifier) F->>Z: Request tokens (code + verifier<br>+ client_id + client_secret) Z->>F: Returns access_token,<br>refresh_token, id_token F->>F: Validates tokens,<br>Creates/Updates User F->>S: Response with Set-Cookie headers<br>(HttpOnly, Secure) Note over U: 5. Session Established S->>U: Cookies stored by browser<br>User redirected to app U->>F: Subsequent API requests<br>include cookies automatically
Testing Plan
Tests will be run against natPortal’s backend using the pytest framework.
Tests run against the backend include unit tests, regression tests, and functional tests.
Tests run against the frontend include visual regression and end-to-end tests.
Frontend testing requires Playwright, completely simulating the real-world use cases and appearance of natPortal.
Deployment
For the timeline of natPortal’s features, see Timeline.
In its early stages, where low traffic can be expected, natPortal can be deployed with a docker compose file, building and deploying multiple containers on a single virtual network.
However, with a separate and in-house backend, it is possible to scale either based on their respective bottlenecking.