Capsule
Desktop companion for The Tempus Project. Point it at a TTP site, sign in with a username and password or paste an API token, and work against that install from the desktop.
This replaces the old TempusToolkit Electron stub. The keepers were the login ? stored-token ? home flow. Hardcoded LAN URLs, nodeIntegration, and the leftover WoW-folder picker did not come along.
Run it
From this folder (Windows source checkout is fine ? Capsule is Node, not PHP):
npm install
npm run dev
npm start previews a production build. There is no local TTP site on the Windows checkout. Login needs a reachable install (typically the Ubuntu host) with api/apiAccessPersonal on for user-token calls.
Package and update
Set CAPSULE_DEFAULT_SITE=https://ttp.joeykimsey.com in .env (copy .env.example) or in the shell before npm run dev or a build. This non-secret setting is embedded at build time and defaults to the demo URL above. It prefills both sign-in forms and supplies the logged-out logo; a saved or connected site takes precedence. It does not select the update feed or connect/sign in automatically. Rebuild installed packages after changing it.
For automatic-update testing without a signing certificate, use the separate dist:test-bootstrap and dist:test commands described in Free automatic-update testing. Original Local installations require one bootstrap installation; subsequent test updates use the in-app updater.
npm run dist:win builds a per-user Windows x64 installer at dist/local/Capsule-0.1.2-x64-Setup.exe (the filename follows the package version). This unsigned local build installs as Capsule. It retains the previous Capsule Local installation identity and session directory for upgrades; automatic updates remain disabled. Close the existing app and run the new installer under the same Windows account to apply the rename. npm run pack:win produces an unpacked app for inspection. npm test checks updater behavior and release validation.
Public builds use npm run release:win, require a permanent HTTPS update URL and Windows signing identity, and go to dist/release/. Update-enabled builds check automatically 15 seconds after launch and every four hours. An available update shows a blue Download update banner; downloading requires that click. After verification, the blue banner offers Restart to update, including before sign-in. Closing the app normally does not install an update. A closed app checks after its next launch.
Read Packaging and releases for signing variables, hosting requirements, the release automation entry point, and the installed-upgrade acceptance test. No public feed or signing credentials are configured in this checkout.
How auth works
All HTTP runs in the main process (net.fetch, so the PHP session cookie sticks). The renderer never sees the token and never talks to the site directly, so TTP's same-origin CORS policy does not apply. POSTs send X-CSRF-Token (and POST token) after a GET harvests csrf.
| Action | Endpoint | Notes |
|---|---|---|
| Password sign-in | POST /api/login |
username + password, application/x-www-form-urlencoded. Same limiter as browser login. CSRF from GET /api/login. No Turnstile. MFA accounts return { mfa } instead of a token. |
| MFA code / method | POST /api/login/mfa/{loginCode} |
auth_code or mfaMethodSelect. loginCode stays in the main process. |
| MFA reset | POST /api/login/mfa/{loginCode}/reset |
Clears the chosen method so the picker shows again. |
| Confirm identity | GET /api/profile |
Bearer user token. Also used to hydrate username after login. GET /api/users/find/{username} remains available. |
| Workspace | GET /api/notifications, GET /api/messages, GET /api/messages/recent |
First inbox page plus the header dropdown after connect. Plugin-off responses show as unavailable. |
| Search | GET /api/search |
Header search. q, resource, page. |
| Profile save | POST /api/profile/update |
Avatar and prefs. |
| Mail / notices | POST /api/messages/?, POST /api/notifications/? |
View, reply, create, read, unread, delete. |
| Contact / bugs | GET / POST /api/contact, GET / POST /api/bugreport |
Footer pages when those plugins are enabled, accepting, and allowed. Hashing in while they are off shows a not-accepting notice. |
| Existing token | Admin ? Tokens | Personal or app token. A user token hydrates the workspace; an app token can connect but cannot call the user API. |
The token is stored under Electron userData (session.json). safeStorage encrypts it when the OS keychain is available. MFA loginCode is not stored.
App-facing pairing notes live with the PHP app: repos/ttp/docs/capsule.md.
Layout
| Path | Job |
|---|---|
src/main/ |
Window, session file, TTP HTTP, IPC |
src/preload/ |
window.capsule bridge |
src/renderer/ |
Login, MFA, TTP-styled chrome, and live API views |
The logged-in header follows the public TTP shell (text-bg-dark, FA 6.7.1, Bootstrap 5.3). Search stays visible and centered. Account is a top-right dropdown like the site. Notifications and messages are the same bell / envelope menus. Profile edit covers User CP preferences except email, password, and phone ? those open {site}/usercp/?. Lists load from the site API after sign-in. The footer matches TTP copyright and social icons. Above that: Contact Us on the left (Contact and Report a Bug only when the site is accepting them), dark-mode in the middle, More Info (Privacy Policy, Terms of Service) on the right. No subscribe box. Privacy and terms open the connected site; contact and bug reports stay in-app.
Remote
This checkout starts with no git remote. When the repo exists on the project host:
ssh://git@git.thetempusproject.com:2222/the-tempus-project/capsule.git