summaryrefslogtreecommitdiff
Commit message (Collapse)AuthorAge
* Handle basics of interface scrollingKit La Touche2024-10-03
|
* Absorb and display eventsKit La Touche2024-09-30
| | | | | At least message-type ones, and at least without styling or memory-limit concerns.
* Merge branch 'main' into feature-frontendKit La Touche2024-09-30
|\
| * Reimplement the logout machinery in terms of token IDs, not token secrets.Owen Jacobson2024-09-29
| | | | | | | | | | | | This (a) reduces the amount of passing secrets around that's needed, and (b) allows tests to log out in a more straightforwards manner. Ish. The fixtures are a mess, but so is the nomenclature. Fix the latter and the former will probably follow.
| * Shut down the `/api/events` stream when the user logs out or their token ↵Owen Jacobson2024-09-29
| | | | | | | | | | | | | | | | expires. When tokens are revoked (logout or expiry), the server now publishes an internal event via the new `logins` event broadcaster. These events are used to guard the `/api/events` stream. When a token revocation event arrives for the token used to subscribe to the stream, the stream is cut short, disconnecting the client. In service of this, tokens now have IDs, which are non-confidential values that can be used to discuss tokens without their secrets being passed around unnecessarily. These IDs are not (at this time) exposed to clients, but they could be.
* | Move layout concerns into layoutKit La Touche2024-09-30
| |
* | Merge branch 'main' into feature-frontendKit La Touche2024-09-28
|\|
| * Wrap credential and credential-holding types to prevent `Debug` leaks.Owen Jacobson2024-09-28
| | | | | | | | | | | | | | | | | | | | | | | | The following values are considered confidential, and should never be logged, even by accident: * `Password`, which is a durable bearer token for a specific Login; * `IdentitySecret`, which is an ephemeral but potentially long-lived bearer token for a specific Login; or * `IdentityToken`, which may hold cookies containing an `IdentitySecret`. These values are now wrapped in types whose `Debug` impls output opaque values, so that they can be included in structs that `#[derive(Debug)]` without requiring any additional care. The wrappers also avoid implementing `Display`, to prevent inadvertent `to_string()`s. We don't bother obfuscating `IdentitySecret`s in memory or in the `.hi` database. There's no point: we'd also need to store the information needed to de-obfuscate them, and they can be freely invalidated and replaced by blanking that table and asking everyone to log in again. Passwords _are_ obfuscated for storage, as they're intended to be durable.
| * Clean up use of bare tuple as a vector element for ResumePoint.Owen Jacobson2024-09-28
| |
| * Expire channels, too.Owen Jacobson2024-09-28
| |
| * Delete expired messages out of band.Owen Jacobson2024-09-28
| | | | | | | | | | | | | | | | Trying to reliably do expiry mid-request was causing some anomalies: * Creating a channel with a dup name would fail, then succeed after listing channels. It was very hard to reason about which operations needed to trigger expiry, to fix this "correctly," so now expiry runs on every request.
| * Assign sequence numbers from a counter, not by scanning messagesOwen Jacobson2024-09-28
| |
| * Push message body into its own object in eventsOwen Jacobson2024-09-28
| |
| * Send created events when channels are added.Owen Jacobson2024-09-28
| |
| * Make `/api/events` a firehose endpoint.Owen Jacobson2024-09-27
| | | | | | | | | | | | | | | | It now includes events for all channels. Clients are responsible for filtering. The schema for channel events has changed; it now includes a channel name and ID, in the same format as the sender's name and ID. They also now include a `"type"` field, whose only valid value (as of this writing) is `"message"`. This is groundwork for delivering message deletion (expiry) events to clients, and notifying clients of channel lifecycle events.
| * Fix test missed in cce1ab45db0de5e912fa7eec8d8a2cfe9a314078Owen Jacobson2024-09-27
| |
* | Make message input tolerable as mock-upKit La Touche2024-09-27
| | | | | | | | | | It's not robust, and it's not yet able to handle multiline or rich input. We'll get there.
* | Add lots of style and layoutKit La Touche2024-09-27
| |
* | Add basic browser clientKit La Touche2024-09-27
|/ | | | | | | | | | | | | Using Svelte. No tests, no linting, yet. This is just starting to get familiar with things. You'll still have to run the dev server and the dev client builder each in their own terminals. Enjoy!
* Browsers default Path= to the directory part of the request URI.Owen Jacobson2024-09-27
| | | | This change makes the identity cookie available throughout `/api`.
* Stream over results while OK, using less code.Owen Jacobson2024-09-25
| | | | This also has the happy effect of removing an unwrap. This feels like a more coherent way of achieving the same result.
* Retire `fixtures::error::expected!`.Owen Jacobson2024-09-25
| | | | I had no idea `std` included a `matches!` macro, and I feel we're better off using it.
* Missed one when drafting the tests.Owen Jacobson2024-09-25
|
* Remove some extraneous turbofish operators.Owen Jacobson2024-09-25
|
* Re-wrap comments.Owen Jacobson2024-09-25
|
* `sequence` was not intended to appear in messages.Owen Jacobson2024-09-25
|
* Package upgradesOwen Jacobson2024-09-25
|
* More reorganizing.Owen Jacobson2024-09-25
|
* Typo in test nameOwen Jacobson2024-09-25
|
* ID alphabet and generation length were never meant to be sharedOwen Jacobson2024-09-25
|
* Crank up the Clippy warnings.Owen Jacobson2024-09-25
| | | | This'll catch style issues, mostly.
* rustdoc comment for the (very limited) public API of the crate.Owen Jacobson2024-09-25
| | | | | | | | This silences some `-Wclippy::pedantic` warning, and it's just a good thing to do. I've made the choice to have the docs comment face programmers, and to provide `hi --help` and `hi -h` content via Clap attributes instead of inferring it from the docs comment. Internal (private) "rustdoc" comments have been converted to regular comments until I learn how to write better rustdoc.
* Code organization changes considered during implementation of ↵Owen Jacobson2024-09-25
| | | | vector-of-sequence-numbers stream resume.
* Redundant code missed in previous commit.Owen Jacobson2024-09-25
|
* Use a vector of sequence numbers, not timestamps, to restart /api/events ↵Owen Jacobson2024-09-25
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | streams. The timestamp-based approach had some formal problems. In particular, it assumed that time always went forwards, which isn't necessarily the case: * Alice calls `/api/channels/Cfoo` to send a message. * The server assigns time T to the request. * The server stalls somewhere in send() for a while, before storing and broadcasting the message. If it helps, imagine blocking on `tx.begin().await?` for a while. * In this interval, Bob calls `/api/events?channel=Cfoo`, receives historical messages up to time U (after T), and disconnects. * The server resumes Alice's request and finishes it. * Bob reconnects, setting his Last-Event-Id header to timestamp U. In this scenario, Bob never sees Alice's message unless he starts over. It wasn't in the original stream, since it wasn't broadcast while Bob was subscribed, and it's not in the new stream, since Bob's resume point is after the timestamp on Alice's message. The new approach avoids this. Each message is assigned a _sequence number_ when it's stored. Bob can be sure that his stream included every event, since the resume point is identified by sequence number even if the server processes them out of chronological order: * Alice calls `/api/channels/Cfoo` to send a message. * The server assigns time T to the request. * The server stalls somewhere in send() for a while, before storing and broadcasting. * In this interval, Bob calls `/api/events?channel=Cfoo`, receives historical messages up to sequence Cfoo=N, and disconnects. * The server resumes Alice's request, assigns her message sequence M (after N), and finishes it. * Bob resumes his subscription at Cfoo=N. * Bob receives Alice's message at Cfoo=M. There's a natural mutual exclusion on sequence numbers, enforced by sqlite, which ensures that no two messages have the same sequence number. Since sqlite promises that transactions are serializable by default (and enforces this with a whole-DB write lock), we can be confident that sequence numbers are monotonic, as well. This scenario is, to put it mildly, contrived and unlikely - which is what motivated me to fix it. These kinds of bugs are fiendishly hard to identify, let alone reproduce or understand. I wonder how costly cloning a map is going to turn out to be… A note on database migrations: sqlite3 really, truly has no `alter table … alter column` statement. The only way to modify an existing column is to add the column to a new table. If `alter column` existed, I would create the new `sequence` column in `message` in a much less roundabout way. Fortunately, these migrations assume that they are being run _offline_, so operations like "replace the whole table" are reasonable.
* Small design docOwen Jacobson2024-09-23
|
* Docs updatesOwen Jacobson2024-09-21
|
* Write tests.Owen Jacobson2024-09-20
|
* Docs updates:Owen Jacobson2024-09-20
| | | | | * Document message expiry. * More warnings about Last-Event-Id.
* Pass dates around by ref more consistentlyOwen Jacobson2024-09-20
|
* Put database prep somewhere tests can call it.Owen Jacobson2024-09-20
|
* Push the handling of the `Last-Event-Id` _format_ inside of `channels::app`.Owen Jacobson2024-09-20
| | | | This is intended to make it a bit more opaque to callers, and to free me up to experiment with the event ID format. It also makes event IDs tractable for testing.
* Push events into a module structure consistent with the rest of the project.Owen Jacobson2024-09-20
|
* Remove the HTML client, and expose a JSON API.Owen Jacobson2024-09-20
| | | | | | | | | | | | | This API structure fell out of a conversation with Kit. Described loosely: kit: ok kit: Here's what I'm picturing in a client kit: list channels, make-new-channel, zero to one active channels, post-to-active. kit: login/sign-up, logout owen: you will likely also want "am I logged in" here kit: sure, whoami
* Expire messages after 90 days.Owen Jacobson2024-09-20
| | | | | | | | | | This is intended to manage storage growth. A community with broadly steady traffic will now reach a steady state (ish) where the amount of storage in use stays within a steady band. The 90 day threshold is a spitball; this should be made configurable for the community's needs. I've also hoisted expiry out into the `app` classes, to reduce the amount of non-database work repo types are doing. This should make it easier to make expiry configurable later on. Includes incidental cleanup and style changes.
* Less Option calisthenicOwen Jacobson2024-09-20
|
* Blanket dependency upgrades, yolo editionOwen Jacobson2024-09-18
|
* Somewhere along the line this lifetime bound became redundant.Owen Jacobson2024-09-18
|
* Most pass-through errors do not need additional message textOwen Jacobson2024-09-18
|
* Log internal errors (and make it possible to track them down).Owen Jacobson2024-09-18
|