Repository navigation
Release 14.0.89 - #5238
Merged
Merged
Release 14.0.89#5238
Conversation
The AWS, Microsoft and Google Cloud usage reporters of a self-hosted Enterprise install bought on a cloud marketplace were in packages/Common/Server/Utils/Marketplace/SelfHosted, but only ee/ ever called them (the usage job and the marketplace license). They are behaviour, not schema, so they move to ee/Server/Marketplace/Reporters, with their tests, and the Community image no longer ships them. They reach core through Common/... specifiers only; the guides that name their location follow.
…ccess controls are Enterprise features Four license features, append-only like the rest: - custom-roles: creating and changing CustomRole, CustomRolePermission and TeamCustomRole needs the license (@TableEditionAccessControl). What a team holds through a role is its own TeamPermission rows, so it keeps applying in every edition; reading and deleting always work. - ip-allowlists: setting the ipWhitelist of a status page, dashboard or form. A list already set is enforced in every edition. - status-page-access-controls: a status page's session length, only private users can subscribe, and subscribers' email domains. Also enforced as set in every edition. - status-page-branding: hiding Powered by OneUptime. A runtime feature: the master page answers false unless the feature is active (StatusPagePoweredBy), so the Community Edition and a lapsed license show the line again, and the switch comes back on a renewal. The column gate learns a value rule per column: retention overrides keep theirs, every other enterprise column is cleared by its default (PlanGatedColumnDefault, the rule the Cloud plans already use), so a Community install can always remove what it configured. OneUptime Cloud is unchanged: the plans gate these on Scale.
… billing hooks OneUptime Cloud's billing is moving into the enterprise module. Core keeps asking for it, through two new optional members of the module contract: - getBillingProvider(): the payment provider (Stripe) BillingService will hand its calls to. Its interface, with the shared Invoice, PaymentMethod and PaymentIntentState types, is Server/Types/Billing/BillingProvider.ts, which loads nothing but Stripe's types. - getProjectBillingHooks(): what the cloud marketplaces and Vercel do when a project is deleted or a marketplace-billed project changes plan. EnterpriseEdition exposes both like getAuditLogRecorder: null on the Community Edition, for a module without the member, for a null answer (billing off) and for a module that throws (logged), never an error. FakeEnterpriseModule can hand out either, or throw.
…ace billing live in ee/ Selling OneUptime Cloud on AWS Marketplace, Microsoft Marketplace, Google Cloud Marketplace and Vercel Marketplace is OneUptime Cloud's billing, so it moves to ee/Server/CloudMarketplace and the Community image no longer ships it: - the marketplace routes (MarketplaceAPI), the provider API Vercel calls (VercelMarketplaceProviderAPI) and sign-in from Vercel (VercelSignIn); - each marketplace's client, adapter and inbound handling (AWS, Azure, Google Cloud, Vercel), the adapter registry, the claim token, the purchase claim and sync, the usage calculator, reporter and summarizer; - the Marketplace:ReportUsage, Marketplace:SyncPurchases and Marketplace:VercelBilling jobs; - recordPurchase, updatePurchase, issueClaimToken, findPurchaseByClaimToken, linkToProject and unlinkProject, now MarketplacePurchases. The CRUD service keeps its lookups. The CloudMarketplace area contributes all of it only with billing on: the routers through getApiRouters, sign-in from Vercel through getIdentityRouters (after SSO, whose paths are unchanged), the jobs through registerWorkerJobs (their names are now ee-owned, so core gives them placeholders), and ProjectBillingHooks through getProjectBillingHooks. ProjectService no longer imports the marketplaces: with billing on it tells the hooks before and after a delete and after a marketplace plan change, and a hook that fails never fails the change. Every edition keeps what it uses: MarketplaceHttp and RemoteJwtVerifier (Sign in with Microsoft) and VercelSignature (the Vercel log drain). The Google Cloud client signs its assertion through JsonWebToken, so ee needs no JWT library of its own. The tests of the moved code move to ee/Tests/Server/CloudMarketplace. New tests cover the area with billing on and off, the hooks on their own and from ProjectService with the real module, ProjectService calling them only with billing on, and a core guard that no core file loads the moved code or serves a marketplace route. The guides name the new paths.
…tatus page branding and access controls are Enterprise screens The custom role pages, the IP allowlist card (status pages, public dashboards and forms), a status page's reader session limit and subscriber restrictions, and its Powered by OneUptime switch move into ee/Dashboard (CustomRoles, IpAllowlists, StatusPageAccessControls, StatusPageBranding). Core keeps a shell for each that draws the Enterprise card, or the upsell. What a record already has keeps applying in every edition, so under the upsell each shell lists it with the one move every edition allows: removing it. On OneUptime Cloud below the Scale plan the same card shows. Powered by OneUptime is runtime: the Community Edition shows the line on every status page, so there is nothing to remove there. Under a lapsed or excluding license the Enterprise cards say so and offer only what the server accepts (remove, delete), via a shared notice. Docs (all 17 languages): the edition matrix, what stops and what keeps applying on a lapse or a switch to Community, the custom roles section, each feature's own section, the status page Powered by card, and an upgrade note. The Home self-hosted page and claims list the moved features. Tests cover the shells, the ee cards and the docs.
…ervice is a facade The Stripe client is OneUptime Cloud's card billing, so it moves to ee/Server/Billing/StripeBillingProvider.ts (the BillingProvider interface) and the Community image no longer ships it. The new Billing area builds the one provider of the process on first use, and only with billing on; the enterprise module hands it to core through getBillingProvider. Core keeps BillingService with the same singleton, method names and signatures, so its callers and the core tests that spy on it are unchanged. Each method hands its call to the provider. Without one - the Community Edition, billing off, a module that answers null or throws - it answers as a server without billing does and never reaches a payment provider: BILLING_NOT_ENABLED for what reads or changes a payment provider's records, shouldSendInvoicesByEmail false, handleWebhookEvent ignores the event. isBillingEnabled, isSubscriptionActive, isTestEnvironment and the metered price ids stay in core; ProjectService.getCurrentPlan reads SubscriptionStatusUtil. Core loads Stripe's types only (import type), and stripe is now an ee dependency. The Stripe tests and their helpers move to ee/Tests/Server/Billing and test the provider; the Stripe mock no longer needs jest-mock-extended. New tests cover the facade with and without a provider (every method, exact arguments, refusals passed through), the Billing area with billing on and off (no Stripe client is built with billing off), the facade with the real module, and a core guard that no core server file loads stripe at runtime.
…ommunity-image-split-625da3 # Conflicts: # packages/App/FeatureSet/Dashboard/src/Locales/da.json # packages/App/FeatureSet/Dashboard/src/Locales/de.json # packages/App/FeatureSet/Dashboard/src/Locales/en.json # packages/App/FeatureSet/Dashboard/src/Locales/es.json # packages/App/FeatureSet/Dashboard/src/Locales/fa.json # packages/App/FeatureSet/Dashboard/src/Locales/fr.json # packages/App/FeatureSet/Dashboard/src/Locales/hi.json # packages/App/FeatureSet/Dashboard/src/Locales/it.json # packages/App/FeatureSet/Dashboard/src/Locales/ja.json # packages/App/FeatureSet/Dashboard/src/Locales/ko.json # packages/App/FeatureSet/Dashboard/src/Locales/nl.json # packages/App/FeatureSet/Dashboard/src/Locales/no.json # packages/App/FeatureSet/Dashboard/src/Locales/pt.json # packages/App/FeatureSet/Dashboard/src/Locales/ru.json # packages/App/FeatureSet/Dashboard/src/Locales/sv.json # packages/App/FeatureSet/Dashboard/src/Locales/zh-CN.json # packages/App/FeatureSet/Dashboard/src/Locales/zh-TW.json # packages/App/FeatureSet/Dashboard/src/Pages/Teams/RoleView.tsx # packages/App/FeatureSet/Dashboard/src/Pages/Teams/Roles.tsx # packages/App/FeatureSet/Docs/Content/da/permissions/index.md # packages/App/FeatureSet/Docs/Content/de/permissions/index.md # packages/App/FeatureSet/Docs/Content/en/permissions/index.md # packages/App/FeatureSet/Docs/Content/es/permissions/index.md # packages/App/FeatureSet/Docs/Content/fa/permissions/index.md # packages/App/FeatureSet/Docs/Content/fr/permissions/index.md # packages/App/FeatureSet/Docs/Content/hi/permissions/index.md # packages/App/FeatureSet/Docs/Content/it/permissions/index.md # packages/App/FeatureSet/Docs/Content/ja/permissions/index.md # packages/App/FeatureSet/Docs/Content/ko/permissions/index.md # packages/App/FeatureSet/Docs/Content/nl/permissions/index.md # packages/App/FeatureSet/Docs/Content/no/permissions/index.md # packages/App/FeatureSet/Docs/Content/pt/permissions/index.md # packages/App/FeatureSet/Docs/Content/ru/permissions/index.md # packages/App/FeatureSet/Docs/Content/sv/permissions/index.md # packages/App/FeatureSet/Docs/Content/zh-CN/permissions/index.md # packages/App/FeatureSet/Docs/Content/zh-TW/permissions/index.md # packages/App/Tests/FeatureSet/Docs/CustomRolesDocs.test.ts
…ve in ee/ The five jobs that keep projects' subscriptions and metered usage in step with Stripe are OneUptime Cloud's billing, and did nothing without it, so they move from core's Workers to ee/Server/Billing/Jobs: - PaymentProvider:CheckSubscriptionStatus - PaymentProvider:PopulatePlanNameInProject - PaymentProvider:UpdateTeamMembersIfNull - PaymentProvider:SendDailyEmailsToOwnersIfSubscriptionIsOverdue - MeteredPlan:ReportTelemetryMeteredPlan The Billing area registers them through registerWorkerJobs, only with billing on, with their names and schedules unchanged. Their names are now ee-owned, so a repeatable definition an earlier release left in Redis gets core's no-op placeholder wherever ee does not register it. The seat-count job's test moves with it. New tests cover the area registering all five on their schedules with billing on, none with billing off, nothing twice, and a registered job doing nothing once billing is off; the core guard pins that core's Workers no longer has or loads them. With no billing email left in core, the email subject check drops its billing exemption.
The ee README names the Billing and CloudMarketplace areas, and a new section says what OneUptime Cloud bills from ee/ (the Stripe client, the subscription and metered plan jobs, the cloud marketplaces and Vercel Marketplace), how core reaches it (getBillingProvider and the BillingService facade, getProjectBillingHooks, the area hooks and the ee-owned job names), and what every edition keeps in core.
…d's billing jobs The DefaultExport fixture registers none of OneUptime Cloud's billing jobs, so under real node + ts-node the loader gives each its no-op placeholder: the three marketplace jobs and the five subscription and metered plan jobs, now that ee owns them.
… failures toPaymentProviderReadFailure and writePaymentProvider moved with the Stripe client to ee/Server/Billing/StripeBillingProvider.ts; the E2E billing helper and a payment method API test still named them on BillingService.
…on teams Master gave API keys custom roles while this branch made custom roles an Enterprise feature. Bring the two together: - ApiKeyCustomRole is gated like TeamCustomRole: a key is given a role only on the Enterprise Edition with a license that includes custom roles (or on OneUptime Cloud's Scale plan); taking a role from a key always works, and what a key already holds keeps applying (its own ApiKeyPermission copies). - The key's Custom Roles card and the role page's API Keys card move to ee/Dashboard/CustomRoles, read-only under a lapsed license. Core keeps a shell on the key's page (ApiKeyCustomRolesSettings) that lists the roles a key still has, with Remove, on the Community Edition and below the plan. - Create API Key, like Create Team, offers custom roles only where the project may use them. - The custom roles browser fixture resolves the ee plugin as the Dashboard's build does and skips its Enterprise-only specs without ee/. - Docs: the edition matrix and the custom roles paragraph name API keys. Also pins master's ApiKeyCustomRole.apiKey relation in the workflow credential-settings survey, which master's own test had not caught up with.
… lives in ee/ # Conflicts: # ee/README.md
…e's Stripe billing provider
…ommunity-image-split-625da3 # Conflicts: # packages/App/FeatureSet/Dashboard/src/Locales/da.json # packages/App/FeatureSet/Dashboard/src/Locales/de.json # packages/App/FeatureSet/Dashboard/src/Locales/en.json # packages/App/FeatureSet/Dashboard/src/Locales/es.json # packages/App/FeatureSet/Dashboard/src/Locales/fa.json # packages/App/FeatureSet/Dashboard/src/Locales/fr.json # packages/App/FeatureSet/Dashboard/src/Locales/hi.json # packages/App/FeatureSet/Dashboard/src/Locales/it.json # packages/App/FeatureSet/Dashboard/src/Locales/ja.json # packages/App/FeatureSet/Dashboard/src/Locales/ko.json # packages/App/FeatureSet/Dashboard/src/Locales/nl.json # packages/App/FeatureSet/Dashboard/src/Locales/no.json # packages/App/FeatureSet/Dashboard/src/Locales/pt.json # packages/App/FeatureSet/Dashboard/src/Locales/ru.json # packages/App/FeatureSet/Dashboard/src/Locales/sv.json # packages/App/FeatureSet/Dashboard/src/Locales/zh-CN.json # packages/App/FeatureSet/Dashboard/src/Locales/zh-TW.json
… plugin key list names ApiKeyCustomRoles
…in Git repositories CodeRepositoryType gains Forgejo and Git beside GitHub and GitLab. A new internal model, CodeRepositoryConnection, holds how a project reaches a Git server that is not GitHub: its address, the account its token acts as, and the encrypted, write-only credentials. CodeRepository names its connection (server-written only). The server reads those servers through one guarded transport (egress guard, pinned addresses, no redirects, size and time caps): ForgejoApi (Forgejo, Gitea, Codeberg), GitLabApi, and GitSmartHttp for any Git repository's branches over smart HTTP. CodeHostAccess turns a repository into one reader, whatever its host, and says which are reachable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Code's connect routes (/code-repository-connection/*): list the repositories a token reaches, connect the ones picked (each read again from the server by id), connect a Git repository by its HTTPS address (checked over smart HTTP, or saved for a project Runner when OneUptime cannot reach it), replace a connection's token, list connections. Who may connect is what connecting GitHub asks. - Reachability everywhere reads CodeHostAccess: Code's gate (new blockers RepositoryTokenRefused and RepositoryNeedsOwnRunner), the repository JSON (provider and connection, never a token), the branch picker, stack trace resolution, source links, OneUptime AI reading code, profile fixes, fix readiness and SubjectCodeFixRun.hasConnectedRepository. - The Runner's token route hands a GitLab, Forgejo or Git repository's token with where to use it (codeHost) only to a Runner that supports the host and can reach it, after the server checked the token. - Pull/merge request state and CI sync for GitLab and Forgejo. - Chat's code-writing tools and a deploy's commits stay GitHub's, and say so plainly for other hosts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Token requests say which hosts this Runner supports; a token for a repository that is not on GitHub comes with codeHost (server, API, username Git signs in with). - Clone and push a repository that is not on GitHub through GitHostGuard: the egress guard (a global Runner reaches the internet only, never http), git pinned to the checked addresses (http.curloptResolve) and no redirects. Git signs in with the connection's username. - PullRequestOpener opens the change's pull request on GitHub (as before), Forgejo and Gitea (pulls), or GitLab (merge requests). A Git repository has none: the branch is pushed and the run's outcome says where it is and where to open the pull request (PushedBranches), instead of no fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Connect repositories asks where the code is: GitHub (the App, as before), GitLab or Forgejo/Gitea (server address and an access token, then pick the repositories it can push to), or any Git server (HTTPS address and credentials; one only a project Runner reaches is asked about first). The empty Code page offers the other hosts under Connect GitHub, and is the way to connect on a server with no GitHub App. - Each host's mark everywhere a repository is named (list, picker, task rows, task header, turns); a self-hosted server is named beside its organization/name; a refused token shows as Token refused. - Settings: Repository Details says how a repository off GitHub connects (server, account, the token's last characters) with Replace access token, what it means when the token was refused or the server is only reachable by a project Runner, and plainly what works on GitHub only. More settings holds only what the host has: no GitHub commands, trigger label or production reviews off GitHub; a Git repository has Branches instead of Pull Requests. - GitLab merge requests are named as GitLab names them (!12); a Git repository's footers say AI pushes a branch for the person to open the pull request from. - Blockers for a refused token (Replace access token) and for a private Git server with no project Runner (Pick a Runner); a lost connection off GitHub is not told to connect GitHub. The branch picker never reads a server only a Runner reaches. - Production Reviews leaves the menu off GitHub and says why if opened. - 98 new strings, translated in all 16 languages. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ify fixes on GitLab and Forgejo - A repository's token now says whether the Runner may reach a private network (isPrivateNetworkAllowed): always for a project's own Runner, and for a global Runner only where OneUptime's server may too - a self-hosted OneUptime, whose bundled Runner runs on its operator's network. OneUptime Cloud's global Runners still reach the internet only, over https. GitHostGuard pins and checks with the server's answer. - Fix verification in production asks GitLab (repository compare) and Forgejo or Gitea (compare base...head) whether a deploy contains the fix's merge commit, through the repository's connection, as GitHub's compare is asked; a plain Git server counts a deploy of the fix's own commit only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dashboard API (#5140) A network controller connection holds a Meraki organization's read-only API key (encrypted, never returned) and is read on a schedule: the organization's uplink usage in five-minute windows - one call for every appliance - and, every two hours, each network's traffic analytics (applications, destinations, flows) and client usage. The reader paces itself to a share of the organization's 10 requests a second, honours 429 Retry-After, follows Meraki's own redirects and page links only, and reads incrementally from cursors; rows land in the new NetworkTrafficUsage table, read through the device they belong to, and /network-traffic/usage-summary answers a Traffic page's Meraki side. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… languages - Code gets a Connect a repository section: the four places a repository can be, how each connects (the GitHub App, an access token with the scopes it needs, or a Git server's HTTPS address and credentials), what AI does in each - commands from comments and production reviews are GitHub's for now; a Git server gets a pushed branch and you open the pull request - tokens kept encrypted with Replace access token and Token refused, and a Git server on a private network (Connect anyway, for a project Runner; a self-hosted OneUptime reaches its own network). - Before you begin, Open Code and the automatic fix and telemetry pull request requirements no longer say the GitHub App only; the GitLab integration and the exception page say AI works in GitLab repositories. - The roadmap's GitLab support entry is gone. - CodeRepositoryHostsDocsFacts holds the section to CodeHost and the connect dialog's words; the other facts suites follow the new lines. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…og and the connections card (#5140) A Traffic page that has Meraki traffic gets a Flows | Meraki switch in its header (kept in the URL); a page with Meraki traffic and no flow records opens on Meraki. The Meraki side draws the same tiles and chart from the appliances' uplinks (download and upload), Top networks or the uplinks, and Top applications, clients and destinations from Meraki's traffic analytics, with one line per connection saying how it is doing. The whole network's page offers Connect Meraki in its set-up guide and lists the connections at its foot: status, what the last read covered, Read now, edit, turn off, delete. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Meraki side of the Traffic pages, the connect and edit dialogs and the connections card, translated into the 16 Dashboard languages; brand and technical words that read the same are recorded as such, and the uplink rows and chart reuse the flow side's In / Out wording. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…gation and fixing were off for an incident or alert The incident and alert AI card used to fill the page with two cards that both said nothing happened. When the record was not investigated for a reason the project chose (AI off, automatic investigation off, no AI rule that investigates matched, severity below the minimum) and fixing did nothing for one either, the card is now one quiet line - what is off and why - that opens to say what to turn on, where, and who can. Ask OneUptime AI stays on the line while AI is on. The Remediation card leaves its 'nothing was fixed' lines to that line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…oard API (#5140) The client, the reader, the connector, the runner, the scheduler, the rows and the connection service, against a fake Meraki dashboard API on a test clock: pacing, 429s, redirects, paging, budgets, windows, cursors, failures. What the tests found, fixed here: - A read whose rows were stored but whose cursor was not recorded (the bookkeeping write failed, or the insert's answer was lost) read its first application window again from a new start, so it counted twice. The runner now moves the cursors up to where the connection's stored windows end before it reads, and a network's applications and clients of a window go in one insert, so its stored end is its cursor. - Stored window starts and the freshness times are read as epoch milliseconds, never as text in the server's time zone. - The longest window is 25 hours: a day's backfill ends when the read asked. - Testing a saved connection keeps its own organization and region, as a save does, so its stored key is only tested where it reads. - A count is a number or numeric text only; a cut never splits a character. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ay act, the conversation and the Remediation card beside it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…an do' where it was still English Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…longest word whole Dutch's Aanmeldgebeurtenissen is 161px: the Data column now caps at 11rem rather than 10rem, so it is never cut mid-word, and the Rule column gives way down to 11rem rather than 12rem, so Dutch fits production's 1024 beside the side menu as German and Swedish do (Dutch was 2px over). Measured in English, German, Swedish, Dutch and Japanese at 1024 and 1280. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Audit log export (Enterprise): a project's or the whole instance's audit log to S3, GCS, Azure Blob, a webhook or syslog
…fix suggestion AI rules now trigger on Incident, Alert, Profile and Trace, and Common/Utils/Suggestions holds TelemetryAiFixSuggestion, Fix with AI's offer on a telemetry lane's finding. The routing test passes a verdict's classification as the string it is, for the strict test compile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-traces Master's AddAuditLogExport took 1807110000000, so the Traces AI switch migration is renumbered to 1807120000000. The locale files' conflict (both sides appended keys) is merged by npm run i18n:extract. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, its adds beside the search, and a dialog that leaves the page where it was UI review of #5233 (security-rule-library-overhaul). - Filters: the three native selects (each as wide as its longest option, wrapping into a ragged stack beside the side menu) are now the filter row every list in OneUptime draws - FacetFilterBar's "Filter", the FilterChipDropdown chips Session Replay and the host lists use, "Clear all" - named Rule category, Data and Status, the value picked beside the name in the words the rows use (Data · Receiving, Status · Not added). How many rules are in sight follows the chips, and is not drawn while the rules are read or could not be. Clear all empties the chips, not the search, which has its own x. - The Data chip is offered only while it can narrow the list: not when the project's events could not be read, nor when none arrived this week (both said under the chips, now with an icon); a data filter kept from the address meanwhile narrows nothing and is not counted (getEffectiveRuleLibraryFilters, countRuleLibraryChipFilters). - The header's adds stay beside an opened search (keepButtonsWhileSearching): a model table folds its buttons while searching, which hid Add N Matching Rules the moment there was something to match. The opened search is 20rem, so on a 1280 laptop the header keeps the title's line instead of jumping under the description at the first letter. - Common Modal takes its first focus with preventScroll. The Dashboard draws its Tailwind as classes first appear, so the first dialog a page opens was focused before its overlay was fixed, and the focus scrolled the page to the panel's place at its foot: Add 17 Recommended Rules left the reader 4,500px down the list, behind the dialog and after it. Product-wide. - A row's Add that cannot be pressed (a role that cannot add, another add on its way) looks it; the outline button has no disabled look of its own. - A rule's details: "No events of this kind arrived..." sits in the box that says how to send them, not between it and the rule's events. - Strings: "Rule category" in 17 languages ("Category" is still English in twelve, whose docs quote it as drawn); the select-only strings dropped. Tests: the page's jsdom suite follows the chips (48 tests, 7 new: the chip row, Clear all and a chip's x, the count while reading, a data filter set aside, the search keeping the adds, the unavailable look while adding, the sentence in the box); the model's (59, 2 new); Modal's first focus without scrolling; the browser suite's library tests on the chips, plus the dialog that leaves the page where it was (1280, 390) and the search's ⋯ adding what it finds. Each new test fails with its fix taken out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s under its name Side by side, a German "Anmeldeereignisse · Empfangen" left the rule names a third of the dialog, three lines each. Each rule now reads as a phone draws a library row: its name, and under it the events it reads and whether they arrive. The browser suite checks the events sit under the name (it fails with the side-by-side layout back), and a rule whose events do not arrive has no "arrived" sentence in its details. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the evidence as written, Fix with AI in the rail - Create Monitor on a trace finding was greyed out with "cannot be created from this kind of insight yet" on all three kinds. A failing operation now opens a Traces monitor on its failed spans (its span name, the Error status, its service, the past hour) at the detector's own floor of 20 failed spans; a slow operation keeps the button, disabled, with a reason of its own (no monitor watches how long an operation takes yet); missing tracing draws no button at all - a monitor could never count what a trace lacks. The operation's name reaches only the span filter, never the monitor's words. - Monitor Create from any AI insight, link or template drew "props.initialValue.toJSON is not a function" and no status to pick: the archived-values read called toJSON() on steps that arrive as JSON. It reads them as text now, whatever their shape (MonitorSteps.tsx). - The evidence a finding shows is the detector's own, built by a pure buildTraceInsightDetail the offline fixture now draws too (it showed made-up prose). Fixed in it: a service's look wrote "p50 0 ms", list items opened in lower case, "Request read" said nothing, code locations sat inside the repeated-pattern list, and "In 5 of the 5 most recent failures" reads "In each of the 5". - Fix with AI in a finding page's narrow rail: the repository picker and the button sat side by side and squeezed the button into "Fix / with / AI". Both strips (Traces' and the Profiler's) stack by a container query now, side by side only where the strip is wide enough. - The Traces lane's summary lines promised a pull request for every problem; a failing operation's waits for the code to be found at fault, and a fix may find nothing to change: "for each one it can fix". - 14 strings in all 16 languages; 4 replaced keys dropped everywhere. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
translateText answers string | undefined: each option falls back to its English name, as the rest of the library does. Common compile-tests and the Dashboard's tsc type-check again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…st for each problem it can fix - in 17 languages; tests for the review - Traces Explorer: "On a failing operation, **Create Monitor** sets up a Traces monitor on its failed spans." and the AI rules line says a pull request opens "for each one it can fix", in all 17 languages, with the Dashboard's own label for Create Monitor in each. TracesAiDocsFacts pins both to the lane's copy and to the monitor prefill. - The real Monitor Create page opens on the Traces monitor from a failing operation and says the slow operation's reason instead of a form (MonitorCreateFromAIInsight). - The strip layout is keyed to its container, never the window, the button never wraps, and both strips use it (TelemetryAiFixCopy); no summary line promises a pull request for each problem (TelemetryAiCopy). - Offline browser specs: the evidence as the detector writes it, Create Monitor on each kind of finding, the picker stacked in the rail and side by side at 1024; the fixture's notes and README say what it draws. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…final UI The filter chips, the add dialog's stacked rules, the details' grouped box, a new project's notice, German and Japanese - and a new frame of a search whose ⋯ adds the rules it finds. Taken from the offline fixture at production widths, 2x, palette-compressed as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ackfill Common Test (7/8) failed on eff0cfa: BackfillFileOwners1797900000000 "reads the inline images of every markdown column people write in" found AutoRemediationRule.aiContext among the models' markdown columns but not in the migration's list. #5230 added that column (migration 1807100000000), long after the backfill ran; as the test's own note says of columns added later, its files are uploaded with their project and need no backfill. It joins MARKDOWN_COLUMNS_ADDED_LATER beside the security case columns. The suite passes (11/11) with CI's settings on a7b661e. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d; /install.sh is the new installer Master's test-image E2E (run 40081137635 on eff0cfa) failed two tests, both on what merged PRs changed on purpose: - Forms D6 "an IP allowlist that leaves this network out shuts the form to it" (saas 3 and 4, self-hosted 2) waited 30 s for the Share page's Access card. #5216 made setting an IP allowlist an Enterprise feature: OneUptime Cloud sells it on Scale (this project is on Growth) and a self-hosted install needs the Enterprise Edition, so on both stacks the page now draws the "IP Allowlist" upsell instead. D6 waits for either card. Under the upsell it checks the card offers the right step ("Upgrade to Scale" with billing, "Learn about Enterprise Edition" without) and that nothing offers Edit IP Allowlist, then skips with the reason. Where the Access card is drawn, the save must go through, and a refusal fails the test with its text (it used to be read as the plan gate). - Home "/install.sh serves the OneUptime installer" (saas 1 and 4) expected the old script's "#!/bin/bash" and "OneUptime Installation Script". #5229's installer (ba2bb05) starts "#!/usr/bin/env bash" and calls itself neither. The spec reads a bash shebang and "Installs OneUptime with Docker Compose", and Home's Redirect.test.ts now holds Home/Scripts/Install.sh to the same two marks on every commit (mutation-checked: a #!/bin/sh shebang fails it), so a rewrite fails there first. The licensed Enterprise E2E stack, where an allowlist can be set, runs only Enterprise/Licensed; covering D6's full path there is a follow-up. E2E tsc, eslint and prettier are clean; Home's Redirect suite passes (37/37). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e reflow after a resize Master's self-hosted E2E (shard 2, run 40081137635) reported "registers a security key on the separate two-factor page and keeps credential lists distinct" flaky: right after setViewportSize to 390 px, one read of documentElement.scrollWidth <= innerWidth came back false, and the retry passed on the same build - the read caught the page still laid out at the wider width. All three such checks in the spec (two-factor page, passkeys page, sign-in page) now go through expectNoHorizontalScroll, which polls the same comparison for up to 10 s, so a layout that really overflows still fails. E2E tsc, eslint and prettier are clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Six more tests (the evidence as the detector writes it, Create Monitor on each kind of finding, the picker in the narrow rail): 1.5 minutes with its bundle locally, from 1.3 - about 21.3 for the group's ten suites. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-traces Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…overhaul Security Events: the Rule Library as a list to scan, filter and add from
…-traces Locale files merged by key: master's new keys and this branch's, no key changed on both sides. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Group 8 took 22.4 minutes on master's last green App Test run without it, and group 1 14.9: with Traces AI's 1.5 minutes group 8 would have passed the 22-minute mark the groups are kept under. About 16.5 for group 1 now. Its screenshots and traces upload as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Traces gets an AI tab: find and fix slow, failing and under-traced operations with pull requests
…ule Library's Data filter App Test (1/3, 2/3) failed on 6b55b79. #5233 gave the Rule Library a Data filter whose options name the events a rule reads, so the Dashboard's locales gained "Data" (translated in each language) and "Okta System Log" (the same in every language). Two docs guards still filed them as words no locale has: - InfrastructureMonitorDocsTranslations listed the host monitor page's "**Data**" as a prose lead, which may not be a label. It is the comparison table's row head, beside Agent, Criteria and Setup, so it joins them in PROSE: a label by coincidence that a translation words as its language needs. - IntegrationsDocsTranslations kept the Okta page's "Okta System Log" as written because no locale had it. It is a label now and every locale draws it as written, so it leaves KEPT_AS_WRITTEN and is held to the drawn label like any other; the note lists it with the earlier connection settings that became labels. Both suites pass (8,307 tests), as do the ten other suites that import these lists (1,746). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
Comment on lines
+180
to
+182
| !String(claims["scope"] || "").includes( | ||
| "https://www.googleapis.com/auth/devstorage", | ||
| ) || |
| ): void { | ||
| this.router.post( | ||
| `${CODE_REPOSITORY_CONNECTION_API_PATH}${path}`, | ||
| UserMiddleware.getUserMiddleware, |
|
|
||
| this.router.post( | ||
| `${basePath}/test`, | ||
| UserMiddleware.getUserMiddleware, |
Comment on lines
+70
to
+147
| async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => { | ||
| try { | ||
| const props: DatabaseCommonInteractionProps = | ||
| await CommonAPI.getDatabaseCommonInteractionProps(req); | ||
| const projectId: ObjectID = | ||
| CommonAPI.assertAuthenticatedProjectMember(props); | ||
| this.assertCanOperate(props); | ||
|
|
||
| const body: JSONObject = | ||
| req.body && typeof req.body === "object" && !Array.isArray(req.body) | ||
| ? (req.body as JSONObject) | ||
| : {}; | ||
|
|
||
| let toTest: { apiKey: string; config: NetworkControllerConfig }; | ||
|
|
||
| try { | ||
| toTest = await this.readSettingsToTest({ body, projectId, props }); | ||
| } catch (error) { | ||
| /* | ||
| * Settings the form can still fix (a key that cannot be one, a | ||
| * region that is not Meraki's) are the test's answer, shown in | ||
| * the form - not a failed request. | ||
| */ | ||
| if (!(error instanceof BadDataException)) { | ||
| throw error; | ||
| } | ||
|
|
||
| const result: NetworkControllerTestResult = { | ||
| provider: NetworkControllerProvider.Meraki, | ||
| status: "fail", | ||
| message: error.message, | ||
| failureKind: LlmConnectionFailureKind.Settings, | ||
| organizations: [], | ||
| durationMs: 0, | ||
| }; | ||
|
|
||
| return Response.sendJsonObjectResponse( | ||
| req, | ||
| res, | ||
| result as unknown as JSONObject, | ||
| ); | ||
| } | ||
|
|
||
| const result: NetworkControllerTestResult = | ||
| await NetworkControllerConnectorRegistry.getConnector( | ||
| NetworkControllerProvider.Meraki, | ||
| ) | ||
| .testConnection(toTest, { | ||
| transport: DataSourceHttpFetch.fetch.bind(DataSourceHttpFetch), | ||
| }) | ||
| .catch((error: unknown): NetworkControllerTestResult => { | ||
| // testConnection never throws; this is the belt to its braces. | ||
| const failure: LlmProviderError = LlmProviderError.from({ | ||
| error, | ||
| step: "test", | ||
| providerTitle: "Meraki", | ||
| secretValues: [toTest.apiKey], | ||
| }); | ||
|
|
||
| return { | ||
| provider: NetworkControllerProvider.Meraki, | ||
| status: "fail", | ||
| message: failure.message, | ||
| failureKind: failure.kind, | ||
| organizations: [], | ||
| durationMs: 0, | ||
| }; | ||
| }); | ||
|
|
||
| return Response.sendJsonObjectResponse( | ||
| req, | ||
| res, | ||
| result as unknown as JSONObject, | ||
| ); | ||
| } catch (error) { | ||
| next(error); | ||
| } | ||
| }, |
|
|
||
| this.router.post( | ||
| `${basePath}/:connectionId/read-now`, | ||
| UserMiddleware.getUserMiddleware, |
Comment on lines
+154
to
+194
| async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => { | ||
| try { | ||
| const props: DatabaseCommonInteractionProps = | ||
| await CommonAPI.getDatabaseCommonInteractionProps(req); | ||
| const projectId: ObjectID = | ||
| CommonAPI.assertAuthenticatedProjectMember(props); | ||
| this.assertCanOperate(props); | ||
|
|
||
| const connectionId: string | undefined = req.params["connectionId"]; | ||
|
|
||
| if (!connectionId || !ObjectID.isValidUUID(connectionId)) { | ||
| throw new BadDataException("A valid connection ID is required."); | ||
| } | ||
|
|
||
| const connection: NetworkControllerConnection | null = | ||
| await this.service.findOneBy({ | ||
| query: { _id: connectionId, projectId }, | ||
| select: { _id: true, projectId: true, isEnabled: true }, | ||
| props, | ||
| }); | ||
| CommonAPI.assertResourceBelongsToProject({ | ||
| resourceProjectId: connection?.projectId, | ||
| projectId, | ||
| }); | ||
|
|
||
| if (!connection?.isEnabled) { | ||
| throw new BadDataException( | ||
| "This connection is turned off. Turn it on to read it.", | ||
| ); | ||
| } | ||
|
|
||
| await NetworkControllerScheduler.enqueue( | ||
| new ObjectID(connectionId), | ||
| new Date(), | ||
| ); | ||
|
|
||
| return Response.sendJsonObjectResponse(req, res, { queued: true }); | ||
| } catch (error) { | ||
| next(error); | ||
| } | ||
| }, |
|
|
||
| router.post( | ||
| TELEMETRY_AI_READINESS_PATH, | ||
| UserMiddleware.getUserMiddleware, |
|
|
||
| router.post( | ||
| TELEMETRY_AI_LOGS_PATH, | ||
| UserMiddleware.getUserMiddleware, |
|
|
||
| router.post( | ||
| TELEMETRY_AI_FIX_SUGGESTION_PATH, | ||
| UserMiddleware.getUserMiddleware, |
|
|
||
| router.post( | ||
| TELEMETRY_AI_FIX_PATH, | ||
| UserMiddleware.getUserMiddleware, |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Do not merge this PR. It is the CI gate for release 14.0.89. Its checks run on exactly the tree the release merge will build: this PR's merge ref is release plus the 14.0.89 bump. They run in a concurrency group that master pushes can't cancel. The release merge is pushed straight to
releaseonce these checks are green (14.0.88 published at 11:46Z on 10-24). GitHub then marks this PR merged.chore: bump version to 14.0.89(af2459b). It changes only VERSION and the package.json / package-lock.json files the hook keeps in step, the same 55 files as every bump. Cut 1.release(0fbf4ee, the 14.0.88 re-spin) to exactly the bump's tree (829e9733a4). Release's only commit not on master's line, the re-spin's cherry-pick of 34b86d8, is on master too.release. All 10 are also open on master, and none is dismissed.🤖 Generated with Claude Code