chore: import upstream snapshot with attribution
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:20:55 +08:00
commit d25d482dc2
13754 changed files with 4996608 additions and 0 deletions
@@ -0,0 +1,171 @@
import { z } from 'zod'
import type {
ContractBody,
ContractBodyInput,
ContractJsonResponse,
} from '@/lib/api/contracts/types'
import { defineRouteContract } from '@/lib/api/contracts/types'
import type { CrowdStrikeAggregateQuery } from '@/tools/crowdstrike/types'
const crowdstrikeNullableStringSchema = z.string().nullable()
const crowdstrikeNullableNumberSchema = z.number().nullable()
const crowdstrikePaginationSchema = z
.object({
limit: crowdstrikeNullableNumberSchema,
offset: crowdstrikeNullableNumberSchema,
total: crowdstrikeNullableNumberSchema,
})
.nullable()
const crowdstrikeSensorSchema = z.object({
agentVersion: crowdstrikeNullableStringSchema,
cid: crowdstrikeNullableStringSchema,
deviceId: crowdstrikeNullableStringSchema,
heartbeatTime: crowdstrikeNullableNumberSchema,
hostname: crowdstrikeNullableStringSchema,
idpPolicyId: crowdstrikeNullableStringSchema,
idpPolicyName: crowdstrikeNullableStringSchema,
ipAddress: crowdstrikeNullableStringSchema,
kerberosConfig: crowdstrikeNullableStringSchema,
ldapConfig: crowdstrikeNullableStringSchema,
ldapsConfig: crowdstrikeNullableStringSchema,
machineDomain: crowdstrikeNullableStringSchema,
ntlmConfig: crowdstrikeNullableStringSchema,
osVersion: crowdstrikeNullableStringSchema,
rdpToDcConfig: crowdstrikeNullableStringSchema,
smbToDcConfig: crowdstrikeNullableStringSchema,
status: crowdstrikeNullableStringSchema,
statusCauses: z.array(z.string()),
tiEnabled: crowdstrikeNullableStringSchema,
})
const crowdstrikeAggregateBucketSchema = z.object({
count: crowdstrikeNullableNumberSchema,
from: crowdstrikeNullableNumberSchema,
keyAsString: crowdstrikeNullableStringSchema,
label: z.unknown().nullable(),
stringFrom: crowdstrikeNullableStringSchema,
stringTo: crowdstrikeNullableStringSchema,
subAggregates: z.array(z.unknown()),
to: crowdstrikeNullableNumberSchema,
value: crowdstrikeNullableNumberSchema,
valueAsString: crowdstrikeNullableStringSchema,
})
const crowdstrikeAggregateResultSchema = z.object({
buckets: z.array(crowdstrikeAggregateBucketSchema),
docCountErrorUpperBound: crowdstrikeNullableNumberSchema,
name: crowdstrikeNullableStringSchema,
sumOtherDocCount: crowdstrikeNullableNumberSchema,
})
const crowdstrikeSensorsResponseSchema = z.object({
success: z.literal(true),
output: z.object({
count: z.number(),
pagination: crowdstrikePaginationSchema,
sensors: z.array(crowdstrikeSensorSchema),
}),
})
const crowdstrikeAggregatesResponseSchema = z.object({
success: z.literal(true),
output: z.object({
aggregates: z.array(crowdstrikeAggregateResultSchema),
count: z.number(),
}),
})
const CROWDSTRIKE_CLOUDS = ['us-1', 'us-2', 'eu-1', 'us-gov-1', 'us-gov-2'] as const
const baseRequestSchema = z.object({
clientId: z.string().min(1, 'Client ID is required'),
clientSecret: z.string().min(1, 'Client Secret is required'),
cloud: z.enum(CROWDSTRIKE_CLOUDS),
})
const dateRangeSchema = z.object({
from: z.string(),
to: z.string(),
})
const extendedBoundsSchema = z.object({
max: z.string(),
min: z.string(),
})
const rangeSpecSchema = z.object({
from: z.number(),
to: z.number(),
})
const aggregateQuerySchema: z.ZodType<CrowdStrikeAggregateQuery> = z.lazy(() =>
z.object({
date_ranges: z.array(dateRangeSchema).optional(),
exclude: z.string().optional(),
extended_bounds: extendedBoundsSchema.optional(),
field: z.string().optional(),
filter: z.string().optional(),
from: z.number().int().nonnegative().optional(),
include: z.string().optional(),
interval: z.string().optional(),
max_doc_count: z.number().int().nonnegative().optional(),
min_doc_count: z.number().int().nonnegative().optional(),
missing: z.string().optional(),
name: z.string().optional(),
q: z.string().optional(),
ranges: z.array(rangeSpecSchema).optional(),
size: z.number().int().nonnegative().optional(),
sort: z.string().optional(),
sub_aggregates: z.array(aggregateQuerySchema).optional(),
time_zone: z.string().optional(),
type: z.string().optional(),
})
)
const querySensorsSchema = baseRequestSchema.extend({
operation: z.literal('crowdstrike_query_sensors'),
filter: z.string().optional(),
limit: z
.number()
.int()
.min(1, 'Limit must be at least 1')
.max(200, 'Limit must be at most 200')
.optional(),
offset: z.number().int().nonnegative('Offset must be 0 or greater').optional(),
sort: z.string().optional(),
})
const getSensorDetailsSchema = baseRequestSchema.extend({
operation: z.literal('crowdstrike_get_sensor_details'),
ids: z
.array(z.string().trim().min(1, 'Sensor IDs must not be empty'))
.min(1, 'At least one sensor ID is required')
.max(5000, 'CrowdStrike supports up to 5000 sensor IDs per request'),
})
const getSensorAggregatesSchema = baseRequestSchema.extend({
operation: z.literal('crowdstrike_get_sensor_aggregates'),
aggregateQuery: aggregateQuerySchema,
})
export const crowdstrikeQueryBodySchema = z.discriminatedUnion('operation', [
querySensorsSchema,
getSensorDetailsSchema,
getSensorAggregatesSchema,
])
export const crowdstrikeQueryContract = defineRouteContract({
method: 'POST',
path: '/api/tools/crowdstrike/query',
body: crowdstrikeQueryBodySchema,
response: {
mode: 'json',
schema: z.union([crowdstrikeSensorsResponseSchema, crowdstrikeAggregatesResponseSchema]),
},
})
export type CrowdstrikeQueryBody = ContractBody<typeof crowdstrikeQueryContract>
export type CrowdstrikeQueryBodyInput = ContractBodyInput<typeof crowdstrikeQueryContract>
export type CrowdstrikeQueryResponse = ContractJsonResponse<typeof crowdstrikeQueryContract>