refactor(core): move database schema ownership (#29068)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
co-authored by
copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
parent
6bcb9cb9bb
commit
7f571d36ea
@@ -1,11 +1,9 @@
|
||||
import { Bus } from "@/bus"
|
||||
import { BusEvent } from "@/bus/bus-event"
|
||||
import { ConfigPermission } from "@/config/permission"
|
||||
import { InstanceState } from "@/effect/instance-state"
|
||||
import { ProjectID } from "@/project/schema"
|
||||
import { ProjectV2 } from "@opencode-ai/core/project"
|
||||
import { MessageID, SessionID } from "@/session/schema"
|
||||
import { PermissionTable } from "@/session/session.sql"
|
||||
import { Database } from "@/storage/db"
|
||||
import { PermissionTable } from "@opencode-ai/core/session/sql"
|
||||
import { Database } from "@opencode-ai/core/database/database"
|
||||
import { eq } from "drizzle-orm"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
import { Wildcard } from "@opencode-ai/core/util/wildcard"
|
||||
@@ -13,6 +11,8 @@ import { Deferred, Effect, Layer, Schema, Context } from "effect"
|
||||
import os from "os"
|
||||
import { PermissionV2 } from "@opencode-ai/core/permission"
|
||||
import { PermissionID } from "./schema"
|
||||
import { EventV2Bridge } from "@/event-v2-bridge"
|
||||
import { EventV2 } from "@opencode-ai/core/event"
|
||||
|
||||
const log = Log.create({ service: "permission" })
|
||||
|
||||
@@ -61,21 +61,21 @@ export const ReplyBody = Schema.Struct(reply).annotate({ identifier: "Permission
|
||||
export type ReplyBody = Schema.Schema.Type<typeof ReplyBody>
|
||||
|
||||
export const Approval = Schema.Struct({
|
||||
projectID: ProjectID,
|
||||
projectID: ProjectV2.ID,
|
||||
patterns: Schema.Array(Schema.String),
|
||||
}).annotate({ identifier: "PermissionApproval" })
|
||||
export type Approval = Schema.Schema.Type<typeof Approval>
|
||||
|
||||
export const Event = {
|
||||
Asked: BusEvent.define("permission.asked", Request),
|
||||
Replied: BusEvent.define(
|
||||
"permission.replied",
|
||||
Schema.Struct({
|
||||
Asked: EventV2.define({ type: "permission.asked", schema: Request.fields }),
|
||||
Replied: EventV2.define({
|
||||
type: "permission.replied",
|
||||
schema: {
|
||||
sessionID: SessionID,
|
||||
requestID: PermissionID,
|
||||
reply: Reply,
|
||||
}),
|
||||
),
|
||||
},
|
||||
}),
|
||||
}
|
||||
|
||||
export class RejectedError extends Schema.TaggedErrorClass<RejectedError>()("PermissionRejectedError", {}) {
|
||||
@@ -144,12 +144,11 @@ export class Service extends Context.Service<Service, Interface>()("@opencode/Pe
|
||||
export const layer = Layer.effect(
|
||||
Service,
|
||||
Effect.gen(function* () {
|
||||
const bus = yield* Bus.Service
|
||||
const events = yield* EventV2Bridge.Service
|
||||
const { db } = yield* Database.Service
|
||||
const state = yield* InstanceState.make<State>(
|
||||
Effect.fn("Permission.state")(function* (ctx) {
|
||||
const row = Database.use((db) =>
|
||||
db.select().from(PermissionTable).where(eq(PermissionTable.project_id, ctx.project.id)).get(),
|
||||
)
|
||||
const row = yield* db.select().from(PermissionTable).where(eq(PermissionTable.project_id, ctx.project.id)).get().pipe(Effect.orDie)
|
||||
const state = {
|
||||
pending: new Map<PermissionID, PendingEntry>(),
|
||||
approved: [...(row?.data ?? [])],
|
||||
@@ -201,7 +200,7 @@ export const layer = Layer.effect(
|
||||
|
||||
const deferred = yield* Deferred.make<void, RejectedError | CorrectedError>()
|
||||
pending.set(id, { info, deferred })
|
||||
yield* bus.publish(Event.Asked, info)
|
||||
yield* events.publish(Event.Asked, info)
|
||||
return yield* Effect.ensuring(
|
||||
Deferred.await(deferred),
|
||||
Effect.sync(() => {
|
||||
@@ -216,7 +215,7 @@ export const layer = Layer.effect(
|
||||
if (!existing) return yield* new NotFoundError({ requestID: input.requestID })
|
||||
|
||||
pending.delete(input.requestID)
|
||||
yield* bus.publish(Event.Replied, {
|
||||
yield* events.publish(Event.Replied, {
|
||||
sessionID: existing.info.sessionID,
|
||||
requestID: existing.info.id,
|
||||
reply: input.reply,
|
||||
@@ -231,7 +230,7 @@ export const layer = Layer.effect(
|
||||
for (const [id, item] of pending.entries()) {
|
||||
if (item.info.sessionID !== existing.info.sessionID) continue
|
||||
pending.delete(id)
|
||||
yield* bus.publish(Event.Replied, {
|
||||
yield* events.publish(Event.Replied, {
|
||||
sessionID: item.info.sessionID,
|
||||
requestID: item.info.id,
|
||||
reply: "reject",
|
||||
@@ -259,7 +258,7 @@ export const layer = Layer.effect(
|
||||
)
|
||||
if (!ok) continue
|
||||
pending.delete(id)
|
||||
yield* bus.publish(Event.Replied, {
|
||||
yield* events.publish(Event.Replied, {
|
||||
sessionID: item.info.sessionID,
|
||||
requestID: item.info.id,
|
||||
reply: "always",
|
||||
@@ -307,6 +306,6 @@ export function disabled(tools: string[], ruleset: Ruleset): Set<string> {
|
||||
return PermissionV2.disabled(tools, ruleset)
|
||||
}
|
||||
|
||||
export const defaultLayer = layer.pipe(Layer.provide(Bus.layer))
|
||||
export const defaultLayer = layer.pipe(Layer.provide(Database.defaultLayer), Layer.provide(EventV2Bridge.defaultLayer))
|
||||
|
||||
export * as Permission from "."
|
||||
|
||||
Reference in New Issue
Block a user