Previously, we would reject this with a 400 error. Considering the
request body is expected to contain "array of requests" and that arrays
may be empty, we really should not be rejecting the requests.
Prior to 156ca21472, sending the empty array would have been convenient
for channel creation. Empty arrays getting rejected forced clients to
inject a faux poke (commonly hi-ing oneself). With that recent change,
the most common case for wanting to PUT the empty list of requests is
largely obsolete, but one can still imagine it being useful for clients
that want to keep their channel alive without necessarily being
connected to it. This also implements sloppier clients from running into
400 responses when they submit an empty "command queue" for whatever.
Regardless, there seems to be no clear reason why the empty request list
_shouldn't_ be accepted and processed as normal.
We add a small test to ensure eyre accepts this.
Previously, a channel could only be created by sending a PUT request,
and a GET request to receive the channel's stream would only succeed
after channel creation had happened that way. This forces client
libraries, that generally have an explicit "set up" step before allowing
normal operation, to do strange things, like sending faux pokes
(commonly hi-ing oneself) before connecting to the channel's stream as
normal.
Here, we update the GET request handling for channels to allow requests
for non-existent channels. When this happens, the channel will be
created, and eyre tracks the request as normal.
We do some... gentle restructuring... of +on-get-request:by-channel to
let the new creation case share code with the "already exists" codepath.
In the process, we find that duct-to-key was never getting updated in
the case where we replace the original channel request/connection with
the new incoming one. We fix this, it's trivial. We also identify two
other areas with vaguely-incorrect behavior, but consider them less
important and out of scope.
We also add a test case for "create channel through GET".
Previously, for endpoints bound to agents, we would pass the request
onto the agent even if the agents wasn't currently running.
Here, we make eyre check to see if the agent is actually running, before
passing the request on. If the bound agent is not running, eyre serves a
503 synchronously instead.
This way, we avoid cluttering up the gall queue for the bound agent.
- let users disable automatic OTA merging for a sync or globally
- a sync can be set to manual, automatic or global default
- unapproved non-auto updates must be approved by the user
This commit adds `%tend` `%germ` and `%snip` to the notes that gall can
pass. `%tend` is analogous to `%grow`, except with a security group defined
by .coop.
### The coop system
A `$coop` is a path, which defines a security context for the portion of
the namespace that it prefixes. Each `$coop` receives a symmetric key,
which is used to encrypt requests and responses for any key-value pair
belonging to a coop.
### Network overview
This design requires a single handshake over ames to inform clients what
key is to be used. However, this handshake can be made less frequent by
including all paths underneath the `%coop` in the response, such that if
the user is requesting sibling paths under the same `%coop`, only one
handshake is required.
### Naming
I am utterly detached to all new names introduced, just trying to get
something down
### API Design
The most contentious part of this proposal will likely be the split
between `%grow` and `%tend`. I assert (rather weakly mind you) that this
is more ergonomic for the end user, although there's a strong argument
to be made that `%grow` should just take a `(unit coop)`. If this were
the case, however, it would muddy the semantics. If the value is
encrypted, then the ship,desk,case will be in the coop, else it will be
specified in the path. Worth noting that specifying the
`%coop` and the rest of the path seperately seems like it could be
unintuitive because the path that it will be bound to is actually
`(welp coop path)`
The lifecycles for coops seem straightforward, although worth revisiting
the invariants it maintains, and how it handles those invariants. A list of such:
- No nesting (obviously good)
- Crashing on binding publically into a private coop (crashing is bad,
do we want to deliver a notification? (See footnote 1))
- Crashing on binding into a coop that doesn't exist (same notes as above)
### Key generation
Current implementation is obviously stupid, how should i do it?
### Footnotes
1. Why are the remote scry datastructures notes and not gifts? Forgive
me being out of the loop, but we don't actually use the wire for
anything anywhere, and remote scry is giving gift anyway.
2. It's so good to be back
Instead of setting a new timer every time, we wait to hear a new %nack
for a %leave to do so, accumulating any unacked %leaves in the state for
up to ~m2. When the timers comes back, we re-send all outsanting %leaves
and skipp setting up a new timer.
The change introduced in 5422715c9b makes it very frequent for subscribers
to get stale facts on the subscriptions they are trying to leave so to not
clutter their dojo, we put the log under the %odd flag
+on-gall-response might detect the symptom of a bug, where we are
getting a %fact for a channel that has since been deleted. (Meaning that
subscription should have been cleaned up, and we shouldn't have received
the %fact.) We want to issue a %leave, but need to take care to do so
with the same identity that the subscription was opened on.
Previously, we would forcefully get the identity from the non-existent
channel, resulting in a crash. Now, we encode the identity into the wire
instead, so that we may retrieve it from there, even when the channel is
long gone.
Makes cosmetic changes to the login page of eyre. This addresses an issue with insufficient contrast between text elements and their backgrounds in dark mode.
This adds a %kiln-change-source poke that changes the sync source
for all syncs from the given remote ship/desk to a new ship/source.
This poke works remotely iff it comes from the publisher, allowing
publishers to migrate app distribution.
A %kiln-change-publisher poke is also added to kiln which sends this out
to all desk subscribers with the let+1 %w %sing that %kiln uses.
As of RFC 5789, PATCH is a valid HTTP request method. The $method:http type,
however, did not include it.
Here, we add it to the $method:http type, so that it now includes all nine
standard HTTP methods.
The 14-to-15 state migration was released in urbit-os-v2.142
so we add a new ames-state-16 to account for the removal of
.num-live from $pump-metrics.
This also adds several `$+` shorthand type name for better
prettyprinting in nest-fails situations, all related to the types in
$ames-state.
(note: ames states 14 and 15 are the same, ane tha migration
just re-retrieved our own %rift—first introduced in state-12-to-13)
The %kroc task was introduced in ames-state-10. The way the
migration works, is that queued-events are transformed right
away into the latests version, and the state is done step-wise in
different arms, but in one go as part of the +molt arm.
This means that all states from %10 need to handle cleaning up
the %kroc task, with the addition that we were already handling
another tasks, %snub, from ames-state-9 until ames-state-11.
This means that we need to handle both tasks in two different
ames-states, and from them only the %kroc task.
This also adds several $+ to the ames types, that make nest-failures
easier to read.
The fact that the target bone of a flow that we have received is a
naxplanation doesn't guarantee that there will be a naxplanation
flow (i.e. we have actually sent one) so instead of crashing, we just
continue processing the next bone.
The guest identities (#6561) and EAuth (#6598) features will both be
released as part of Zuse 412K, so their +load logic can be collapsed
into a single step.
Keeping a queue of nonces to match the outgoing %pleas we send lets us
recover the nonce for the %done we receive in response. This is
important in the nack case, where we may want to eagerly serve the HTTP
client an error page response, instead of waiting for the timeout timer
to fire.
We probably want something slightly fancier, like a banner or something,
that also shows up on the login page (and perhaps other "system" pages),
but for now this should suffice.
This was removed when the logic for re-subscriptions was taken from %ames
into the generator. Sorting allows us to keep the current (last) subscription
as the last in the list, and in this case we check if it received an ack for
a naxplanation—see https://github.com/urbit/urbit/issues/6065#issuecomment-1322011137—
in which case it's safe to be corked.
Instead of doing formal network traffic on the host-side whenever a
login attempt gets initiated, we now do it no earlier than when we're on
the client-side. This has the important property that network traffic
can only be initiated by authenticated HTTP requests. The previous
implementation, where hosts sent pleas when an unauthenticated HTTP
client said then wanted to log in, was vulnerable to abuse.
So now, formally, the eauth flow starts at the client's confirmation
screen. There is an optional step preceding this, where an attempt is
started on the host (and data is still stored for this), but to get the
redirect target, the host uses remote scry to get the eauth URL out of
the client ship.
Hosts now also give attempt-specific return URLs, useful in case they
are accessible (or even serving different content) from different
hostnames.
+on-kroc was cluttered with ad-hoc logic to indentify stale flows from
failed resubscriptions that were not properly %corked. Here we move
that logic to a generator that, if not in dry mode, will call %ames with a
(list [ship bone]) to %cork them.
Another option would be to move the logic in the generator to a state
update in ames, which will trigger possibly thousands of %ames messages
to be sent, on every ship that runs the state migration—these flows are
not causing a problem that neds to be addressed, and only take extra
space.
If we decide that this needs to be run by everyone, one solution could be
to set up a timer (maybe taking advantage of the fact that ships don't get
the OTA a the same time) that will eventually poke %hood with a
%helm-ames-kroc task.
(1) In `+thread-fail`, `+thread-clean` is called before `+thread-http-fail` and `+cancel-scry` meaning neither of the latter two actually. `serving` has been replaced with `(~(del by serving.state) tid)` in the state and therefore we cannot `(~(get by serving.state) tid)` in `+thread-http-fail` or `+cancel-scry`.
(2) In `+thread-http-fail` return an informative tang as json instead of an empty 500 http response when the failure results from an internal crash.
Description of the issue can be found here: https://github.com/urbit/urbit/issues/6625
The fix involved changing the instance of `+roll` to a `+spin` which increments a counter each time a column contains null tapes. Also, `+row`'s trap stops at the point when the null count equals the number of columns, indicating there's nothing left to render.