Compare commits

...

16 Commits

Author SHA1 Message Date
ArshBallagan
f1bc26e2e5 Update terraform.mdx 2025-03-20 16:09:01 -07:00
Maidul Islam
8aeb607f6e Merge pull request #3287 from akhilmhdh/fix/patch-4
Fix/patch 4
2025-03-20 17:32:32 -04:00
=
e530b7a788 feat: reduced to two 2025-03-21 02:59:44 +05:30
=
bf61090b5a feat: added cache clear and refresh with session limit 2025-03-21 02:58:59 +05:30
Maidul Islam
106b068a51 Merge pull request #3286 from akhilmhdh/fix/patch-4
feat: removed refresh
2025-03-20 17:16:01 -04:00
=
6f0a97a2fa feat: removed refresh 2025-03-21 02:43:10 +05:30
Maidul Islam
5d604be091 Merge pull request #3285 from akhilmhdh/fix/patch-4
feat: return fastify res and making it async
2025-03-20 17:01:03 -04:00
=
905cf47d90 feat: return fastify res and making it async 2025-03-21 02:26:33 +05:30
Sheen
2c40d316f4 Merge pull request #3284 from Infisical/misc/add-flag-for-disabling-worker-queue
misc: add flag for disabling workers
2025-03-21 03:49:57 +08:00
Sheen Capadngan
32521523c1 misc: add flag for disabling workers 2025-03-21 03:46:17 +08:00
Sheen
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
Maidul Islam
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
21 changed files with 437 additions and 393 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -65,7 +65,7 @@ export const registerSecretScannerGhApp = async (server: FastifyZodProvider) =>
payload: JSON.stringify(req.body),
signature: signatureSHA256
});
void res.send("ok");
return res.send("ok");
}
});
}

View File

@@ -34,7 +34,7 @@ export const registerServeUI = async (
TELEMETRY_CAPTURING_ENABLED: appCfg.TELEMETRY_ENABLED
};
const js = `window.__INFISICAL_RUNTIME_ENV__ = Object.freeze(${JSON.stringify(config)});`;
void res.send(js);
return res.send(js);
}
});
@@ -57,7 +57,7 @@ export const registerServeUI = async (
reply.callNotFound();
return;
}
void reply.sendFile("index.html");
return reply.sendFile("index.html");
}
});
}

View File

@@ -69,9 +69,15 @@ export const identityUaServiceFactory = ({
isClientSecretRevoked: false
});
const validClientSecretInfo = clientSecrtInfo.find(({ clientSecretHash }) =>
bcrypt.compareSync(clientSecret, clientSecretHash)
);
let validClientSecretInfo: (typeof clientSecrtInfo)[0] | null = null;
for await (const info of clientSecrtInfo) {
const isMatch = await bcrypt.compare(clientSecret, info.clientSecretHash);
if (isMatch) {
validClientSecretInfo = info;
break;
}
}
if (!validClientSecretInfo) throw new UnauthorizedError({ message: "Invalid credentials" });
const { clientSecretTTL, clientSecretNumUses, clientSecretNumUsesLimit } = validClientSecretInfo;
@@ -104,7 +110,7 @@ export const identityUaServiceFactory = ({
}
const identityAccessToken = await identityUaDAL.transaction(async (tx) => {
const uaClientSecretDoc = await identityUaClientSecretDAL.incrementUsage(validClientSecretInfo.id, tx);
const uaClientSecretDoc = await identityUaClientSecretDAL.incrementUsage(validClientSecretInfo!.id, tx);
const newToken = await identityAccessTokenDAL.create(
{
identityId: identityUa.identityId,

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**,
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.
</Info>
Infisical provides audit logs for security and compliance teams to monitor information access.
With the Audit Log functionality, teams can:
- **Track** 40+ different events;
- **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.
![Audit logs](../../images/platform/audit-logs/audit-logs-table.png)
## Audit Log Structure
Each log contains the following data:
- **Event**: The underlying action such as create, list, read, update, or delete secret(s).
- **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.
- **Source** (User agent + IP): The software (user agent) and network address (IP) from which the event was initiated.
- **Metadata**: Additional data to provide context for each event. For example, this could be the path at which a secret was fetched from etc.
| Field | Type | Description | Purpose |
| ------------------------- | -------- | --------------------------------------------------------- | ------------------------------------------------------------- |
| **event** | Object | Contains details about the action performed | Captures what happened |
| event.type | String | The specific action that occurred (e.g., "create-secret") | Identifies the exact operation |
| 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

@@ -6,7 +6,7 @@ description: "Learn how to fetch secrets from Infisical with Terraform using bot
This guide demonstrates how to use Infisical to manage secrets in your Terraform infrastructure code, supporting both traditional data sources and ephemeral resources for enhanced security. It uses:
- Infisical (you can use [Infisical Cloud](https://app.infisical.com) or a [self-hosted instance of Infisical](https://infisical.com/docs/self-hosting/overview)) to store your secrets
- The [Terraform Provider](https://registry.terraform.io/providers/Infisical/infisical/latest) to fetch secrets for your infrastructure
- The [Terraform Provider](https://registry.terraform.io/providers/Infisical/infisical/latest/docs) to fetch secrets for your infrastructure
## Prerequisites

View File

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

View File

@@ -22,14 +22,37 @@ import "./translation";
// have a look at the Quick start guide
// for passing in lng and translations on init/
// https://vite.dev/guide/build#load-error-handling
window.addEventListener("vite:preloadError", () => {
window.location.reload(); // for example, refresh the page
});
// Create a new router instance
NProgress.configure({ showSpinner: false });
window.addEventListener("vite:preloadError", async (event) => {
event.preventDefault();
// Get current count from session storage or initialize to 0
const reloadCount = parseInt(sessionStorage.getItem("vitePreloadErrorCount") || "0", 10);
// Check if we've already tried 3 times
if (reloadCount >= 2) {
console.warn("Vite preload has failed multiple times. Stopping automatic reload.");
// Optionally show a user-facing message here
return;
}
try {
if ("caches" in window) {
const keys = await caches.keys();
await Promise.all(keys.map((key) => caches.delete(key)));
}
} catch (cleanupError) {
console.error(cleanupError);
}
//
// Increment and save the counter
sessionStorage.setItem("vitePreloadErrorCount", (reloadCount + 1).toString());
console.log(`Reloading page (attempt ${reloadCount + 1} of 2)...`);
window.location.reload(); // for example, refresh the page
});
const router = createRouter({
routeTree,
context: { serverConfig: null, queryClient },

View File

@@ -18,7 +18,7 @@ export const AuditLogsPage = () => {
title="Audit logs"
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>

View File

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

View File

@@ -1,5 +1,6 @@
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 {
Button,
@@ -11,6 +12,7 @@ import {
Td,
Th,
THead,
Tooltip,
Tr
} from "@app/components/v2";
import { useGetAuditLogs } from "@app/hooks/api";
@@ -19,32 +21,13 @@ import { TGetAuditLogsFilter } from "@app/hooks/api/auditLogs/types";
import { LogsTableRow } from "./LogsTableRow";
type Props = {
isOrgAuditLogs?: boolean;
showActorColumn: boolean;
filter?: TGetAuditLogsFilter;
remappedHeaders?: Partial<Record<TAuditLogTableHeader, string>>;
refetchInterval?: number;
};
const AUDIT_LOG_LIMIT = 15;
const TABLE_HEADERS = [
"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) => {
export const LogsTable = ({ filter, refetchInterval }: Props) => {
// Determine the project ID for filtering
const filterProjectId =
// Use the projectId from the filter if it exists
@@ -69,38 +52,37 @@ export const LogsTable = ({
<Table>
<THead>
<Tr>
{TABLE_HEADERS.map((header, idx) => {
if (
(header === "Project" && !isOrgAuditLogs) ||
(header === "Actor" && !showActorColumn)
) {
return null;
}
return (
<Th key={`table-header-${idx + 1}`}>{remappedHeaders?.[header] || header}</Th>
);
})}
<Th className="w-24" />
<Th className="w-64">
Timestamp
<Tooltip
className="normal-case"
content="Time displayed in your system's time zone."
sideOffset={10}
>
<FontAwesomeIcon icon={faInfoCircle} className="ml-1" />
</Tooltip>
</Th>
<Th>Event</Th>
</Tr>
</THead>
<TBody>
{!isPending &&
data?.pages?.map((group, i) => (
<Fragment key={`audit-log-fragment-${i + 1}`}>
{group.map((auditLog) => (
{group.map((auditLog, index) => (
<LogsTableRow
showActorColumn={showActorColumn}
isOrgAuditLogs={isOrgAuditLogs}
rowNumber={index + i * AUDIT_LOG_LIMIT + 1}
auditLog={auditLog}
key={`audit-log-${auditLog.id}`}
/>
))}
</Fragment>
))}
{isPending && <TableSkeleton innerKey="logs-table" columns={5} key="logs" />}
{isPending && <TableSkeleton innerKey="logs-table" columns={3} key="logs-loading" />}
{isEmpty && (
<Tr>
<Td colSpan={5}>
<Td colSpan={3}>
<EmptyState title="No audit logs on file" icon={faFile} />
</Td>
</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 { format } from "date-fns";
import { Td, Tooltip, Tr } from "@app/components/v2";
import { eventToNameMap, userAgentTTypeoNameMap } from "@app/hooks/api/auditLogs/constants";
import { ActorType, EventType } from "@app/hooks/api/auditLogs/enums";
import { Actor, AuditLog } from "@app/hooks/api/auditLogs/types";
import { Td, Tr } from "@app/components/v2";
import { useToggle } from "@app/hooks";
import { ActorType } from "@app/hooks/api/auditLogs/enums";
import { AuditLog } from "@app/hooks/api/auditLogs/types";
type Props = {
auditLog: AuditLog;
isOrgAuditLogs?: boolean;
showActorColumn: boolean;
rowNumber: number;
};
export const LogsTableRow = ({ auditLog, isOrgAuditLogs, showActorColumn }: Props) => {
const renderActor = (actor: Actor) => {
if (!actor) {
return <Td />;
}
switch (actor.type) {
case ActorType.USER:
return (
<Td>
<p>{actor.metadata.email}</p>
<p>User</p>
</Td>
);
case ActorType.SERVICE:
return (
<Td>
<p>{`${actor.metadata.name}`}</p>
<p>Service token</p>
</Td>
);
case ActorType.IDENTITY:
return (
<Td>
<p>{`${actor.metadata.name}`}</p>
<p>Machine Identity</p>
</Td>
);
case ActorType.PLATFORM:
return (
<Td>
<p>Platform</p>
</Td>
);
case ActorType.KMIP_CLIENT:
return (
<Td>
<p>{actor.metadata.name}</p>
<p>KMIP Client</p>
</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>
</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>
);
};
type TagProps = {
label: string;
value?: string;
};
const Tag = ({ label, value }: TagProps) => {
if (!value) return null;
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>
<div className="flex items-center space-x-1.5">
<div className="rounded bg-mineshaft-600 p-0.5 pl-1 font-mono">{label}:</div>
<div>{value}</div>
</div>
);
};
export const LogsTableRow = ({ auditLog, rowNumber }: Props) => {
const [isOpen, setIsOpen] = useToggle();
return (
<>
<Tr
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 className="align-top">
{format(new Date(auditLog.createdAt), "MMM do yyyy, hh:mm a")}
</Td>
<Td>
<div className="flex flex-wrap gap-4 text-sm">
<Tag label="event" value={auditLog.event.type} />
<Tag label="actor" value={auditLog.actor.type} />
{auditLog.actor.type === ActorType.USER && (
<Tag label="user_email" value={auditLog.actor.metadata.email} />
)}
{auditLog.actor.type === ActorType.IDENTITY && (
<Tag label="identity_name" value={auditLog.actor.metadata.name} />
)}
</div>
</Td>
</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={{
actorId: orgMembership.user.id
}}
isOrgAuditLogs
/>
</div>
)

View File

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

View File

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