-
Notifications
You must be signed in to change notification settings - Fork 98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Audit log proposal wip #4990
Audit log proposal wip #4990
Conversation
|
🐋 This PR was built and pushed to the following Docker images (tag: Docker Bake metadata{
"app": {
"buildx.build.ref": "builder-040c5276-f5cf-4fbf-9d8f-5926d887da82/builder-040c5276-f5cf-4fbf-9d8f-5926d887da820/86jq51umh9qwcjbpph9w3ysbu",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"digest": "sha256:539c065dad908bd85b4666254d05772923aba7dd35bacc60ea2316b48b846fe5",
"size": 685
},
"containerimage.digest": "sha256:539c065dad908bd85b4666254d05772923aba7dd35bacc60ea2316b48b846fe5",
"image.name": "ghcr.io/kamilkisiela/graphql-hive/app:9fcbb6073d9a38a85b16ff92641ee31a823f1239,ghcr.io/kamilkisiela/graphql-hive/app:audit_log_wip"
},
"composition-federation-2": {
"buildx.build.ref": "builder-040c5276-f5cf-4fbf-9d8f-5926d887da82/builder-040c5276-f5cf-4fbf-9d8f-5926d887da820/68nux27o9hzkuhly69glr429x",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"digest": "sha256:7fc7661783301a65775265be08d412b578f5bbaf1f228e02e81e629a874013be",
"size": 685
},
"containerimage.digest": "sha256:7fc7661783301a65775265be08d412b578f5bbaf1f228e02e81e629a874013be",
"image.name": "ghcr.io/kamilkisiela/graphql-hive/composition-federation-2:9fcbb6073d9a38a85b16ff92641ee31a823f1239,ghcr.io/kamilkisiela/graphql-hive/composition-federation-2:audit_log_wip"
},
"emails": {
"buildx.build.ref": "builder-040c5276-f5cf-4fbf-9d8f-5926d887da82/builder-040c5276-f5cf-4fbf-9d8f-5926d887da820/5oa28gcjztxolrz46t2xcki7f",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"digest": "sha256:57e51764125489a5f2707789e59f935c0e0fb2f7da302dbd5357fa80453c4020",
"size": 685
},
"containerimage.digest": "sha256:57e51764125489a5f2707789e59f935c0e0fb2f7da302dbd5357fa80453c4020",
"image.name": "ghcr.io/kamilkisiela/graphql-hive/emails:9fcbb6073d9a38a85b16ff92641ee31a823f1239,ghcr.io/kamilkisiela/graphql-hive/emails:audit_log_wip"
},
"policy": {
"buildx.build.ref": "builder-040c5276-f5cf-4fbf-9d8f-5926d887da82/builder-040c5276-f5cf-4fbf-9d8f-5926d887da820/f0xxlzpidslh6dkxars1vyeko",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"digest": "sha256:8c99e550237485fd7ba91756757de22b77c37594b45d96541360cede0bd772f6",
"size": 685
},
"containerimage.digest": "sha256:8c99e550237485fd7ba91756757de22b77c37594b45d96541360cede0bd772f6",
"image.name": "ghcr.io/kamilkisiela/graphql-hive/policy:9fcbb6073d9a38a85b16ff92641ee31a823f1239,ghcr.io/kamilkisiela/graphql-hive/policy:audit_log_wip"
},
"rate-limit": {
"buildx.build.ref": "builder-040c5276-f5cf-4fbf-9d8f-5926d887da82/builder-040c5276-f5cf-4fbf-9d8f-5926d887da820/prvvlu9zcxod4hnbit2gybdqo",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"digest": "sha256:07344efa2254701a2646c494182ae24aa949092847cf1cc574d82b0335af98d0",
"size": 685
},
"containerimage.digest": "sha256:07344efa2254701a2646c494182ae24aa949092847cf1cc574d82b0335af98d0",
"image.name": "ghcr.io/kamilkisiela/graphql-hive/rate-limit:9fcbb6073d9a38a85b16ff92641ee31a823f1239,ghcr.io/kamilkisiela/graphql-hive/rate-limit:audit_log_wip"
},
"schema": {
"buildx.build.ref": "builder-040c5276-f5cf-4fbf-9d8f-5926d887da82/builder-040c5276-f5cf-4fbf-9d8f-5926d887da820/uu8pgip2khqms2lodk20vwdr3",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"digest": "sha256:1dbf36028242c349bf3065018b3fa3fe76d8cf574e60e853e6f03b2450853f9c",
"size": 685
},
"containerimage.digest": "sha256:1dbf36028242c349bf3065018b3fa3fe76d8cf574e60e853e6f03b2450853f9c",
"image.name": "ghcr.io/kamilkisiela/graphql-hive/schema:9fcbb6073d9a38a85b16ff92641ee31a823f1239,ghcr.io/kamilkisiela/graphql-hive/schema:audit_log_wip"
},
"server": {
"buildx.build.ref": "builder-040c5276-f5cf-4fbf-9d8f-5926d887da82/builder-040c5276-f5cf-4fbf-9d8f-5926d887da820/v1oxvqiifww1w2ecwpgrtiort",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"digest": "sha256:e8af9f1194403b483cde85f7c11dfb36bff103570c4050a68513b879849703be",
"size": 685
},
"containerimage.digest": "sha256:e8af9f1194403b483cde85f7c11dfb36bff103570c4050a68513b879849703be",
"image.name": "ghcr.io/kamilkisiela/graphql-hive/server:9fcbb6073d9a38a85b16ff92641ee31a823f1239,ghcr.io/kamilkisiela/graphql-hive/server:audit_log_wip"
},
"storage": {
"buildx.build.ref": "builder-040c5276-f5cf-4fbf-9d8f-5926d887da82/builder-040c5276-f5cf-4fbf-9d8f-5926d887da820/rqqiqqzvizhwdwenn3vi7p2fd",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"digest": "sha256:1e0a19e7fcca5d4addf97a552c6d66feb2a0b06de13b8e30cc6b6836fa719125",
"size": 685
},
"containerimage.digest": "sha256:1e0a19e7fcca5d4addf97a552c6d66feb2a0b06de13b8e30cc6b6836fa719125",
"image.name": "ghcr.io/kamilkisiela/graphql-hive/storage:9fcbb6073d9a38a85b16ff92641ee31a823f1239,ghcr.io/kamilkisiela/graphql-hive/storage:audit_log_wip"
},
"stripe-billing": {
"buildx.build.ref": "builder-040c5276-f5cf-4fbf-9d8f-5926d887da82/builder-040c5276-f5cf-4fbf-9d8f-5926d887da820/yx4umneupru26970r3ptybmy6",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"digest": "sha256:b40bef43cdb9bd55089f435dae88f690e81935ae1f395b6949704316fcde56ae",
"size": 685
},
"containerimage.digest": "sha256:b40bef43cdb9bd55089f435dae88f690e81935ae1f395b6949704316fcde56ae",
"image.name": "ghcr.io/kamilkisiela/graphql-hive/stripe-billing:9fcbb6073d9a38a85b16ff92641ee31a823f1239,ghcr.io/kamilkisiela/graphql-hive/stripe-billing:audit_log_wip"
},
"tokens": {
"buildx.build.ref": "builder-040c5276-f5cf-4fbf-9d8f-5926d887da82/builder-040c5276-f5cf-4fbf-9d8f-5926d887da820/2t44x5dp1pvpxu6388mcgf1i6",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"digest": "sha256:09de7dc08a8d6eaa02bc137242c3a530f4423782cdb4c88743c4c8b7e58b9a00",
"size": 685
},
"containerimage.digest": "sha256:09de7dc08a8d6eaa02bc137242c3a530f4423782cdb4c88743c4c8b7e58b9a00",
"image.name": "ghcr.io/kamilkisiela/graphql-hive/tokens:9fcbb6073d9a38a85b16ff92641ee31a823f1239,ghcr.io/kamilkisiela/graphql-hive/tokens:audit_log_wip"
},
"usage": {
"buildx.build.ref": "builder-040c5276-f5cf-4fbf-9d8f-5926d887da82/builder-040c5276-f5cf-4fbf-9d8f-5926d887da820/rf24lgkc3yl0m6hthxnfrnp00",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"digest": "sha256:35e55d1a7271444594f5406aadb4491ce9d3c9ae5acd6a968878c22e08f6c80b",
"size": 685
},
"containerimage.digest": "sha256:35e55d1a7271444594f5406aadb4491ce9d3c9ae5acd6a968878c22e08f6c80b",
"image.name": "ghcr.io/kamilkisiela/graphql-hive/usage:9fcbb6073d9a38a85b16ff92641ee31a823f1239,ghcr.io/kamilkisiela/graphql-hive/usage:audit_log_wip"
},
"usage-estimator": {
"buildx.build.ref": "builder-040c5276-f5cf-4fbf-9d8f-5926d887da82/builder-040c5276-f5cf-4fbf-9d8f-5926d887da820/abovun7ysqwdbedp7pii959mt",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"digest": "sha256:0762c150e10420da5f6d8e43d5c033d7eaa0bbee0bedbbfe001c1f00b826fe68",
"size": 685
},
"containerimage.digest": "sha256:0762c150e10420da5f6d8e43d5c033d7eaa0bbee0bedbbfe001c1f00b826fe68",
"image.name": "ghcr.io/kamilkisiela/graphql-hive/usage-estimator:9fcbb6073d9a38a85b16ff92641ee31a823f1239,ghcr.io/kamilkisiela/graphql-hive/usage-estimator:audit_log_wip"
},
"usage-ingestor": {
"buildx.build.ref": "builder-040c5276-f5cf-4fbf-9d8f-5926d887da82/builder-040c5276-f5cf-4fbf-9d8f-5926d887da820/uus3w247zpqrxdcujollhi5bz",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"digest": "sha256:c15708a565738b2f5a3f6b5a6924e719499dab9edf3aa9911a80effe073bb83f",
"size": 685
},
"containerimage.digest": "sha256:c15708a565738b2f5a3f6b5a6924e719499dab9edf3aa9911a80effe073bb83f",
"image.name": "ghcr.io/kamilkisiela/graphql-hive/usage-ingestor:9fcbb6073d9a38a85b16ff92641ee31a823f1239,ghcr.io/kamilkisiela/graphql-hive/usage-ingestor:audit_log_wip"
},
"webhooks": {
"buildx.build.ref": "builder-040c5276-f5cf-4fbf-9d8f-5926d887da82/builder-040c5276-f5cf-4fbf-9d8f-5926d887da820/npwz1qdit3b00mfcp76yvu4wr",
"containerimage.descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"digest": "sha256:6674ab906d3da70377f08e4449b9c3f2991b0c776f61b3c8500d6c9817cc40f3",
"size": 685
},
"containerimage.digest": "sha256:6674ab906d3da70377f08e4449b9c3f2991b0c776f61b3c8500d6c9817cc40f3",
"image.name": "ghcr.io/kamilkisiela/graphql-hive/webhooks:9fcbb6073d9a38a85b16ff92641ee31a823f1239,ghcr.io/kamilkisiela/graphql-hive/webhooks:audit_log_wip"
}
} |
@capaj Compiling this list based on GraphQL mutation root fields might be more useful as they already describe the actions from a user point of view. Then from there, we can pick the classes/methods that have the business logic for these. See the type Mutation {
activateAppDeployment(input: ActivateAppDeploymentInput!): ActivateAppDeploymentResult!
addAlert(input: AddAlertInput!): AddAlertResult!
addAlertChannel(input: AddAlertChannelInput!): AddAlertChannelResult!
addDocumentsToAppDeployment(input: AddDocumentsToAppDeploymentInput!): AddDocumentsToAppDeploymentResult!
addGitHubIntegration(input: AddGitHubIntegrationInput!): Boolean!
addSlackIntegration(input: AddSlackIntegrationInput!): Boolean!
answerOrganizationTransferRequest(input: AnswerOrganizationTransferRequestInput!): AnswerOrganizationTransferRequestResult!
"""Approve a failed schema check with breaking changes."""
approveFailedSchemaCheck(input: ApproveFailedSchemaCheckInput!): ApproveFailedSchemaCheckResult!
assignMemberRole(input: AssignMemberRoleInput!): AssignMemberRoleResult!
createAppDeployment(input: CreateAppDeploymentInput!): CreateAppDeploymentResult!
createCdnAccessToken(input: CreateCdnAccessTokenInput!): CdnAccessTokenCreateResult!
"""Create a contract for a given target."""
createContract(input: CreateContractInput!): CreateContractResult!
createDocumentCollection(input: CreateDocumentCollectionInput!, selector: TargetSelectorInput!): ModifyDocumentCollectionResult!
createMemberRole(input: CreateMemberRoleInput!): CreateMemberRoleResult!
createOIDCIntegration(input: CreateOIDCIntegrationInput!): CreateOIDCIntegrationResult!
createOperationInDocumentCollection(input: CreateDocumentCollectionOperationInput!, selector: TargetSelectorInput!): ModifyDocumentCollectionOperationResult!
createOrganization(input: CreateOrganizationInput!): CreateOrganizationResult!
createProject(input: CreateProjectInput!): CreateProjectResult!
createTarget(input: CreateTargetInput!): CreateTargetResult!
createToken(input: CreateTokenInput!): CreateTokenResult!
deleteAlertChannels(input: DeleteAlertChannelsInput!): DeleteAlertChannelsResult!
deleteAlerts(input: DeleteAlertsInput!): DeleteAlertsResult!
deleteCdnAccessToken(input: DeleteCdnAccessTokenInput!): DeleteCdnAccessTokenResult!
deleteDocumentCollection(id: ID!, selector: TargetSelectorInput!): DeleteDocumentCollectionResult!
deleteGitHubIntegration(input: OrganizationSelectorInput!): DeleteGitHubIntegrationResult!
deleteMemberRole(input: DeleteMemberRoleInput!): DeleteMemberRoleResult!
deleteOIDCIntegration(input: DeleteOIDCIntegrationInput!): DeleteOIDCIntegrationResult!
deleteOperationInDocumentCollection(id: ID!, selector: TargetSelectorInput!): DeleteDocumentCollectionOperationResult!
deleteOrganization(selector: OrganizationSelectorInput!): OrganizationPayload!
deleteOrganizationInvitation(input: DeleteOrganizationInvitationInput!): DeleteOrganizationInvitationResult!
deleteOrganizationMember(input: OrganizationMemberInput!): OrganizationPayload!
deleteProject(selector: ProjectSelectorInput!): DeleteProjectPayload!
deleteSlackIntegration(input: OrganizationSelectorInput!): DeleteSlackIntegrationResult!
deleteTarget(selector: TargetSelectorInput!): DeleteTargetPayload!
deleteTokens(input: DeleteTokensInput!): DeleteTokensPayload!
"""Disable a contract."""
disableContract(input: DisableContractInput!): DisableContractResult!
disableExternalSchemaComposition(input: DisableExternalSchemaCompositionInput!): DisableExternalSchemaCompositionResult!
downgradeToHobby(input: DowngradeToHobbyInput!): ChangePlanResult!
enableExternalSchemaComposition(input: EnableExternalSchemaCompositionInput!): EnableExternalSchemaCompositionResult!
enableProjectNameInGithubCheck(input: ProjectSelectorInput!): Project!
"""
Overwrites project's schema composition library.
Works only for Federation projects with native composition enabled.
This mutation is temporary and will be removed once no longer needed.
It's part of a feature flag called "forceLegacyCompositionInTargets".
"""
experimental__updateTargetSchemaComposition(input: Experimental__UpdateTargetSchemaCompositionInput!): Target!
generateStripePortalLink(selector: OrganizationSelectorInput!): String!
inviteToOrganizationByEmail(input: InviteToOrganizationByEmailInput!): InviteToOrganizationByEmailResult!
joinOrganization(code: String!): JoinOrganizationPayload!
leaveOrganization(input: OrganizationSelectorInput!): LeaveOrganizationResult!
"""Remove this mutation after migration is complete."""
migrateUnassignedMembers(input: MigrateUnassignedMembersInput!): MigrateUnassignedMembersResult!
noop(noop: String): Boolean
requestOrganizationTransfer(input: RequestOrganizationTransferInput!): RequestOrganizationTransferResult!
retireAppDeployment(input: RetireAppDeploymentInput!): RetireAppDeploymentResult!
"""Requires API Token"""
schemaCheck(input: SchemaCheckInput!): SchemaCheckPayload!
"""Requires API Token"""
schemaCompose(input: SchemaComposeInput!): SchemaComposePayload!
"""Requires API Token"""
schemaDelete(input: SchemaDeleteInput!): SchemaDeleteResult!
"""Requires API Token"""
schemaPublish(input: SchemaPublishInput!): SchemaPublishPayload!
sendFeedback(feedback: String!): Boolean!
setTargetValidation(input: SetTargetValidationInput!): Target!
supportTicketCreate(input: SupportTicketCreateInput!): SupportTicketCreateResult!
supportTicketReply(input: SupportTicketReplyInput!): SupportTicketReplyResult!
updateBaseSchema(input: UpdateBaseSchemaInput!): UpdateBaseSchemaResult!
updateDocumentCollection(input: UpdateDocumentCollectionInput!, selector: TargetSelectorInput!): ModifyDocumentCollectionResult!
updateMe(input: UpdateMeInput!): UpdateMeResult!
updateMemberRole(input: UpdateMemberRoleInput!): UpdateMemberRoleResult!
updateNativeFederation(input: UpdateNativeFederationInput!): UpdateNativeFederationResult!
updateOIDCIntegration(input: UpdateOIDCIntegrationInput!): UpdateOIDCIntegrationResult!
updateOperationInDocumentCollection(input: UpdateDocumentCollectionOperationInput!, selector: TargetSelectorInput!): ModifyDocumentCollectionOperationResult!
updateOrgRateLimit(monthlyLimits: RateLimitInput!, selector: OrganizationSelectorInput!): Organization!
updateOrganizationMemberAccess(input: OrganizationMemberAccessInput!): OrganizationPayload!
updateOrganizationName(input: UpdateOrganizationNameInput!): UpdateOrganizationNameResult!
updateProjectName(input: UpdateProjectNameInput!): UpdateProjectNameResult!
updateProjectRegistryModel(input: UpdateProjectRegistryModelInput!): UpdateProjectRegistryModelResult!
updateSchemaPolicyForOrganization(allowOverrides: Boolean!, policy: SchemaPolicyInput!, selector: OrganizationSelectorInput!): UpdateSchemaPolicyResult!
updateSchemaPolicyForProject(policy: SchemaPolicyInput!, selector: ProjectSelectorInput!): UpdateSchemaPolicyResult!
updateSchemaVersionStatus(input: SchemaVersionUpdateInput!): SchemaVersion!
"""Updates the target's explorer endpoint url."""
updateTargetGraphQLEndpointUrl(input: UpdateTargetGraphQLEndpointUrlInput!): UpdateTargetGraphQLEndpointUrlResult!
updateTargetName(input: UpdateTargetNameInput!): UpdateTargetNameResult!
updateTargetValidationSettings(input: UpdateTargetValidationSettingsInput!): UpdateTargetValidationSettingsResult!
upgradeToPro(input: UpgradeToProInput!): ChangePlanResult!
} |
@n1ru4l I did it based on the provider typescript classes as suggested here: Are there still too many events missing? I have added a lot of them from Storage interface now. |
Co-authored-by: Dimitri POSTOLOV <en3m@ya.ru>
Co-authored-by: Dimitri POSTOLOV <en3m@ya.ru>
Co-authored-by: Dimitri POSTOLOV <en3m@ya.ru>
@capaj I think there was a misunderstanding before, in which exact method the logging is added is not as important right now. We need a list of the event types, the data stored for that specific event, and a sample formatted sentence on how to display that data within the app for users. We can take the mutation resolvers as an entry point to locate the class method where the logging should be added for the actual implementation later on, and get a better idea of the data worth storing. |
@n1ru4l the list of events I propose to log is here between lines 10 and 144:
why is FE a necessary part of this task? It was once mentioned, but I never thought it's part of this proposal. I can add it if you deem it is necessary and we need to implement it from the get got.
this will take me like 2-3 days to add to the proposal. I need to go through each event, basically find where it is going to be called. EDIT: actually you mentioned FE once here https://guild-oss.slack.com/archives/C01E8ATBQGN/p1718615139510519?thread_ts=1718613813.068609&cid=C01E8ATBQGN |
I was suggesting using an http middleware where mutation resolver names would be used as event names in our initial conversation on slack and you said we should rather use our bussinec logic classes here: https://guild-oss.slack.com/archives/C01E8ATBQGN/p1718614773106589?thread_ts=1718613813.068609&cid=C01E8ATBQGN so that's why I went for the class method names rather than GQL mutation resolver names. If you think we should rather use GQL mutation resolver names I am totally fine with that, In that case I would probably suggest we track almost all of them, maybe with exception of For example for event |
From what it seems to me there is misalignment between me and @kamilkisiela @n1ru4l on what the objective is for this issue. They see it as fullstack solution that we can deploy and it will have a nice UI for the user to be able to search, filter, download and explore the audit logs. I have never considered the UI part for this proposal. Since the UI part is so important to both @kamilkisiela and @n1ru4l it's not productive to try to work on the proposal for anyone without the knowledge of actual usecases. I am a bit confused why anyone would think this task is ready for getting specced when @kamilkisiela admitted himself we do not have a list of filters from the UI: https://guild-oss.slack.com/archives/CAY2119MX/p1718801461050759?thread_ts=1718790068.341029&cid=CAY2119MX Let's close this proposal until we have clearer requirements as in it's current form it's nowhere near acceptable for @n1ru4l and @kamilkisiela |
just for review purposes, don't merge