Compare commits

...

7 Commits

Author SHA1 Message Date
32521523c1 misc: add flag for disabling workers 2025-03-21 03:46:17 +08:00
3a2e8939b1 Merge pull request #3282 from Infisical/misc/add-event-loop-stats
misc: add event loop stats
2025-03-21 01:54:12 +08:00
a6d9c74054 Merge pull request #3272 from akhilmhdh/feat/metadata-audit-log
Permission metadata data in audit log
2025-03-20 13:47:52 -04:00
=
c4b7d4618d feat: updated ui 2025-03-19 20:33:31 +05:30
=
747b5ec68d feat: updated doc 2025-03-19 15:00:36 +05:30
=
ed0dc324a3 feat: updated audit log ui 2025-03-19 13:28:26 +05:30
=
1c13ed54af feat: updated audit log to permission metadataw 2025-03-19 13:28:26 +05:30
16 changed files with 395 additions and 380 deletions

View File

@ -106,6 +106,7 @@ declare module "@fastify/request-context" {
claims: Record<string, string>; claims: Record<string, string>;
}; };
}; };
identityPermissionMetadata?: Record<string, unknown>; // filled by permission service
} }
} }

View File

@ -1,8 +1,10 @@
import { ForbiddenError } from "@casl/ability"; import { ForbiddenError } from "@casl/ability";
import { requestContext } from "@fastify/request-context";
import { ActionProjectType } from "@app/db/schemas"; import { ActionProjectType } from "@app/db/schemas";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { BadRequestError } from "@app/lib/errors"; import { BadRequestError } from "@app/lib/errors";
import { ActorType } from "@app/services/auth/auth-type";
import { OrgPermissionActions, OrgPermissionSubjects } from "../permission/org-permission"; import { OrgPermissionActions, OrgPermissionSubjects } from "../permission/org-permission";
import { TPermissionServiceFactory } from "../permission/permission-service"; import { TPermissionServiceFactory } from "../permission/permission-service";
@ -81,8 +83,12 @@ export const auditLogServiceFactory = ({
if (!data.projectId && !data.orgId) if (!data.projectId && !data.orgId)
throw new BadRequestError({ message: "Must specify either project id or org id" }); throw new BadRequestError({ message: "Must specify either project id or org id" });
} }
const el = { ...data };
return auditLogQueue.pushToLog(data); if (el.actor.type === ActorType.USER || el.actor.type === ActorType.IDENTITY) {
const permissionMetadata = requestContext.get("identityPermissionMetadata");
el.actor.metadata.permission = permissionMetadata;
}
return auditLogQueue.pushToLog(el);
}; };
return { return {

View File

@ -290,6 +290,7 @@ interface UserActorMetadata {
userId: string; userId: string;
email?: string | null; email?: string | null;
username: string; username: string;
permission?: Record<string, unknown>;
} }
interface ServiceActorMetadata { interface ServiceActorMetadata {
@ -300,6 +301,7 @@ interface ServiceActorMetadata {
interface IdentityActorMetadata { interface IdentityActorMetadata {
identityId: string; identityId: string;
name: string; name: string;
permission?: Record<string, unknown>;
} }
interface ScimClientActorMetadata {} interface ScimClientActorMetadata {}

View File

@ -244,22 +244,20 @@ export const permissionServiceFactory = ({
const rules = buildProjectPermissionRules(rolePermissions.concat(additionalPrivileges)); const rules = buildProjectPermissionRules(rolePermissions.concat(additionalPrivileges));
const templatedRules = handlebars.compile(JSON.stringify(rules), { data: false }); const templatedRules = handlebars.compile(JSON.stringify(rules), { data: false });
const metadataKeyValuePair = escapeHandlebarsMissingDict( const unescapedMetadata = objectify(
objectify(
userProjectPermission.metadata, userProjectPermission.metadata,
(i) => i.key, (i) => i.key,
(i) => i.value (i) => i.value
),
"identity.metadata"
); );
const templateValue = { const metadataKeyValuePair = escapeHandlebarsMissingDict(unescapedMetadata, "identity.metadata");
requestContext.set("identityPermissionMetadata", { metadata: unescapedMetadata });
const interpolateRules = templatedRules(
{
identity: {
id: userProjectPermission.userId, id: userProjectPermission.userId,
username: userProjectPermission.username, username: userProjectPermission.username,
metadata: metadataKeyValuePair metadata: metadataKeyValuePair
}; }
const interpolateRules = templatedRules(
{
identity: templateValue
}, },
{ data: false } { data: false }
); );
@ -331,15 +329,16 @@ export const permissionServiceFactory = ({
? escapeHandlebarsMissingDict(unescapedIdentityAuthInfo as never, "identity.auth") ? escapeHandlebarsMissingDict(unescapedIdentityAuthInfo as never, "identity.auth")
: {}; : {};
const metadataKeyValuePair = escapeHandlebarsMissingDict(unescapedMetadata, "identity.metadata"); const metadataKeyValuePair = escapeHandlebarsMissingDict(unescapedMetadata, "identity.metadata");
const templateValue = {
requestContext.set("identityPermissionMetadata", { metadata: unescapedMetadata, auth: unescapedIdentityAuthInfo });
const interpolateRules = templatedRules(
{
identity: {
id: identityProjectPermission.identityId, id: identityProjectPermission.identityId,
username: identityProjectPermission.username, username: identityProjectPermission.username,
metadata: metadataKeyValuePair, metadata: metadataKeyValuePair,
auth: identityAuthInfo auth: identityAuthInfo
}; }
const interpolateRules = templatedRules(
{
identity: templateValue
}, },
{ data: false } { data: false }
); );
@ -440,14 +439,13 @@ export const permissionServiceFactory = ({
), ),
"identity.metadata" "identity.metadata"
); );
const templateValue = { const interpolateRules = templatedRules(
{
identity: {
id: userProjectPermission.userId, id: userProjectPermission.userId,
username: userProjectPermission.username, username: userProjectPermission.username,
metadata: metadataKeyValuePair metadata: metadataKeyValuePair
}; }
const interpolateRules = templatedRules(
{
identity: templateValue
}, },
{ data: false } { data: false }
); );
@ -487,14 +485,13 @@ export const permissionServiceFactory = ({
), ),
"identity.metadata" "identity.metadata"
); );
const templateValue = { const interpolateRules = templatedRules(
{
identity: {
id: identityProjectPermission.identityId, id: identityProjectPermission.identityId,
username: identityProjectPermission.username, username: identityProjectPermission.username,
metadata: metadataKeyValuePair metadata: metadataKeyValuePair
}; }
const interpolateRules = templatedRules(
{
identity: templateValue
}, },
{ data: false } { data: false }
); );

View File

@ -56,6 +56,7 @@ const envSchema = z
// TODO(akhilmhdh): will be changed to one // TODO(akhilmhdh): will be changed to one
ENCRYPTION_KEY: zpStr(z.string().optional()), ENCRYPTION_KEY: zpStr(z.string().optional()),
ROOT_ENCRYPTION_KEY: zpStr(z.string().optional()), ROOT_ENCRYPTION_KEY: zpStr(z.string().optional()),
QUEUE_WORKERS_ENABLED: zodStrBool.default("true"),
HTTPS_ENABLED: zodStrBool, HTTPS_ENABLED: zodStrBool,
// smtp options // smtp options
SMTP_HOST: zpStr(z.string().optional()), SMTP_HOST: zpStr(z.string().optional()),

View File

@ -272,10 +272,13 @@ export const queueServiceFactory = (
connection connection
}); });
const appCfg = getConfig();
if (appCfg.QUEUE_WORKERS_ENABLED) {
workerContainer[name] = new Worker<TQueueJobTypes[T]["payload"], void, TQueueJobTypes[T]["name"]>(name, jobFn, { workerContainer[name] = new Worker<TQueueJobTypes[T]["payload"], void, TQueueJobTypes[T]["name"]>(name, jobFn, {
...queueSettings, ...queueSettings,
connection connection
}); });
}
}; };
const startPg = async <T extends QueueName>( const startPg = async <T extends QueueName>(
@ -307,6 +310,11 @@ export const queueServiceFactory = (
event: U, event: U,
listener: WorkerListener<TQueueJobTypes[T]["payload"], void, TQueueJobTypes[T]["name"]>[U] listener: WorkerListener<TQueueJobTypes[T]["payload"], void, TQueueJobTypes[T]["name"]>[U]
) => { ) => {
const appCfg = getConfig();
if (!appCfg.QUEUE_WORKERS_ENABLED) {
return;
}
const worker = workerContainer[name]; const worker = workerContainer[name];
worker.on(event, listener); worker.on(event, listener);
}; };

View File

@ -9,20 +9,76 @@ description: "Track evert event action performed within Infisical projects."
If you're using Infisical Cloud, then it is available under the **Pro**, If you're using Infisical Cloud, then it is available under the **Pro**,
and **Enterprise Tier** with varying retention periods. If you're self-hosting Infisical, and **Enterprise Tier** with varying retention periods. If you're self-hosting Infisical,
then you should contact sales@infisical.com to purchase an enterprise license to use it. then you should contact sales@infisical.com to purchase an enterprise license to use it.
</Info> </Info>
Infisical provides audit logs for security and compliance teams to monitor information access. Infisical provides audit logs for security and compliance teams to monitor information access.
With the Audit Log functionality, teams can: With the Audit Log functionality, teams can:
- **Track** 40+ different events; - **Track** 40+ different events;
- **Filter** audit logs by event, actor, source, date or any combination of these filters; - **Filter** audit logs by event, actor, source, date or any combination of these filters;
- **Inspect** extensive metadata in the event of any suspicious activity or incident review. - **Inspect** extensive metadata in the event of any suspicious activity or incident review.
![Audit logs](../../images/platform/audit-logs/audit-logs-table.png) ![Audit logs](../../images/platform/audit-logs/audit-logs-table.png)
## Audit Log Structure
Each log contains the following data: Each log contains the following data:
- **Event**: The underlying action such as create, list, read, update, or delete secret(s). | Field | Type | Description | Purpose |
- **Actor**: The entity responsible for performing or causing the event; this can be a user or service. | ------------------------- | -------- | --------------------------------------------------------- | ------------------------------------------------------------- |
- **Timestamp**: The date and time at which point the event occurred. | **event** | Object | Contains details about the action performed | Captures what happened |
- **Source** (User agent + IP): The software (user agent) and network address (IP) from which the event was initiated. | event.type | String | The specific action that occurred (e.g., "create-secret") | Identifies the exact operation |
- **Metadata**: Additional data to provide context for each event. For example, this could be the path at which a secret was fetched from etc. | event.metadata | Object | Context-specific details about the event | Provides detailed information relevant to the specific action |
| **actor** | Object | Information about who performed the action | Identifies the responsible entity |
| actor.type | String | Category of actor (user, service, identity, etc.) | Distinguishes between human and non-human actors |
| actor.metadata | Object | Details about the specific actor | Provides identity information |
| actor.metadata.userId | String | Unique identifier for user actors | Links to specific user account |
| actor.metadata.email | String | Email address for user actors | Email of the executing user |
| actor.metadata.username | String | Username for user actors | Username of the executing user |
| actor.metadata.serviceId | String | Identifier for service actors | ID of specific service token |
| actor.metadata.identityId | String | Identifier for identity actors | ID to specific identity |
| actor.metadata.permission | Object | Permission context for the action | Shows permission template data when action was performed |
| **orgId** | String | Organization identifier | Indicates which organization the action occurred in |
| **projectId** | String | Project identifier | Indicates which project the action affected |
| **ipAddress** | String | Source IP address | Shows where the request originated from |
| **userAgent** | String | Client application information | Identifies browser or application used |
| **userAgentType** | String | Category of client (web, CLI, SDK, etc.) | Classifies the access method |
| **timestamp** | DateTime | When the action occurred | Records the exact time of the event |
<Accordion title="Example Payload">
```json
{
"id": "[UUID]",
"ipAddress": "[IP_ADDRESS]",
"userAgent": "[USER_AGENT_STRING]",
"userAgentType": "web",
"expiresAt": "[TIMESTAMP]",
"createdAt": "[TIMESTAMP]",
"updatedAt": "[TIMESTAMP]",
"orgId": "[ORGANIZATION_UUID]",
"projectId": "[PROJECT_UUID]",
"projectName": "[PROJECT_NAME]",
"event": {
"type": "get-secrets",
"metadata": {
"secretPath": "[PATH]",
"environment": "[ENVIRONMENT_NAME]",
"numberOfSecrets": [NUMBER]
}
},
"actor": {
"type": "user",
"metadata": {
"email": "[EMAIL]",
"userId": "[USER_UUID]",
"username": "[USERNAME]",
"permission": {
"metadata": {},
"auth": {}
}
}
}
}
```
</Accordion>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 430 KiB

View File

@ -362,26 +362,26 @@
} }
}, },
"node_modules/@babel/helpers": { "node_modules/@babel/helpers": {
"version": "7.26.0", "version": "7.26.10",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz",
"integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/template": "^7.25.9", "@babel/template": "^7.26.9",
"@babel/types": "^7.26.0" "@babel/types": "^7.26.10"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/parser": { "node_modules/@babel/parser": {
"version": "7.26.3", "version": "7.26.10",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz",
"integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/types": "^7.26.3" "@babel/types": "^7.26.10"
}, },
"bin": { "bin": {
"parser": "bin/babel-parser.js" "parser": "bin/babel-parser.js"
@ -423,9 +423,9 @@
} }
}, },
"node_modules/@babel/runtime": { "node_modules/@babel/runtime": {
"version": "7.26.0", "version": "7.26.10",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.10.tgz",
"integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", "integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"regenerator-runtime": "^0.14.0" "regenerator-runtime": "^0.14.0"
@ -435,14 +435,14 @@
} }
}, },
"node_modules/@babel/template": { "node_modules/@babel/template": {
"version": "7.25.9", "version": "7.26.9",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz",
"integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.25.9", "@babel/code-frame": "^7.26.2",
"@babel/parser": "^7.25.9", "@babel/parser": "^7.26.9",
"@babel/types": "^7.25.9" "@babel/types": "^7.26.9"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@ -476,9 +476,9 @@
} }
}, },
"node_modules/@babel/types": { "node_modules/@babel/types": {
"version": "7.26.3", "version": "7.26.10",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz",
"integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-string-parser": "^7.25.9", "@babel/helper-string-parser": "^7.25.9",
@ -1010,6 +1010,23 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/@esbuild/netbsd-arm64": {
"version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz",
"integrity": "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-x64": { "node_modules/@esbuild/netbsd-x64": {
"version": "0.21.5", "version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
@ -1028,9 +1045,9 @@
} }
}, },
"node_modules/@esbuild/openbsd-arm64": { "node_modules/@esbuild/openbsd-arm64": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz",
"integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", "integrity": "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -1647,12 +1664,12 @@
} }
}, },
"node_modules/@octokit/endpoint": { "node_modules/@octokit/endpoint": {
"version": "10.1.1", "version": "10.1.3",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.1.tgz", "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.3.tgz",
"integrity": "sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q==", "integrity": "sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@octokit/types": "^13.0.0", "@octokit/types": "^13.6.2",
"universal-user-agent": "^7.0.2" "universal-user-agent": "^7.0.2"
}, },
"engines": { "engines": {
@ -1674,18 +1691,18 @@
} }
}, },
"node_modules/@octokit/openapi-types": { "node_modules/@octokit/openapi-types": {
"version": "22.2.0", "version": "24.2.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
"integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==", "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@octokit/plugin-paginate-rest": { "node_modules/@octokit/plugin-paginate-rest": {
"version": "11.3.6", "version": "11.6.0",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.6.tgz", "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.6.0.tgz",
"integrity": "sha512-zcvqqf/+TicbTCa/Z+3w4eBJcAxCFymtc0UAIsR3dEVoNilWld4oXdscQ3laXamTszUZdusw97K8+DrbFiOwjw==", "integrity": "sha512-n5KPteiF7pWKgBIBJSk8qzoZWcUkza2O6A0za97pMGVrGfPdltxrfmfF5GucHYvHGZD8BdaZmmHGz5cX/3gdpw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@octokit/types": "^13.6.2" "@octokit/types": "^13.10.0"
}, },
"engines": { "engines": {
"node": ">= 18" "node": ">= 18"
@ -1722,14 +1739,15 @@
} }
}, },
"node_modules/@octokit/request": { "node_modules/@octokit/request": {
"version": "9.1.3", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.1.3.tgz", "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.2.tgz",
"integrity": "sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA==", "integrity": "sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@octokit/endpoint": "^10.0.0", "@octokit/endpoint": "^10.1.3",
"@octokit/request-error": "^6.0.1", "@octokit/request-error": "^6.1.7",
"@octokit/types": "^13.1.0", "@octokit/types": "^13.6.2",
"fast-content-type-parse": "^2.0.0",
"universal-user-agent": "^7.0.2" "universal-user-agent": "^7.0.2"
}, },
"engines": { "engines": {
@ -1737,12 +1755,12 @@
} }
}, },
"node_modules/@octokit/request-error": { "node_modules/@octokit/request-error": {
"version": "6.1.5", "version": "6.1.7",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.5.tgz", "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.7.tgz",
"integrity": "sha512-IlBTfGX8Yn/oFPMwSfvugfncK2EwRLjzbrpifNaMY8o/HTEAFqCA1FZxjD9cWvSKBHgrIhc4CSBIzMxiLsbzFQ==", "integrity": "sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@octokit/types": "^13.0.0" "@octokit/types": "^13.6.2"
}, },
"engines": { "engines": {
"node": ">= 18" "node": ">= 18"
@ -1764,12 +1782,12 @@
} }
}, },
"node_modules/@octokit/types": { "node_modules/@octokit/types": {
"version": "13.6.2", "version": "13.10.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.6.2.tgz", "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
"integrity": "sha512-WpbZfZUcZU77DrSW4wbsSgTPfKcp286q3ItaIgvSbBpZJlu6mnYXAkjZz6LVZPXkEvLIM8McanyZejKTYUHipA==", "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@octokit/openapi-types": "^22.2.0" "@octokit/openapi-types": "^24.2.0"
} }
}, },
"node_modules/@peculiar/asn1-cms": { "node_modules/@peculiar/asn1-cms": {
@ -4956,9 +4974,9 @@
} }
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.7.9", "version": "1.8.3",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz",
"integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", "integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"follow-redirects": "^1.15.6", "follow-redirects": "^1.15.6",
@ -5451,9 +5469,9 @@
"license": "CC-BY-4.0" "license": "CC-BY-4.0"
}, },
"node_modules/canvg": { "node_modules/canvg": {
"version": "3.0.10", "version": "3.0.11",
"resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz", "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.11.tgz",
"integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==", "integrity": "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
@ -7314,6 +7332,22 @@
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
}, },
"node_modules/fast-content-type-parse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz",
"integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"license": "MIT"
},
"node_modules/fast-deep-equal": { "node_modules/fast-deep-equal": {
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@ -12588,13 +12622,13 @@
"license": "0BSD" "license": "0BSD"
}, },
"node_modules/tsx": { "node_modules/tsx": {
"version": "4.19.2", "version": "4.19.3",
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz",
"integrity": "sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==", "integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"esbuild": "~0.23.0", "esbuild": "~0.25.0",
"get-tsconfig": "^4.7.5" "get-tsconfig": "^4.7.5"
}, },
"bin": { "bin": {
@ -12608,9 +12642,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/aix-ppc64": { "node_modules/tsx/node_modules/@esbuild/aix-ppc64": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz",
"integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", "integrity": "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
@ -12625,9 +12659,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/android-arm": { "node_modules/tsx/node_modules/@esbuild/android-arm": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.1.tgz",
"integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", "integrity": "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@ -12642,9 +12676,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/android-arm64": { "node_modules/tsx/node_modules/@esbuild/android-arm64": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz",
"integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", "integrity": "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -12659,9 +12693,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/android-x64": { "node_modules/tsx/node_modules/@esbuild/android-x64": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.1.tgz",
"integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", "integrity": "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -12676,9 +12710,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/darwin-arm64": { "node_modules/tsx/node_modules/@esbuild/darwin-arm64": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz",
"integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", "integrity": "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -12693,9 +12727,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/darwin-x64": { "node_modules/tsx/node_modules/@esbuild/darwin-x64": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz",
"integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", "integrity": "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -12710,9 +12744,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz",
"integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", "integrity": "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -12727,9 +12761,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/freebsd-x64": { "node_modules/tsx/node_modules/@esbuild/freebsd-x64": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz",
"integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", "integrity": "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -12744,9 +12778,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/linux-arm": { "node_modules/tsx/node_modules/@esbuild/linux-arm": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz",
"integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", "integrity": "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@ -12761,9 +12795,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/linux-arm64": { "node_modules/tsx/node_modules/@esbuild/linux-arm64": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz",
"integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", "integrity": "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -12778,9 +12812,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/linux-ia32": { "node_modules/tsx/node_modules/@esbuild/linux-ia32": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz",
"integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", "integrity": "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@ -12795,9 +12829,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/linux-loong64": { "node_modules/tsx/node_modules/@esbuild/linux-loong64": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz",
"integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", "integrity": "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==",
"cpu": [ "cpu": [
"loong64" "loong64"
], ],
@ -12812,9 +12846,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/linux-mips64el": { "node_modules/tsx/node_modules/@esbuild/linux-mips64el": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz",
"integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", "integrity": "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==",
"cpu": [ "cpu": [
"mips64el" "mips64el"
], ],
@ -12829,9 +12863,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/linux-ppc64": { "node_modules/tsx/node_modules/@esbuild/linux-ppc64": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz",
"integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", "integrity": "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
@ -12846,9 +12880,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/linux-riscv64": { "node_modules/tsx/node_modules/@esbuild/linux-riscv64": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz",
"integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", "integrity": "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
@ -12863,9 +12897,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/linux-s390x": { "node_modules/tsx/node_modules/@esbuild/linux-s390x": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz",
"integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", "integrity": "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==",
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
@ -12880,9 +12914,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/linux-x64": { "node_modules/tsx/node_modules/@esbuild/linux-x64": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz",
"integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", "integrity": "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -12897,9 +12931,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/netbsd-x64": { "node_modules/tsx/node_modules/@esbuild/netbsd-x64": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz",
"integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", "integrity": "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -12914,9 +12948,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/openbsd-x64": { "node_modules/tsx/node_modules/@esbuild/openbsd-x64": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz",
"integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", "integrity": "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -12931,9 +12965,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/sunos-x64": { "node_modules/tsx/node_modules/@esbuild/sunos-x64": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz",
"integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", "integrity": "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -12948,9 +12982,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/win32-arm64": { "node_modules/tsx/node_modules/@esbuild/win32-arm64": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz",
"integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", "integrity": "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@ -12965,9 +12999,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/win32-ia32": { "node_modules/tsx/node_modules/@esbuild/win32-ia32": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz",
"integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", "integrity": "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@ -12982,9 +13016,9 @@
} }
}, },
"node_modules/tsx/node_modules/@esbuild/win32-x64": { "node_modules/tsx/node_modules/@esbuild/win32-x64": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz",
"integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", "integrity": "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@ -12999,9 +13033,9 @@
} }
}, },
"node_modules/tsx/node_modules/esbuild": { "node_modules/tsx/node_modules/esbuild": {
"version": "0.23.1", "version": "0.25.1",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz",
"integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==",
"dev": true, "dev": true,
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT", "license": "MIT",
@ -13012,30 +13046,31 @@
"node": ">=18" "node": ">=18"
}, },
"optionalDependencies": { "optionalDependencies": {
"@esbuild/aix-ppc64": "0.23.1", "@esbuild/aix-ppc64": "0.25.1",
"@esbuild/android-arm": "0.23.1", "@esbuild/android-arm": "0.25.1",
"@esbuild/android-arm64": "0.23.1", "@esbuild/android-arm64": "0.25.1",
"@esbuild/android-x64": "0.23.1", "@esbuild/android-x64": "0.25.1",
"@esbuild/darwin-arm64": "0.23.1", "@esbuild/darwin-arm64": "0.25.1",
"@esbuild/darwin-x64": "0.23.1", "@esbuild/darwin-x64": "0.25.1",
"@esbuild/freebsd-arm64": "0.23.1", "@esbuild/freebsd-arm64": "0.25.1",
"@esbuild/freebsd-x64": "0.23.1", "@esbuild/freebsd-x64": "0.25.1",
"@esbuild/linux-arm": "0.23.1", "@esbuild/linux-arm": "0.25.1",
"@esbuild/linux-arm64": "0.23.1", "@esbuild/linux-arm64": "0.25.1",
"@esbuild/linux-ia32": "0.23.1", "@esbuild/linux-ia32": "0.25.1",
"@esbuild/linux-loong64": "0.23.1", "@esbuild/linux-loong64": "0.25.1",
"@esbuild/linux-mips64el": "0.23.1", "@esbuild/linux-mips64el": "0.25.1",
"@esbuild/linux-ppc64": "0.23.1", "@esbuild/linux-ppc64": "0.25.1",
"@esbuild/linux-riscv64": "0.23.1", "@esbuild/linux-riscv64": "0.25.1",
"@esbuild/linux-s390x": "0.23.1", "@esbuild/linux-s390x": "0.25.1",
"@esbuild/linux-x64": "0.23.1", "@esbuild/linux-x64": "0.25.1",
"@esbuild/netbsd-x64": "0.23.1", "@esbuild/netbsd-arm64": "0.25.1",
"@esbuild/openbsd-arm64": "0.23.1", "@esbuild/netbsd-x64": "0.25.1",
"@esbuild/openbsd-x64": "0.23.1", "@esbuild/openbsd-arm64": "0.25.1",
"@esbuild/sunos-x64": "0.23.1", "@esbuild/openbsd-x64": "0.25.1",
"@esbuild/win32-arm64": "0.23.1", "@esbuild/sunos-x64": "0.25.1",
"@esbuild/win32-ia32": "0.23.1", "@esbuild/win32-arm64": "0.25.1",
"@esbuild/win32-x64": "0.23.1" "@esbuild/win32-ia32": "0.25.1",
"@esbuild/win32-x64": "0.25.1"
} }
}, },
"node_modules/tsyringe": { "node_modules/tsyringe": {
@ -13552,9 +13587,9 @@
} }
}, },
"node_modules/vite": { "node_modules/vite": {
"version": "5.4.11", "version": "5.4.14",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.14.tgz",
"integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", "integrity": "sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {

View File

@ -18,7 +18,7 @@ export const AuditLogsPage = () => {
title="Audit logs" title="Audit logs"
description="Audit logs for security and compliance teams to monitor information access." description="Audit logs for security and compliance teams to monitor information access."
/> />
<LogsSection filterClassName="static py-2" showFilters isOrgAuditLogs showActorColumn /> <LogsSection filterClassName="static py-2" showFilters />
</div> </div>
</div> </div>
</div> </div>

View File

@ -10,7 +10,7 @@ import { ActorType, EventType, UserAgentType } from "@app/hooks/api/auditLogs/en
import { usePopUp } from "@app/hooks/usePopUp"; import { usePopUp } from "@app/hooks/usePopUp";
import { LogsFilter } from "./LogsFilter"; import { LogsFilter } from "./LogsFilter";
import { LogsTable, TAuditLogTableHeader } from "./LogsTable"; import { LogsTable } from "./LogsTable";
import { AuditLogFilterFormData, auditLogFilterFormSchema } from "./types"; import { AuditLogFilterFormData, auditLogFilterFormSchema } from "./types";
type Props = { type Props = {
@ -25,22 +25,11 @@ type Props = {
showFilters?: boolean; showFilters?: boolean;
filterClassName?: string; filterClassName?: string;
isOrgAuditLogs?: boolean;
showActorColumn?: boolean;
remappedHeaders?: Partial<Record<TAuditLogTableHeader, string>>;
refetchInterval?: number; refetchInterval?: number;
}; };
export const LogsSection = withPermission( export const LogsSection = withPermission(
({ ({ presets, filterClassName, refetchInterval, showFilters }: Props) => {
presets,
filterClassName,
remappedHeaders,
isOrgAuditLogs,
showActorColumn,
refetchInterval,
showFilters
}: Props) => {
const { subscription } = useSubscription(); const { subscription } = useSubscription();
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["upgradePlan"] as const); const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["upgradePlan"] as const);
@ -90,9 +79,6 @@ export const LogsSection = withPermission(
)} )}
<LogsTable <LogsTable
refetchInterval={refetchInterval} refetchInterval={refetchInterval}
remappedHeaders={remappedHeaders}
isOrgAuditLogs={isOrgAuditLogs}
showActorColumn={!!showActorColumn}
filter={{ filter={{
secretPath: debouncedSecretPath || undefined, secretPath: debouncedSecretPath || undefined,
eventMetadata: presets?.eventMetadata, eventMetadata: presets?.eventMetadata,

View File

@ -1,5 +1,6 @@
import { Fragment } from "react"; import { Fragment } from "react";
import { faFile } from "@fortawesome/free-solid-svg-icons"; import { faFile, faInfoCircle } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { import {
Button, Button,
@ -11,6 +12,7 @@ import {
Td, Td,
Th, Th,
THead, THead,
Tooltip,
Tr Tr
} from "@app/components/v2"; } from "@app/components/v2";
import { useGetAuditLogs } from "@app/hooks/api"; import { useGetAuditLogs } from "@app/hooks/api";
@ -19,32 +21,13 @@ import { TGetAuditLogsFilter } from "@app/hooks/api/auditLogs/types";
import { LogsTableRow } from "./LogsTableRow"; import { LogsTableRow } from "./LogsTableRow";
type Props = { type Props = {
isOrgAuditLogs?: boolean;
showActorColumn: boolean;
filter?: TGetAuditLogsFilter; filter?: TGetAuditLogsFilter;
remappedHeaders?: Partial<Record<TAuditLogTableHeader, string>>;
refetchInterval?: number; refetchInterval?: number;
}; };
const AUDIT_LOG_LIMIT = 15; const AUDIT_LOG_LIMIT = 15;
const TABLE_HEADERS = [ export const LogsTable = ({ filter, refetchInterval }: Props) => {
"Timestamp (MM/DD/YYYY)",
"Event",
"Project",
"Actor",
"Source",
"Metadata"
] as const;
export type TAuditLogTableHeader = (typeof TABLE_HEADERS)[number];
export const LogsTable = ({
showActorColumn,
isOrgAuditLogs,
filter,
remappedHeaders,
refetchInterval
}: Props) => {
// Determine the project ID for filtering // Determine the project ID for filtering
const filterProjectId = const filterProjectId =
// Use the projectId from the filter if it exists // Use the projectId from the filter if it exists
@ -69,38 +52,37 @@ export const LogsTable = ({
<Table> <Table>
<THead> <THead>
<Tr> <Tr>
{TABLE_HEADERS.map((header, idx) => { <Th className="w-24" />
if ( <Th className="w-64">
(header === "Project" && !isOrgAuditLogs) || Timestamp
(header === "Actor" && !showActorColumn) <Tooltip
) { className="normal-case"
return null; content="Time displayed in your system's time zone."
} sideOffset={10}
>
return ( <FontAwesomeIcon icon={faInfoCircle} className="ml-1" />
<Th key={`table-header-${idx + 1}`}>{remappedHeaders?.[header] || header}</Th> </Tooltip>
); </Th>
})} <Th>Event</Th>
</Tr> </Tr>
</THead> </THead>
<TBody> <TBody>
{!isPending && {!isPending &&
data?.pages?.map((group, i) => ( data?.pages?.map((group, i) => (
<Fragment key={`audit-log-fragment-${i + 1}`}> <Fragment key={`audit-log-fragment-${i + 1}`}>
{group.map((auditLog) => ( {group.map((auditLog, index) => (
<LogsTableRow <LogsTableRow
showActorColumn={showActorColumn} rowNumber={index + i * AUDIT_LOG_LIMIT + 1}
isOrgAuditLogs={isOrgAuditLogs}
auditLog={auditLog} auditLog={auditLog}
key={`audit-log-${auditLog.id}`} key={`audit-log-${auditLog.id}`}
/> />
))} ))}
</Fragment> </Fragment>
))} ))}
{isPending && <TableSkeleton innerKey="logs-table" columns={5} key="logs" />} {isPending && <TableSkeleton innerKey="logs-table" columns={3} key="logs-loading" />}
{isEmpty && ( {isEmpty && (
<Tr> <Tr>
<Td colSpan={5}> <Td colSpan={3}>
<EmptyState title="No audit logs on file" icon={faFile} /> <EmptyState title="No audit logs on file" icon={faFile} />
</Td> </Td>
</Tr> </Tr>

View File

@ -1,128 +1,76 @@
import { faQuestionCircle } from "@fortawesome/free-solid-svg-icons"; import { faCaretDown, faCaretRight } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { format } from "date-fns";
import { Td, Tooltip, Tr } from "@app/components/v2"; import { Td, Tr } from "@app/components/v2";
import { eventToNameMap, userAgentTTypeoNameMap } from "@app/hooks/api/auditLogs/constants"; import { useToggle } from "@app/hooks";
import { ActorType, EventType } from "@app/hooks/api/auditLogs/enums"; import { ActorType } from "@app/hooks/api/auditLogs/enums";
import { Actor, AuditLog } from "@app/hooks/api/auditLogs/types"; import { AuditLog } from "@app/hooks/api/auditLogs/types";
type Props = { type Props = {
auditLog: AuditLog; auditLog: AuditLog;
isOrgAuditLogs?: boolean; rowNumber: number;
showActorColumn: boolean;
}; };
export const LogsTableRow = ({ auditLog, isOrgAuditLogs, showActorColumn }: Props) => { type TagProps = {
const renderActor = (actor: Actor) => { label: string;
if (!actor) { value?: string;
return <Td />; };
} const Tag = ({ label, value }: TagProps) => {
if (!value) return null;
switch (actor.type) {
case ActorType.USER:
return ( return (
<Td> <div className="flex items-center space-x-1.5">
<p>{actor.metadata.email}</p> <div className="rounded bg-mineshaft-600 p-0.5 pl-1 font-mono">{label}:</div>
<p>User</p> <div>{value}</div>
</Td> </div>
); );
case ActorType.SERVICE: };
export const LogsTableRow = ({ auditLog, rowNumber }: Props) => {
const [isOpen, setIsOpen] = useToggle();
return ( return (
<Td> <>
<p>{`${actor.metadata.name}`}</p> <Tr
<p>Service token</p> className="h-10 cursor-pointer border-x-0 border-b border-t-0 hover:bg-mineshaft-700"
role="button"
tabIndex={0}
onClick={() => setIsOpen.toggle()}
onKeyDown={(evt) => {
if (evt.key === "Enter") setIsOpen.toggle();
}}
isHoverable
>
<Td className="flex items-center gap-2 pr-0 align-top">
<FontAwesomeIcon icon={isOpen ? faCaretDown : faCaretRight} />
{rowNumber}
</Td> </Td>
); <Td className="align-top">
case ActorType.IDENTITY: {format(new Date(auditLog.createdAt), "MMM do yyyy, hh:mm a")}
return (
<Td>
<p>{`${actor.metadata.name}`}</p>
<p>Machine Identity</p>
</Td> </Td>
);
case ActorType.PLATFORM:
return (
<Td> <Td>
<p>Platform</p> <div className="flex flex-wrap gap-4 text-sm">
</Td> <Tag label="event" value={auditLog.event.type} />
); <Tag label="actor" value={auditLog.actor.type} />
case ActorType.KMIP_CLIENT: {auditLog.actor.type === ActorType.USER && (
return ( <Tag label="user_email" value={auditLog.actor.metadata.email} />
<Td> )}
<p>{actor.metadata.name}</p> {auditLog.actor.type === ActorType.IDENTITY && (
<p>KMIP Client</p> <Tag label="identity_name" value={auditLog.actor.metadata.name} />
</Td> )}
);
case ActorType.UNKNOWN_USER:
return (
<Td>
<div className="flex items-center gap-2">
<p>Unknown User</p>
<Tooltip content="This action was performed by a user who was not authenticated at the time.">
<FontAwesomeIcon className="text-mineshaft-400" icon={faQuestionCircle} />
</Tooltip>
</div> </div>
</Td> </Td>
);
default:
return <Td />;
}
};
const formatDate = (dateToFormat: string) => {
const date = new Date(dateToFormat);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
let hours = date.getHours();
const minutes = String(date.getMinutes()).padStart(2, "0");
// convert from 24h to 12h format
const period = hours >= 12 ? "PM" : "AM";
hours %= 12;
hours = hours || 12; // the hour '0' should be '12'
const formattedDate = `${month}-${day}-${year} at ${hours}:${minutes} ${period}`;
return formattedDate;
};
const renderSource = () => {
const { event, actor } = auditLog;
if (event.type === EventType.INTEGRATION_SYNCED) {
if (actor.type === ActorType.USER) {
return (
<Td>
<p>Manually triggered by {actor.metadata.email}</p>
</Td>
);
}
// Platform / automatic syncs
return (
<Td>
<p>Automatically synced by Infisical</p>
</Td>
);
}
return (
<Td>
<p>{userAgentTTypeoNameMap[auditLog.userAgentType]}</p>
<p>{auditLog.ipAddress}</p>
</Td>
);
};
return (
<Tr className={`log-${auditLog.id} h-10 border-x-0 border-b border-t-0`}>
<Td>{formatDate(auditLog.createdAt)}</Td>
<Td>{`${eventToNameMap[auditLog.event.type]}`}</Td>
{isOrgAuditLogs && <Td>{auditLog?.projectName ?? auditLog?.projectId ?? "N/A"}</Td>}
{showActorColumn && renderActor(auditLog.actor)}
{renderSource()}
<Td className="max-w-xs break-all">{JSON.stringify(auditLog.event.metadata || {})}</Td>
</Tr> </Tr>
{isOpen && (
<Tr className={`log-${auditLog.id} h-10 border-x-0 border-b border-t-0`}>
<Td colSpan={3} className="px-3 py-2">
<div className="thin-scrollbar my-1 max-h-96 overflow-auto whitespace-pre-wrap rounded border border-mineshaft-600 bg-bunker-800 p-2 font-mono leading-6">
{JSON.stringify(auditLog, null, 4)}
</div>
</Td>
</Tr>
)}
</>
); );
}; };

View File

@ -45,7 +45,6 @@ export const UserAuditLogsSection = withPermission(
presets={{ presets={{
actorId: orgMembership.user.id actorId: orgMembership.user.id
}} }}
isOrgAuditLogs
/> />
</div> </div>
) )

View File

@ -29,9 +29,6 @@ export const IntegrationAuditLogsSection = ({ integration }: Props) => {
</div> </div>
<LogsSection <LogsSection
refetchInterval={4000} refetchInterval={4000}
remappedHeaders={{
Metadata: "Sync Status"
}}
showFilters={false} showFilters={false}
presets={{ presets={{
eventMetadata: { integrationId: integration.id }, eventMetadata: { integrationId: integration.id },

View File

@ -35,9 +35,6 @@ export const SecretSyncAuditLogsSection = ({ secretSync }: Props) => {
{subscription.auditLogs ? ( {subscription.auditLogs ? (
<LogsSection <LogsSection
refetchInterval={4000} refetchInterval={4000}
remappedHeaders={{
Metadata: "Sync Status"
}}
showFilters={false} showFilters={false}
presets={{ presets={{
eventMetadata: { syncId: secretSync.id }, eventMetadata: { syncId: secretSync.id },