Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
f924d9e
feat(integrations): connect an AWS account as a source
Makisuo Oct 21, 2026
5f1449e
chore(aws): regenerate the iOS OpenAPI spec and anticipated error ide…
Makisuo Oct 21, 2026
abbbacf
fix(aws): the unavailable card drops the steps it cannot offer
Makisuo Oct 21, 2026
d0e7750
fix(aws): a background check only closes its own setup; pending setup…
Makisuo Oct 21, 2026
5bba37d
fix(aws): the hourly sweep runs batches until nothing is due, never-c…
Makisuo Oct 21, 2026
fbc7156
fix(aws): a sweep checks its batch in due order, never-checked first
Makisuo Oct 21, 2026
46672c9
fix(aws): no check starts past the sweep budget
Makisuo Oct 21, 2026
a871fb5
Merge remote-tracking branch 'origin/main' into feat/aws-connection
Makisuo Oct 22, 2026
e8ff331
fix(aws): a disconnect closes only its own dialog; document and test …
Makisuo Oct 22, 2026
14126ea
test(web): the in-flight click case starts a poll before it clicks
Makisuo Oct 22, 2026
434200b
test(aws): the budget sweep allows a check that timed out unassumed
Makisuo Oct 22, 2026
d64740d
Merge main into feat/aws-connection
Makisuo Oct 22, 2026
0ad1774
Merge remote-tracking branch 'origin/main' into feat/aws-connection
Makisuo Oct 22, 2026
195fc41
fix(web): an AWS stack that needs updating reads as needing attention
Makisuo Oct 22, 2026
d0b04d2
Merge remote-tracking branch 'origin/main' into feat/aws-connection
Makisuo Oct 22, 2026
406f9ec
test(aws): another org's admin cannot see or touch a connection; memb…
Makisuo Oct 22, 2026
4ee8570
test(github): pass the initiator in the install admin cases
Makisuo Oct 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,13 @@ INGEST_REQUIRE_TLS=false
# the IAM Service Account Credentials API enabled.
# MAPLE_GCP_SERVICE_ACCOUNT_KEY=

# AWS integration (an administrator deploys a generated CloudFormation stack from CloudShell).
# Maple's own IAM user, whose only permission is sts:AssumeRole on arn:aws:iam::*:role/MapleIntegration-*.
# Customer roles trust it with their connection's external id. All three unset: AWS is unavailable.
# MAPLE_AWS_PRINCIPAL_ARN=arn:aws:iam::<maple-account>:user/maple-integrations
# MAPLE_AWS_ACCESS_KEY_ID=
# MAPLE_AWS_SECRET_ACCESS_KEY=

# OpenTelemetry (API self-observability) — read by @maple-dev/effect-sdk
# MAPLE_ENVIRONMENT=local # "local" = no export; any other value enables OTLP
# MAPLE_ENDPOINT=http://127.0.0.1:3474 # Ingest gateway endpoint (enriches with org_id)
Expand Down
5 changes: 4 additions & 1 deletion apps/alerting/src/schedule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ export const ALERTING_SCHEDULE = {
},
// `supabase_insights` reads top queries every tick and advisors hourly (it tracks the hour itself).
"*/15 * * * *": { lanes: ["digest", "supabase_insights"], deadline: "10 minutes" },
"0 * * * *": { lanes: ["service_map_rollup", "supabase_discovery"], deadline: "15 minutes" },
"0 * * * *": {
lanes: ["service_map_rollup", "supabase_discovery", "aws_connections"],
deadline: "15 minutes",
},
} as const satisfies Record<string, CronSchedule>

export type AlertingCron = keyof typeof ALERTING_SCHEDULE
Expand Down
3 changes: 2 additions & 1 deletion apps/alerting/src/scheduled.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const cronCases = [
],
],
["*/15 * * * *", ["digest", "supabaseInsights"]],
["0 * * * *", ["serviceMapRollup", "supabaseDiscovery"]],
["0 * * * *", ["serviceMapRollup", "supabaseDiscovery", "awsConnections"]],
["* * * * *", ["alert", "error", "escalation", "fixVerification", "supabaseLogs"]],
] as const

Expand All @@ -31,6 +31,7 @@ const recordingTicks = (
return {
alert: tick("alert"),
anomaly: tick("anomaly"),
awsConnections: tick("awsConnections"),
cloudflareAnalytics: tick("cloudflareAnalytics"),
digest: tick("digest"),
error: tick("error"),
Expand Down
19 changes: 19 additions & 0 deletions apps/alerting/src/scheduled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { PullRequestLookupLive } from "@maple/backend/services/errors/pull-reque
import { PlanetScaleService } from "@maple/backend/services/integrations/PlanetScaleService"
import { PrReviewPostMergeService } from "@maple/backend/services/pr-review/PrReviewPostMergeService"
import { RailwayMetricsService } from "@maple/backend/services/integrations/RailwayMetricsService"
import { AwsConnectionService } from "@maple/backend/services/integrations/AwsConnectionService"
import { SupabaseConnectionService } from "@maple/backend/services/integrations/SupabaseConnectionService"
import { SupabaseInsightsService } from "@maple/backend/services/integrations/SupabaseInsightsService"
import { SupabaseLogsService } from "@maple/backend/services/integrations/SupabaseLogsService"
Expand Down Expand Up @@ -56,6 +57,7 @@ export const layerTick = (
GcpMetricsService.layer,
PlanetScaleService.layer,
RailwayMetricsService.layer,
AwsConnectionService.layer,
SupabaseConnectionService.layer,
SupabaseLogsService.layer,
SupabaseInsightsService.layer,
Expand Down Expand Up @@ -291,6 +293,19 @@ const planetScaleTick = makeTick(
: undefined,
)

const awsConnectionsTick = makeTick(
AwsConnectionService.use((aws) => aws.checkDue()),
"aws_connections",
(result) =>
result.due > 0
? {
due: result.due,
checked: result.checked,
failures: result.failures,
}
: undefined,
)

const railwayMetricsTick = makeTick(
RailwayMetricsService.use((railway) => railway.pollAllOrgs()),
"railway_metrics",
Expand Down Expand Up @@ -366,6 +381,7 @@ const prReviewPostMergeTick = makeTick(
export interface ScheduledTickPrograms<R = never> {
readonly alert: Effect.Effect<void, never, R>
readonly anomaly: Effect.Effect<void, never, R>
readonly awsConnections: Effect.Effect<void, never, R>
readonly cloudflareAnalytics: Effect.Effect<void, never, R>
readonly digest: Effect.Effect<void, never, R>
readonly error: Effect.Effect<void, never, R>
Expand Down Expand Up @@ -398,6 +414,7 @@ const laneProgram = <R>(lane: TickLane, ticks: ScheduledTickPrograms<R>): Effect
Match.when("pr_review_post_merge", () => ticks.prReviewPostMerge),
Match.when("digest", () => ticks.digest),
Match.when("service_map_rollup", () => ticks.serviceMapRollup),
Match.when("aws_connections", () => ticks.awsConnections),
Match.when("supabase_discovery", () => ticks.supabaseDiscovery),
Match.when("supabase_logs", () => ticks.supabaseLogs),
Match.when("supabase_insights", () => ticks.supabaseInsights),
Expand Down Expand Up @@ -439,6 +456,7 @@ export const selectLaneProgram = <R>(
type ScheduledServices =
| AlertsService
| AnomalyDetectionService
| AwsConnectionService
| CloudflareAnalyticsService
| DigestService
| WebAnalyticsDigestService
Expand All @@ -457,6 +475,7 @@ type ScheduledServices =
export const scheduledTicks: ScheduledTickPrograms<ScheduledServices> = {
alert: alertTick,
anomaly: anomalyTick,
awsConnections: awsConnectionsTick,
cloudflareAnalytics: cloudflareAnalyticsTick,
digest: digestTick,
error: errorTick,
Expand Down
4 changes: 4 additions & 0 deletions apps/alerting/src/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ const configuredEnv = (stage: MapleStage, region: MapleRegion, domains: MapleDom
supabaseOAuthEnv,
// Sign-in for the Google Cloud metrics poller; unset leaves its tick a no-op.
optionalSecret("MAPLE_GCP_SERVICE_ACCOUNT_KEY"),
// Maple's AWS identity for the hourly connection check; unset leaves its tick a no-op.
optionalPlain("MAPLE_AWS_PRINCIPAL_ARN"),
optionalPlain("MAPLE_AWS_ACCESS_KEY_ID"),
optionalSecret("MAPLE_AWS_SECRET_ACCESS_KEY"),
// Ticks post pull-request replies through the GitHub App; without it each one fails.
githubAppSourceEnv,
// Outbound config for `chat` destinations' connectors.
Expand Down
4 changes: 4 additions & 0 deletions apps/api/src/resources/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,8 @@ export const apiConfiguredEnv = (stage: MapleStage, region: MapleRegion, domains
planetScaleOAuthEnv,
supabaseOAuthEnv,
optionalPlain("MAPLE_GCP_SERVICE_ACCOUNT_EMAIL"),
// Maple's AWS identity: assumes customer roles. Unset leaves AWS unavailable.
optionalPlain("MAPLE_AWS_PRINCIPAL_ARN"),
optionalPlain("MAPLE_AWS_ACCESS_KEY_ID"),
optionalSecret("MAPLE_AWS_SECRET_ACCESS_KEY"),
)
Loading
Loading