Tags: unkeyed/unkey
Tags
refactor(worker, dashboard): show steps when it starts not finishes (#… …7679) * feat(ctrl): write a build step row when the step starts Step rows were only written on completion, so a running step and the log entries it already wrote were invisible until it finished. ctrl now writes a row with completed_at = 0 when a vertex starts, and the normal row when it completes. * feat(dashboard): show a running build step Dedupe step rows per step_id, preferring the completed row, and show "running" instead of a duration while completed_at is 0. * chore: document running build step rows Define completed_at 0 on BuildStepV1, drop the ctrl comment it replaces, generate test ids, and note the running state in the build logs docs. * fix(dashboard): limit build step logs per step The logs query took the first 20 entries of the whole deployment, so noisy early steps used them all and every later step showed "No logs available". The limit now applies per step.
fix(cache): keep stale reads nonblocking during refresh overload (#7668) * fix(cache): keep stale reads nonblocking during refresh overload A full refresh queue must not make stale cache reads wait for the origin. Deduplicate queued and running refreshes, and leave dropped refreshes retryable on a later read. Do not treat caller cancellation as a shared ratelimit-origin failure. Keep real timeout and network failures eligible to trip the breaker. Measure refresh execution time, queue wait, enqueue depth, and enqueue outcomes before changing the existing worker and queue limits. Amp-Thread-ID: https://ampcode.com/threads/T-01a0f3ee-93a2-7520-99d0-f66d23246981 Co-authored-by: Amp <amp@ampcode.com> * Update cache.go Co-authored-by: polylane[bot] <277585245+polylane[bot]@users.noreply.github.com> * style(cache): format revalidation warning Amp-Thread-ID: https://ampcode.com/threads/T-01a0f3ee-93a2-7520-99d0-f66d23246981 Co-authored-by: Amp <amp@ampcode.com> --------- Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: polylane[bot] <277585245+polylane[bot]@users.noreply.github.com>
fix(cache): keep stale reads nonblocking during refresh overload (#7668) * fix(cache): keep stale reads nonblocking during refresh overload A full refresh queue must not make stale cache reads wait for the origin. Deduplicate queued and running refreshes, and leave dropped refreshes retryable on a later read. Do not treat caller cancellation as a shared ratelimit-origin failure. Keep real timeout and network failures eligible to trip the breaker. Measure refresh execution time, queue wait, enqueue depth, and enqueue outcomes before changing the existing worker and queue limits. Amp-Thread-ID: https://ampcode.com/threads/T-01a0f3ee-93a2-7520-99d0-f66d23246981 Co-authored-by: Amp <amp@ampcode.com> * Update cache.go Co-authored-by: polylane[bot] <277585245+polylane[bot]@users.noreply.github.com> * style(cache): format revalidation warning Amp-Thread-ID: https://ampcode.com/threads/T-01a0f3ee-93a2-7520-99d0-f66d23246981 Co-authored-by: Amp <amp@ampcode.com> --------- Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: polylane[bot] <277585245+polylane[bot]@users.noreply.github.com>
feat(api): accept remoteIp match conditions in gateway policies (#7639) * feat(api): accept remoteIp match expressions in gateway policies **tldr;** `gateway.setPolicies` and `gateway.updatePolicy` accept a `remoteIp` match with `in` or `notIn` CIDR lists. Needs the frontline PR deployed first. ```json { "remoteIp": { "in": ["203.0.113.0/24"] } } { "remoteIp": { "notIn": ["198.51.100.0/24", "203.0.113.7"] } } ``` Entries are stored as canonical prefixes, so frontline only parses prefixes and an unchanged policy round-trips byte for byte. ```sh 203.0.113.7 stored as 203.0.113.7/32 2001:db8::1 stored as 2001:db8::1/128 10.1.2.3/8 400, host bits set; use 10.0.0.0/8 ::ffff:203.0.113.7 400, use the IPv4 form fe80::1%eth0 400, not a valid IP or CIDR ``` Exactly one of `in` or `notIn`, 1 to 100 entries each. ## Also fixed `mapMatchExprToProto` treated `default` as queryParam, so any new matcher would have hit a nil dereference. queryParam is an explicit case now and `default` returns a 500. ## Heads up - `gen.go` and `openapi-generated.yaml` carry only the `remoteIp` hunks of the generator output. A full regen on main breaks the build today (libopenapi renames `BaseError`), fixed by #7629. Regenerate after it lands. - The dashboard cannot load an environment's policies once one uses `remoteIp`, until the dashboard PR ships. * fix(api): tighten remoteIp comments and document all rejected entries * fix(api): address pre-review findings on remoteIp * feat(api): accept IPv4 remoteIp entries only * docs(gateway): document remote IP match conditions * feat(api): support ipv6 entries * chore: stick to remote ip * fix: typo
feat(api): accept remoteIp match conditions in gateway policies (#7639) * feat(api): accept remoteIp match expressions in gateway policies **tldr;** `gateway.setPolicies` and `gateway.updatePolicy` accept a `remoteIp` match with `in` or `notIn` CIDR lists. Needs the frontline PR deployed first. ```json { "remoteIp": { "in": ["203.0.113.0/24"] } } { "remoteIp": { "notIn": ["198.51.100.0/24", "203.0.113.7"] } } ``` Entries are stored as canonical prefixes, so frontline only parses prefixes and an unchanged policy round-trips byte for byte. ```sh 203.0.113.7 stored as 203.0.113.7/32 2001:db8::1 stored as 2001:db8::1/128 10.1.2.3/8 400, host bits set; use 10.0.0.0/8 ::ffff:203.0.113.7 400, use the IPv4 form fe80::1%eth0 400, not a valid IP or CIDR ``` Exactly one of `in` or `notIn`, 1 to 100 entries each. ## Also fixed `mapMatchExprToProto` treated `default` as queryParam, so any new matcher would have hit a nil dereference. queryParam is an explicit case now and `default` returns a 500. ## Heads up - `gen.go` and `openapi-generated.yaml` carry only the `remoteIp` hunks of the generator output. A full regen on main breaks the build today (libopenapi renames `BaseError`), fixed by #7629. Regenerate after it lands. - The dashboard cannot load an environment's policies once one uses `remoteIp`, until the dashboard PR ships. * fix(api): tighten remoteIp comments and document all rejected entries * fix(api): address pre-review findings on remoteIp * feat(api): accept IPv4 remoteIp entries only * docs(gateway): document remote IP match conditions * feat(api): support ipv6 entries * chore: stick to remote ip * fix: typo
feat(api): allow null expiration on keys.rerollKey (#7642) * feat(api): make keys.rerollKey expiration optional Omitting expiration keeps the original key valid with its current expiry. Amp-Thread-ID: https://ampcode.com/threads/T-01a0ede3-e2de-726a-a35a-277a15675161 Co-authored-by: Amp <amp@ampcode.com> * feat(api): require explicit null to keep the original key on reroll Amp-Thread-ID: https://ampcode.com/threads/T-01a0ede3-e2de-726a-a35a-277a15675161 Co-authored-by: Amp <amp@ampcode.com> * fix(cli): use nullable expiration in reroll-key test Amp-Thread-ID: https://ampcode.com/threads/T-01a0ede3-e2de-726a-a35a-277a15675161 Co-authored-by: Amp <amp@ampcode.com> --------- Co-authored-by: Amp <amp@ampcode.com>
feat(api): accept remoteIp match expressions in gateway policies
**tldr;** `gateway.setPolicies` and `gateway.updatePolicy` accept a
`remoteIp` match with `in` or `notIn` CIDR lists. Needs the frontline PR
deployed first.
```json
{ "remoteIp": { "in": ["203.0.113.0/24"] } }
{ "remoteIp": { "notIn": ["198.51.100.0/24", "203.0.113.7"] } }
```
Entries are stored as canonical prefixes, so frontline only parses
prefixes and an unchanged policy round-trips byte for byte.
```sh
203.0.113.7 stored as 203.0.113.7/32
2001:db8::1 stored as 2001:db8::1/128
10.1.2.3/8 400, host bits set; use 10.0.0.0/8
::ffff:203.0.113.7 400, use the IPv4 form
fe80::1%eth0 400, not a valid IP or CIDR
```
Exactly one of `in` or `notIn`, 1 to 100 entries each.
## Also fixed
`mapMatchExprToProto` treated `default` as queryParam, so any new matcher
would have hit a nil dereference. queryParam is an explicit case now and
`default` returns a 500.
## Heads up
- `gen.go` and `openapi-generated.yaml` carry only the `remoteIp` hunks of
the generator output. A full regen on main breaks the build today
(libopenapi renames `BaseError`), fixed by #7629. Regenerate after it
lands.
- The dashboard cannot load an environment's policies once one uses
`remoteIp`, until the dashboard PR ships.
fix(ctrl): cap generated domain labels at 63 characters (#7622) * fix(ctrl): cap generated domain labels at 63 characters **tldr;** long branch names give preview URLs that never resolve. DNS caps one label at 63 characters (RFC 1035 section 2.3.4) and `buildDomains` never checked. Michael's branch URL on canary was 74. ```sh before homestead-home-tracking-git-michaelunkey-phase-8-ui-foundation-stagejune26 74, label too long after homestead-home-tracking-git-michaelunkey-phase-8-ui-fo-9141f508 63 ``` Every generated domain goes through `cappedDomain` now. A label over 63 keeps its first 54 characters, then `-` and 8 hex of the sha256 of the full label. The hash keeps `phase-8-ui-foundation` and `phase-8-ui-foundation-v2` apart, and it is deterministic, so a branch keeps its sticky domain across deploys. Labels of 63 or less do not change. Every label this changes never resolved, so no migration. ## Also fixed `sluggify` capped the branch at 80. Any branch that long already broke the label, and the cap made branches that differ after character 80 share one domain. Gone. ## Heads up - A cut label loses the workspace slug at the end. - 8 hex is 32 bits. Fine for accidents, not for someone brute forcing a collision. The real guard is an ownership check in `configureRouting`, which today reassigns any route with a matching FQDN, even across workspaces. Next PR. * refactor: Add workspace too
fix(api): read identities before inserting when attaching to keys (#7635 ) Key create and update ran INSERT ... ON DUPLICATE KEY UPDATE on every request with an externalId, taking a write lock even when the identity already existed. Read first and insert only on a miss. A lost insert race returns a duplicate-key error, and the whole transaction retries with a fresh snapshot. Amp-Thread-ID: https://ampcode.com/threads/T-01a0ece8-2b58-74fb-8139-635098b6c21d Co-authored-by: Amp <amp@ampcode.com>
PreviousNext