diff --git a/drawings/appsec_achitecture/db_scheme.sql b/drawings/appsec_achitecture/db_scheme.sql
new file mode 100644
index 0000000..9339292
--- /dev/null
+++ b/drawings/appsec_achitecture/db_scheme.sql
@@ -0,0 +1,117 @@
+CREATE TABLE "meta" (
+ "id" uuid UNIQUE PRIMARY KEY NOT NULL,
+ "system_code" varchar(50) NOT NULL,
+ "tool" uuid,
+ "practice" varchar(32) NOT NULL,
+ "build" varchar(250) NOT NULL,
+ "enviroment" varchar(250) NOT NULL,
+ "library" varchar(50),
+ "method" varchar(10),
+ "hash" varchar(500) NOT NULL,
+ "created_at" datetime NOT NULL
+);
+
+CREATE TABLE "tool" (
+ "id" uuid UNIQUE PRIMARY KEY NOT NULL,
+ "tool" varchar(50) NOT NULL,
+ "practive" varchar(20) NOT NULL
+);
+
+CREATE TABLE "problem" (
+ "id" uuid UNIQUE PRIMARY KEY NOT NULL,
+ "executor" uuid,
+ "is_created_manually" bool,
+ "status" varchar(32) NOT NULL,
+ "status_updated_at" datetime NOT NULL,
+ "resolution" varchar(32),
+ "priority" varchar(32) NOT NULL,
+ "description" varchar(500),
+ "remediation" varchar(500),
+ "сategory" varchar(250),
+ "cve" varchar(50),
+ "cwe" varchar(500),
+ "cvss" int,
+ "location" varchar(500) NOT NULL,
+ "defect_id" uuid,
+ "defect_status" varchar(32),
+ "created_at" datetime NOT NULL,
+ "exception_date" datetime,
+ "category" varchar(250),
+ "hash" varchar(500) NOT NULL,
+ "creator" uuid,
+ "version" int NOT NULL,
+ "group_id" uuid,
+ "meta" uuid NOT NULL
+);
+
+CREATE TABLE "user" (
+ "id" uuid UNIQUE PRIMARY KEY NOT NULL,
+ "login" varchar(100) NOT NULL,
+ "is_active" bool
+);
+
+CREATE TABLE "problem_group" (
+ "id" uuid UNIQUE PRIMARY KEY NOT NULL,
+ "name" varchar(50) NOT NULL,
+ "description" varchar(300)
+);
+
+CREATE TABLE "system" (
+ "id" uuid UNIQUE PRIMARY KEY NOT NULL,
+ "name" varchar(50) NOT NULL,
+ "code" varchar(50) NOT NULL,
+ "buiseness_critical" bool,
+ "security_critical" bool,
+ "is_active" bool,
+ PRIMARY KEY ("id")
+);
+
+CREATE TABLE "user_to_system" (
+ "system_id" uuid NOT NULL,
+ "user_id" uuid NOT NULL,
+ PRIMARY KEY ("system_id", "user_id")
+);
+
+CREATE TABLE "comment" (
+ "id" uuid PRIMARY KEY NOT NULL,
+ "problem_id" uuid NOT NULL,
+ "description" varchar(500) NOT NULL,
+ "created_by" uuid NOT NULL,
+ "created_at" datetime NOT NULL
+);
+
+CREATE TABLE "work_history" (
+ "id" uuid PRIMARY KEY NOT NULL,
+ "problem_id" uuid NOT NULL,
+ "action" varchar(100),
+ "old_value" varchar(100),
+ "new_value" varchar(100),
+ "user_id" uuid NOT NULL,
+ "created_at" datetime NOT NULL
+);
+
+CREATE INDEX ON "system" ("code");
+
+ALTER TABLE "meta" ADD FOREIGN KEY ("system_code") REFERENCES "system" ("code");
+
+ALTER TABLE "meta" ADD FOREIGN KEY ("tool") REFERENCES "tool" ("id");
+
+ALTER TABLE "problem" ADD FOREIGN KEY ("executor") REFERENCES "user" ("id");
+
+ALTER TABLE "problem" ADD FOREIGN KEY ("creator") REFERENCES "user" ("id");
+
+ALTER TABLE "problem" ADD FOREIGN KEY ("group_id") REFERENCES "problem_group" ("id");
+
+ALTER TABLE "problem" ADD FOREIGN KEY ("meta") REFERENCES "meta" ("id");
+
+ALTER TABLE "user_to_system" ADD FOREIGN KEY ("system_id") REFERENCES "system" ("id");
+
+ALTER TABLE "user_to_system" ADD FOREIGN KEY ("user_id") REFERENCES "user" ("id");
+
+ALTER TABLE "comment" ADD FOREIGN KEY ("problem_id") REFERENCES "problem" ("id");
+
+ALTER TABLE "comment" ADD FOREIGN KEY ("created_by") REFERENCES "user" ("id");
+
+ALTER TABLE "work_history" ADD FOREIGN KEY ("problem_id") REFERENCES "problem" ("id");
+
+ALTER TABLE "work_history" ADD FOREIGN KEY ("user_id") REFERENCES "user" ("id");
diff --git a/drawings/appsec_achitecture/db_scheme.txt b/drawings/appsec_achitecture/db_scheme.txt
new file mode 100644
index 0000000..e7a26b5
--- /dev/null
+++ b/drawings/appsec_achitecture/db_scheme.txt
@@ -0,0 +1,101 @@
+// Use DBML to define your database structure
+// Docs: https://dbml.dbdiagram.io/docs
+
+Table meta {
+ id uuid [pk, unique, not null]
+ system_code varchar(50) [not null, ref: > system.code]
+ tool uuid [ref: > tool.id]
+ practice varchar(32) [not null]
+ build varchar(250) [not null]
+ enviroment varchar(250) [not null]
+ library varchar(50)
+ method varchar(10)
+ hash varchar(500) [not null]
+ created_at datetime [not null]
+}
+
+Table tool {
+ id uuid [pk, unique, not null]
+ tool varchar(50) [not null]
+ practive varchar(20) [not null]
+}
+
+Table problem {
+ id uuid [pk, unique, not null]
+ executor uuid [ref: > user.id]
+ is_created_manually bool
+ status varchar(32) [not null]
+ status_updated_at datetime [not null]
+ resolution varchar(32)
+ priority varchar(32) [not null]
+ description varchar(500)
+ remediation varchar(500)
+ сategory varchar(250)
+ cve varchar(50)
+ cwe varchar(500)
+ cvss int
+ location varchar(500) [not null]
+ defect_id uuid
+ defect_status varchar(32)
+ created_at datetime [not null]
+ exception_date datetime
+ category varchar(250)
+ hash varchar(500) [not null]
+ creator uuid [ref: > user.id]
+ version int [not null]
+ group_id uuid [ref: > problem_group.id ]
+
+ meta uuid [not null, ref: > meta.id]
+}
+
+Table user {
+ id uuid [pk, unique, not null]
+ login varchar(100) [not null]
+ is_active bool
+}
+
+Table problem_group {
+ id uuid [pk, unique, not null]
+ name varchar(50) [not null]
+ description varchar(300)
+}
+
+Table system {
+ id uuid [pk, unique, not null]
+ name varchar(50) [not null]
+ code varchar(50) [not null]
+ buiseness_critical bool
+ security_critical bool
+ is_active bool
+
+ indexes {
+ id [pk]
+ code
+ }
+}
+
+Table user_to_system {
+ system_id uuid [not null, ref: > system.id]
+ user_id uuid [not null, ref: > user.id]
+ indexes {
+ (system_id, user_id) [pk, unique]
+ }
+}
+
+Table comment {
+ id uuid [pk, not null]
+ problem_id uuid [not null, ref: > problem.id]
+ description varchar(500) [not null]
+ created_by uuid [not null, ref: > user.id]
+ created_at datetime [not null]
+}
+
+Table work_history {
+ id uuid [pk, not null]
+ problem_id uuid [not null, ref: > problem.id]
+ action varchar(100)
+ old_value varchar(100)
+ new_value varchar(100)
+ user_id uuid [not null, ref: > user.id]
+ created_at datetime [not null]
+}
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/domain/aggregates/problem_meta_group.puml b/drawings/appsec_achitecture/domain/aggregates/problem_meta_group.puml
new file mode 100644
index 0000000..13a0e6d
--- /dev/null
+++ b/drawings/appsec_achitecture/domain/aggregates/problem_meta_group.puml
@@ -0,0 +1,23 @@
+@startuml problem_meta_group
+
+!include ../models/problem.puml
+!include ../models/meta.puml
+!include ../models/problem_group.puml
+
+package Domain {
+
+ package Aggregates {
+ struct ProblemMetaGroupAggregate {
+ Problem Problem
+ Meta Meta
+ Groups []Group
+ }
+ }
+
+}
+
+ProblemMetaGroupAggregate o-- Problem
+ProblemMetaGroupAggregate o-- Meta
+ProblemMetaGroupAggregate o-- Group
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/domain/aggregates/problem_meta_group_detail.puml b/drawings/appsec_achitecture/domain/aggregates/problem_meta_group_detail.puml
new file mode 100644
index 0000000..70ec02f
--- /dev/null
+++ b/drawings/appsec_achitecture/domain/aggregates/problem_meta_group_detail.puml
@@ -0,0 +1,7 @@
+@startuml problem_meta_group_deatail
+
+!include problem_meta_group.puml
+!include ../models/problem_detail.puml
+!include ../models/meta_detail.puml
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/domain/aggregates/problem_meta_report.puml b/drawings/appsec_achitecture/domain/aggregates/problem_meta_report.puml
new file mode 100644
index 0000000..5468e98
--- /dev/null
+++ b/drawings/appsec_achitecture/domain/aggregates/problem_meta_report.puml
@@ -0,0 +1,24 @@
+@startuml problem_meta_aggregat
+
+!include ../models/problem.puml
+!include ../models/meta.puml
+
+package Domain {
+
+ package Aggregates {
+ struct ProblemMetaReportAggregate {
+ Problem Problem
+ Meta Meta
+ }
+
+ ProblemMetaReportAggregate o-- Problem
+ ProblemMetaReportAggregate o-- Meta
+
+ note "Используется при разборе\nотчетов для передачи\nв Issue Processor" as ProblemMetaReportAggregateNote
+
+ ProblemMetaReportAggregateNote -- ProblemMetaReportAggregate
+ }
+
+}
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/domain/aggregates/problem_meta_report_details.puml b/drawings/appsec_achitecture/domain/aggregates/problem_meta_report_details.puml
new file mode 100644
index 0000000..a26b2b6
--- /dev/null
+++ b/drawings/appsec_achitecture/domain/aggregates/problem_meta_report_details.puml
@@ -0,0 +1,7 @@
+@startuml problem_meta_aggregat_detail
+
+!include problem_meta_report.puml
+!include ../models/problem_detail.puml
+!include ../models/meta_detail.puml
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/domain/models/enums.puml b/drawings/appsec_achitecture/domain/models/enums.puml
new file mode 100644
index 0000000..b3dc88f
--- /dev/null
+++ b/drawings/appsec_achitecture/domain/models/enums.puml
@@ -0,0 +1,60 @@
+@startuml enums
+
+package Domain {
+
+ package Models {
+ enum Practice {
+ BCA
+ DAST
+ MAST
+ OSA
+ SAST
+ SCA
+ }
+
+ enum HTTPMethod {
+ GET
+ POST
+ PUT
+ OPTIONS
+ }
+
+ enum Status {
+ Created
+ Approving
+ Open
+ Closed
+ InProcess
+ Postponed
+ }
+
+ enum Resolution {
+ None
+ FalsePositive
+ Confirmed
+ Fixed
+ Exception
+ }
+
+ enum Priority {
+ NotDefined
+ Low
+ Medium
+ High
+ Critical
+ }
+
+ enum DefectStatus {
+ Created
+ Open
+ Analysis
+ Correction
+ Testing
+ Postponed
+ Closed
+ }
+
+ }
+}
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/domain/models/meta.puml b/drawings/appsec_achitecture/domain/models/meta.puml
new file mode 100644
index 0000000..caec419
--- /dev/null
+++ b/drawings/appsec_achitecture/domain/models/meta.puml
@@ -0,0 +1,22 @@
+@startuml meta
+
+package Domain {
+ package Models {
+
+ struct Meta {
+ Id uuid.UUID
+ SystemCode string
+ ToolCode string
+ Practice string
+ Build string
+ Enviroment string
+ Library string
+ Method string
+ Hash string
+ CreatedAt time.Time
+ }
+
+ }
+}
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/domain/models/meta_detail.puml b/drawings/appsec_achitecture/domain/models/meta_detail.puml
new file mode 100644
index 0000000..48aecf5
--- /dev/null
+++ b/drawings/appsec_achitecture/domain/models/meta_detail.puml
@@ -0,0 +1,16 @@
+@startuml meta_detail
+
+!include enums.puml
+!include meta.puml
+!include system.puml
+
+Meta o-- Practice
+Meta o-- HTTPMethod
+
+Meta o-- System
+
+note "Содержит общую информацию\nдля несколькоих ПБ" as MetaNote
+
+MetaNote -- Meta
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/domain/models/problem.puml b/drawings/appsec_achitecture/domain/models/problem.puml
new file mode 100644
index 0000000..0150183
--- /dev/null
+++ b/drawings/appsec_achitecture/domain/models/problem.puml
@@ -0,0 +1,37 @@
+@startuml problem
+
+package Domain {
+
+ package Models {
+ struct Problem {
+ Id uuid.UUID
+ Executor User
+ IsCreatedManually bool
+ Status string
+ StatusUpdatedAt time.Time
+ Resolution string
+ Priority string
+ Description string
+ Remedation string
+ Category string
+ CVE string
+ CWE string
+ CVSS string
+ Location string
+ DefectNumber int
+ DefectStatus string
+ PlannedFixingAt time.Time
+ CreatedAt time.Time
+ ExceptionDate time.Time
+ Category string
+ Hash string
+ Creator User
+ Version int
+ Meta Meta
+ }
+ }
+
+
+}
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/domain/models/problem_detail.puml b/drawings/appsec_achitecture/domain/models/problem_detail.puml
new file mode 100644
index 0000000..cbca44c
--- /dev/null
+++ b/drawings/appsec_achitecture/domain/models/problem_detail.puml
@@ -0,0 +1,16 @@
+@startuml problem_detail
+
+!include enums.puml
+!include problem.puml
+!include meta.puml
+
+Problem o-- Practice
+Problem o-- HTTPMethod
+Problem o-- Status
+Problem o-- Resolution
+Problem o-- Priority
+Problem o-- DefectStatus
+
+Problem o-- Meta
+
+@enduml
diff --git a/drawings/appsec_achitecture/domain/models/problem_group.puml b/drawings/appsec_achitecture/domain/models/problem_group.puml
new file mode 100644
index 0000000..786097a
--- /dev/null
+++ b/drawings/appsec_achitecture/domain/models/problem_group.puml
@@ -0,0 +1,18 @@
+@startuml problem_group
+
+package Domain {
+
+ package Models{
+
+ struct Group {
+ Id uuid.UUID
+ Name string
+ Description string
+ CreatedBy User
+ }
+
+ }
+
+}
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/domain/models/problem_group_detail.puml b/drawings/appsec_achitecture/domain/models/problem_group_detail.puml
new file mode 100644
index 0000000..7f36215
--- /dev/null
+++ b/drawings/appsec_achitecture/domain/models/problem_group_detail.puml
@@ -0,0 +1,10 @@
+@startuml problem_group_detail
+
+!include problem_group.puml
+!include problem_detail.puml
+!include user_detail.puml
+
+Group o-- Problem
+Group o-- User
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/domain/models/system.puml b/drawings/appsec_achitecture/domain/models/system.puml
new file mode 100644
index 0000000..9788fb6
--- /dev/null
+++ b/drawings/appsec_achitecture/domain/models/system.puml
@@ -0,0 +1,18 @@
+@startuml system
+
+package Domain {
+
+ package Models {
+ struct System {
+ Code string
+ Name string
+ BuisenessCritical bool
+ SecurityCritical bool
+ Area string
+ IsActive bool
+ }
+ }
+
+}
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/domain/models/user.puml b/drawings/appsec_achitecture/domain/models/user.puml
new file mode 100644
index 0000000..f5136bb
--- /dev/null
+++ b/drawings/appsec_achitecture/domain/models/user.puml
@@ -0,0 +1,14 @@
+@startuml user
+
+package Domain {
+
+ package Models {
+ struct User {
+ Login string
+ IsActive bool
+ }
+ }
+
+}
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/domain/models/user_detail.puml b/drawings/appsec_achitecture/domain/models/user_detail.puml
new file mode 100644
index 0000000..62c4899
--- /dev/null
+++ b/drawings/appsec_achitecture/domain/models/user_detail.puml
@@ -0,0 +1,16 @@
+@startuml user_detail
+
+!include user.puml
+
+package Domain {
+ package Models {
+
+ note "Внешняя связь к\nСфера Доступы и Роли" as UserExternalNote
+
+ UserExternalNote .. User
+
+ }
+}
+
+
+@enduml
diff --git a/drawings/appsec_achitecture/issue_processor.puml b/drawings/appsec_achitecture/issue_processor.puml
new file mode 100644
index 0000000..b174299
--- /dev/null
+++ b/drawings/appsec_achitecture/issue_processor.puml
@@ -0,0 +1,5 @@
+@startuml issueprocessor
+
+!include repository/user_repo_detail.puml
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/report_parser/report_parser.puml b/drawings/appsec_achitecture/report_parser/report_parser.puml
new file mode 100644
index 0000000..f7485e0
--- /dev/null
+++ b/drawings/appsec_achitecture/report_parser/report_parser.puml
@@ -0,0 +1,53 @@
+@startuml repoerparser
+
+!include ../domain/aggregates/problem_meta_report_details.puml
+
+package ReportParser {
+ interface Parser {
+ + ReadReport(reader io.Reader) ([]ProblemMetaReportAggregate, error)
+ }
+
+ class CodeScoringParser
+ class KasperskyParser
+ class StingrayParser
+ class ZapParser
+ class PTParser
+ class SolarParser
+
+ Parser <|.. CodeScoringParser
+ Parser <|.. KasperskyParser
+ Parser <|.. StingrayParser
+ Parser <|.. ZapParser
+ Parser <|.. PTParser
+ Parser <|.. SolarParser
+
+ Parser o-- ProblemMetaReportAggregate
+}
+
+package Sender {
+
+ interface ProblemSender {
+ + SendProblem(problem ProblemMetaReportAggregate) error
+ + SendProblems(problems []ProblemMetaReportAggregate) error
+ }
+
+ class KafkaSender {
+ + Address string
+ }
+
+ ProblemSender <|.. KafkaSender
+ ProblemSender o-- ProblemMetaReportAggregate
+}
+
+
+class ReportParserService{
+ + SetParser(parser Praser)
+ + SetSender(sender ProblemSender)
+ + MetricsHandler(ResponseWriter, *Request)
+ + HealthCheckHandler(ResponseWriter, *Request)
+}
+
+ReportParserService o-- Parser
+ReportParserService o-- ProblemSender
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/repository/getter.puml b/drawings/appsec_achitecture/repository/getter.puml
new file mode 100644
index 0000000..636caed
--- /dev/null
+++ b/drawings/appsec_achitecture/repository/getter.puml
@@ -0,0 +1,13 @@
+@startuml getter
+
+package Repo {
+
+ struct GetOptions {
+ Page int
+ PerPage int
+ Sorting map[string]interface{}
+ Filters map[string]interface{}
+ }
+}
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/repository/getter_detail.puml b/drawings/appsec_achitecture/repository/getter_detail.puml
new file mode 100644
index 0000000..ecdee13
--- /dev/null
+++ b/drawings/appsec_achitecture/repository/getter_detail.puml
@@ -0,0 +1,9 @@
+@startuml getter_detail
+
+!include getter.puml
+
+note "Используется для пагинации\nсортировки и\nфильтрации результатов" as GetterNote
+
+GetOptions .. GetterNote
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/repository/postgres/postgres.puml b/drawings/appsec_achitecture/repository/postgres/postgres.puml
new file mode 100644
index 0000000..e69f5d6
--- /dev/null
+++ b/drawings/appsec_achitecture/repository/postgres/postgres.puml
@@ -0,0 +1,13 @@
+@startuml pustgres_repo_base
+
+package Repo {
+ package Postgres {
+ class PostgresRepo {
+ + Connect(ctx context.Context, connectionString string) error
+ + Ping(ctx context.Context) error
+ - db *sql.DB
+ }
+ }
+}
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/repository/repository.puml b/drawings/appsec_achitecture/repository/repository.puml
new file mode 100644
index 0000000..1b9cd67
--- /dev/null
+++ b/drawings/appsec_achitecture/repository/repository.puml
@@ -0,0 +1,8 @@
+@startuml repository
+
+!include getter.puml
+!include system_repo.puml
+!include user_repo.puml
+!include user_system_repo.puml
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/repository/repository_detail.puml b/drawings/appsec_achitecture/repository/repository_detail.puml
new file mode 100644
index 0000000..61e6f5c
--- /dev/null
+++ b/drawings/appsec_achitecture/repository/repository_detail.puml
@@ -0,0 +1,8 @@
+@startuml repository_detail
+
+!include getter_detail.puml
+!include system_repo_detail.puml
+!include user_repo_detail.puml
+!include user_system_repo_detail.puml
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/repository/system_repo.puml b/drawings/appsec_achitecture/repository/system_repo.puml
new file mode 100644
index 0000000..f8c80d4
--- /dev/null
+++ b/drawings/appsec_achitecture/repository/system_repo.puml
@@ -0,0 +1,21 @@
+@startuml system_repo
+
+!include postgres/postgres.puml
+
+package Repo {
+
+ interface SystemRepository{
+ AddSystem(ctx context.Context, system domain.Models.System) (domain.Models.System, error)
+ GetSystemByCode(ctx context.Context, code string) (domain.Models.System, error)
+ GetSystems(ctx context.Context, options GetOptions) ([]domain.Models.System, error)
+ UpdateSystem(ctx context.Context, system domain.Models.System)(domain.Modesl.System, error)
+ DeleteSystem(ctx context.Context, system domain.Models.System)error
+ }
+
+ class PostgresSystemRepository
+
+ SystemRepository <|-- PostgresSystemRepository
+ PostgresRepo <|-- PostgresSystemRepository
+}
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/repository/system_repo_detail.puml b/drawings/appsec_achitecture/repository/system_repo_detail.puml
new file mode 100644
index 0000000..006d761
--- /dev/null
+++ b/drawings/appsec_achitecture/repository/system_repo_detail.puml
@@ -0,0 +1,10 @@
+@startuml systemrepo_detail
+
+!include system_repo.puml
+!include ../domain/models/system.puml
+!include getter_detail.puml
+
+SystemRepository o-- GetOptions
+SystemRepository o-- System
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/repository/user_repo.puml b/drawings/appsec_achitecture/repository/user_repo.puml
new file mode 100644
index 0000000..2e459b7
--- /dev/null
+++ b/drawings/appsec_achitecture/repository/user_repo.puml
@@ -0,0 +1,22 @@
+@startuml user_repo
+
+!include postgres/postgres.puml
+
+package Repo {
+
+ interface UserRepository {
+ GetUserByLogin(ctx context.Context, login string) (domain.Models.User, error)
+ AddUser(ctx context.Context, user domain.Models.User) (domain.Models.User, error)
+ ChangeUser(ctx context.Conext, user domain.Models.User) (domain.Models.User, error)
+ GetUsers(ctx context.Context, options GetOptions) ([]domain.Models.User, error)
+ Deleteuser(ctx context.Context, login string) error
+ }
+
+ class PostgresUserRepository
+
+ UserRepository <|-- PostgresUserRepository
+ PostgresRepo <|-- PostgresUserRepository
+}
+
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/repository/user_repo_detail.puml b/drawings/appsec_achitecture/repository/user_repo_detail.puml
new file mode 100644
index 0000000..d58c63f
--- /dev/null
+++ b/drawings/appsec_achitecture/repository/user_repo_detail.puml
@@ -0,0 +1,12 @@
+@startuml user_repo_detail
+
+!include user_repo.puml
+!include ../domain/models/user_detail.puml
+!include getter_detail.puml
+
+package Repo {
+ UserRepository o-- User
+ UserRepository o-- GetOptions
+}
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/repository/user_system_repo.puml b/drawings/appsec_achitecture/repository/user_system_repo.puml
new file mode 100644
index 0000000..4b18fc9
--- /dev/null
+++ b/drawings/appsec_achitecture/repository/user_system_repo.puml
@@ -0,0 +1,25 @@
+@startuml usersystem_repo
+
+!include postgres/postgres.puml
+
+package Repo {
+ interface UserSystemRepository{
+ GetSystemUsers(ctx context.Context, system_code string) ([]UserSystemAggregate, error)
+ AddUserToSystem(ctx context.Context, system_code string, user domain.Models.User) error
+ RemoceUserFromSystem(ctx context.Context, system_code string, user domain.Models.User) error
+ }
+
+ struct UserSystemAggregate {
+ System domain.Models.System
+ Users []domain.Models.User
+ }
+
+ UserSystemRepository o-- UserSystemAggregate
+
+ class UserSystemPostgresRepo
+
+ UserSystemRepository <|-- UserSystemPostgresRepo
+ PostgresRepo <|-- UserSystemPostgresRepo
+}
+
+@enduml
\ No newline at end of file
diff --git a/drawings/appsec_achitecture/repository/user_system_repo_detail.puml b/drawings/appsec_achitecture/repository/user_system_repo_detail.puml
new file mode 100644
index 0000000..3be3fc1
--- /dev/null
+++ b/drawings/appsec_achitecture/repository/user_system_repo_detail.puml
@@ -0,0 +1,10 @@
+@startuml usersystem_repo_detail
+
+!include user_system_repo.puml
+!include ../domain/models/user_detail.puml
+!include ../domain/models/system.puml
+
+UserSystemAggregate o-- System
+UserSystemAggregate o-- User
+
+@enduml
\ No newline at end of file
diff --git a/drawings/cisco asa/policies_serialization.wsd b/drawings/cisco asa/policies_serialization.wsd
new file mode 100644
index 0000000..6bc18c4
--- /dev/null
+++ b/drawings/cisco asa/policies_serialization.wsd
@@ -0,0 +1,34 @@
+@startuml
+!define RESULT result
+!define UNPARSED_RESULT unparsed_result
+
+start
+:Получаем данные, обработанные\nTextFSM со списком правил ACL acl_entries;
+:Создаем два результирующих массива:
+- RESULT для хранения хороших результатов
+- UNPARSED_RESULT для хранения необработанных;
+:Начинаем итерацию по acl_entries;
+repeat
+ :Берем следующий элемент из acl_entries - acl_entry;
+ :Проверяем его содержание и в зависимости от\nнего обрабатываем соответственно;
+ if (acl_entry = ACL header)
+ :Пропускам элемент;
+ elseif (acl_entry = unparsed ACE)
+ :Записываем в список UNPARSED_RESULT;
+ elseif (acl_entry = ACE)
+ :Обрабатываем правило;
+ note
+ _parse_remark_acl_entry()
+ end note
+ :Добавляем обработанный результат в results;
+ elseif (acl_entry = Remark)
+ :Обрабатываем согласно правилам\nработы c Remark;
+ note
+ _parse_ace_acl_entry()
+ end note
+ :Добавляем обработанный результат в results;
+ endif
+repeat while (В acl_entries есть еще элементы?)
+:Возвращаем RESULT, UNPARSED_RESULT;
+stop
+@enduml
diff --git a/drawings/cisco asa/policies_serialization_results_parsing.wsd b/drawings/cisco asa/policies_serialization_results_parsing.wsd
new file mode 100644
index 0000000..b15976b
--- /dev/null
+++ b/drawings/cisco asa/policies_serialization_results_parsing.wsd
@@ -0,0 +1,52 @@
+@startuml
+!define RESULT result
+!define CONCAT_RESULTS concat_results
+!define TMP_ENTRY tmp_entry
+
+start
+:Начинаем проходить по элементам RESULT;
+:Создаем массив CONCAT_RESULTS;
+:Создаем словарь TMP_ENTRY\nв которм будет собираться правило\nпо шаблону ace_template;
+note
+ace_template = {
+ "rule_id": 0,
+ "enabled": True,
+ "rule_numbers": [],
+ "action": "",
+ "source": [],
+ "destination": [],
+ "destination_service": "",
+ "source_service": "",
+ "hit_count": 0,
+ "users": [],
+ "logging": "",
+ "logging_interval": "",
+ "time_range": "",
+ "description": "",
+ "raw_entry": "",
+ "raw_entries": [],
+ "hash": "",
+ "protocol": "",
+ }
+endnote
+repeat
+ :Берем следующий элемент RESULT;
+ if (RESULT entry = ACE)
+ :Записываем в поля TMP_ENTRY данные из RESULT entry
+ согласно правилам ace;
+ note
+ _fill_template_with_ace_data()
+ endnote
+ :Добавяем TMP_ENTRY в CONCAT_RESULTS;
+ :Сбрасываем ace_template в исходное значение;
+ elseif (RESULT = remark)
+ :Записываем в поля TMP_ENTRY данные из RESULT entry
+ согласно правилам remark;
+ note right
+ _fill_template_with_remark_data()
+ endnote
+ endif
+repeat while (В RESULT есть еще элементы?)
+:Возвращаем CONCAT_RESULTS;
+stop
+@enduml
diff --git a/drawings/cisco asa/test.wsd b/drawings/cisco asa/test.wsd
new file mode 100644
index 0000000..e3ef546
--- /dev/null
+++ b/drawings/cisco asa/test.wsd
@@ -0,0 +1,12 @@
+@startuml
+start
+:Берем значение поля destination из нераскрытого правила;
+:Проходимся его значением по списку network objects;
+if (Находится объект с таким именем?) then (да)
+ :Поля сервиса ставятся на место поля destination в раскрытом списке правил;
+ end
+else (нет)
+ :В раскрытом списке правил ставится значение, которое было изначально;
+ end
+endif
+@enduml
\ No newline at end of file
diff --git a/drawings/cisco_ftd/cisco_model.puml b/drawings/cisco_ftd/cisco_model.puml
new file mode 100644
index 0000000..a0a5abe
--- /dev/null
+++ b/drawings/cisco_ftd/cisco_model.puml
@@ -0,0 +1,16 @@
+@startuml
+
+class Cisco << (M,#FF7700) Model>> {
+ cisco_type : CharField
+ connection_type : CharField
+ current_context : CharField
+ enable_password : CharField
+ multiple_mode : BooleanField
+ password : CharField
+ port : PositiveIntegerField
+ protocol : CharField
+ rsa_limit : IntegerField
+ user : CharField
+}
+
+@enduml
\ No newline at end of file
diff --git a/drawings/cisco_ftd/create_strategy.puml b/drawings/cisco_ftd/create_strategy.puml
new file mode 100644
index 0000000..39b7d03
--- /dev/null
+++ b/drawings/cisco_ftd/create_strategy.puml
@@ -0,0 +1,84 @@
+@startuml
+struct CiscoCreateData {
+ + ip: str
+ + login: str
+ + password: str
+ + port: str = DEFAULT_SSH_PORT
+ + device_name: str
+ + device_protocol: str
+ + manufacturer: str = CISCO_ASA_MANUFACTURER
+}
+
+struct CiscoAuthenticationCheckDataPyModel {
+ + ip: str
+ + manufacturer: NOT NEEDED - SET CISCO
+ + login: str
+ + password: str
+ + port: int
+ + device_name: str
+}
+
+
+package CiscoApp {
+ class AsaBackendService {
+ + {static} create_cisco_asa_insatnce(\n name: str,\n ip: str,\n user: str,\n password: str,\n enable_password: str,\n connection_type: Optional[str] = CONNECTION_CLI_TYPE,\n protocol: Optional[str] = CONNECTION_SSH_PROTOCOL,\n rsa_limit: Optional[int] = 0,\n port: Optional[str] = DEFAULT_ASA_PORT,\n description: Optional[str] = "",\n administrators: Optional[list] = None\n)
+ }
+ AsaBackendService --> CiscoASAUnifiedStrategy : "Использование статического\nметода create_cisco_asa_instance"
+
+ class CiscoFTDRepository {
+ + {static} create_instance(create_data: Dict)
+ }
+ CiscoFTDRepository --> CiscoFTDUnifiedStrategy : "Использование статического\nметода create_instance"
+
+ class CiscoFTDCreateDataModel {
+ name: str
+ ip: str
+ username: str
+ password: str
+ connection_type: str = CONNECTION_CLI_TYPE
+ port: int = DEFAULT_FTD_PORT
+ description: str = ""
+ administrators: List[int] = []
+ }
+ CiscoFTDCreateDataModel --> CiscoFTDRepository : "Pydantic model\nдля валидации create_data"
+
+ abstract CiscoUnifiedStrategyABC{
+ + create_instance(cisco_create_data: Dict)
+ + check_authentication_status(cisco_connect_data: Dict)
+ }
+
+
+ class CiscoFTDUnifiedStrategy {
+ + create_instance(cisco_create_data: Dict)
+ + check_authentication_status(cisco_connect_data: Dict)
+ }
+ CiscoFTDUnifiedStrategy ..|> CiscoUnifiedStrategyABC
+
+ class CiscoASAUnifiedStrategy {
+ + create_instance(cisco_create_data: Dict)
+ + check_authentication_status(cisco_connect_data: Dict)
+ }
+ CiscoASAUnifiedStrategy ..|> CiscoUnifiedStrategyABC
+
+ class CiscoUnifiedManager {
+ + cisco_create_strategy: CiscoCreateStrategyABC
+ + create_cisco_instance(cisco_create_data: Dict)
+ + check_authentication(cisco_connect_data: Dict)
+ }
+ CiscoUnifiedStrategyABC --* CiscoUnifiedManager
+ CiscoUnifiedManager --* .PingServices.FirewallAuthStatusService
+}
+
+package PingServices {
+ class FirewallAuthStatusService {
+ + manufacturer: str
+ + ip: str
+ + login: str
+ + password: str
+ + port: str
+ + device_name: Optional[str]
+ + device_protocol: Optional[str]
+ }
+}
+
+@enduml
\ No newline at end of file
diff --git a/drawings/cisco_ftd/ftd_backend_service.puml b/drawings/cisco_ftd/ftd_backend_service.puml
new file mode 100644
index 0000000..2831c98
--- /dev/null
+++ b/drawings/cisco_ftd/ftd_backend_service.puml
@@ -0,0 +1,20 @@
+@startuml ftd_backend_service
+
+!includesub ./ftd_model.puml!CiscoFTDModel
+
+!startsub FTDBackendService
+class CiscoFTDBackendService {
++ ftd_instance: CiscoFTD
++ set_ftd_status(status_to_set: str) -> CiscoFTD
++ form_cache_prefix() -> str
++ flush_cache()
++ set_cache_update_mutex()
++ get_cache_update_mutex() -> str
++ free_cache_update_mutex()
+# _check_connection(**kwargs)
+}
+!endsub
+
+CiscoFTD --o CiscoFTDBackendService
+
+@enduml
\ No newline at end of file
diff --git a/drawings/cisco_ftd/ftd_main.puml b/drawings/cisco_ftd/ftd_main.puml
new file mode 100644
index 0000000..e638d73
--- /dev/null
+++ b/drawings/cisco_ftd/ftd_main.puml
@@ -0,0 +1,14 @@
+@startuml main
+
+!includesub ./ftd_backend_service.puml!FTDBackendService
+!include ./ftd_model.puml
+!includesub ./ftd_repository.puml!CiscoFTDRepository
+!includesub ./ftd_operation_performers.puml!CISCOFTDSSHOPERATIONFACTORY
+!includesub ./ftd_operation_performers.puml!CISCOFTDCACHEOPERATIONFACTORY
+
+CiscoFTDBackendService o-- CiscoFTD
+CiscoFTDSSHOperationFactory o-- CiscoFTD
+CiscoFTDCacheOperationFactory o-- CiscoFTD
+CiscoFTDRepository o-- CiscoFTD
+
+@enduml
\ No newline at end of file
diff --git a/drawings/cisco_ftd/ftd_model.puml b/drawings/cisco_ftd/ftd_model.puml
new file mode 100644
index 0000000..6878c94
--- /dev/null
+++ b/drawings/cisco_ftd/ftd_model.puml
@@ -0,0 +1,34 @@
+@startuml CiscoFTD
+
+!include ./model_firewall.puml
+
+!startsub CiscoFTDModel
+class CiscoFTD << (M,#FF7700) Model>> {
+ + username: CharField
+ + password: CharField
+ + protocol : CharField [FTDProtocolChoices]
+ + port : IntField
+ + active_node : ForeignKey
+ + administrators : ManyToManyField
+ + cluster : BooleanField
+ + cluster_data : JSONField
+ + description : CharField
+ + group : ForeignKey
+ + ip : CharField
+ + last_status_change : DateTimeField
+ + manufacturer : CharField
+ + name : CharField
+ + objects
+ + passive_node : ForeignKey
+ + status : CharField
+}
+!endsub
+
+enum FTDProtocolChoices {
+ SSH: "ssh"
+}
+
+CiscoFTD <-- FTDProtocolChoices
+CiscoFTD --|> Firewall
+
+@enduml
\ No newline at end of file
diff --git a/drawings/cisco_ftd/ftd_operation_performers.puml b/drawings/cisco_ftd/ftd_operation_performers.puml
new file mode 100644
index 0000000..296e41c
--- /dev/null
+++ b/drawings/cisco_ftd/ftd_operation_performers.puml
@@ -0,0 +1,39 @@
+@startuml
+
+!includesub ./ftd_model.puml!CiscoFTDModel
+!include ./ftd_ssh_strategy.puml
+
+interface CiscoFTDFactoryInterfaces {
+ + perform_request()
+}
+
+!startsub CISCOFTDSSHOPERATIONFACTORY
+class CiscoFTDSSHOperationFactory {
+ + ftd_instance: CiscoFTD
+ + request_data: Dict
+ + perform_request()
+ + @property\nftd_connect_data() -> Dict
+ # _parse_client_data(client_data: Dict) -> Dict
+ # _parse_ftd_response(ftd_response: str) -> Dict
+ # _prepare_operation() -> CiscoFTDSSHOperation
+}
+!endsub
+
+!startsub CISCOFTDCACHEOPERATIONFACTORY
+class CiscoFTDCacheOperationFactory {
+ + ftd_instance: CiscoFTD
+ + request_data: Dict
+ + perform_request()
+ # _get_config() -> str
+}
+!endsub
+
+CiscoFTD --o CiscoFTDCacheOperationFactory
+CiscoFTD --o CiscoFTDSSHOperationFactory
+
+CiscoFTDSSHOperationFactory ..|> CiscoFTDFactoryInterfaces
+CiscoFTDCacheOperationFactory ..|> CiscoFTDFactoryInterfaces
+
+CiscoFTDSSHOperationFactory *-- CiscoFTDSSHOperation
+
+@enduml
\ No newline at end of file
diff --git a/drawings/cisco_ftd/ftd_pydantic.puml b/drawings/cisco_ftd/ftd_pydantic.puml
new file mode 100644
index 0000000..0ec393a
--- /dev/null
+++ b/drawings/cisco_ftd/ftd_pydantic.puml
@@ -0,0 +1,38 @@
+@startuml
+
+!startsub CISCO_FTD_PYDANTIC_CHECK_CONNECTION_DATA
+struct CiscoFTDAuthenticationModel <<(P,#fc0373) Pydantic Model>> {
+ + host: str
+ + username: str
+ + password: str
+ + port: Optional[str] = 22
+}
+!endsub
+
+struct CiscoFTDSSHOperationCommandModel <<(P,#fc0373) Pydantic Model>> {
+ + command: str
+ + result: Union[str, List[Any], Dict[str, Any]] = ""
+}
+
+!startsub CISCO_FTD_PYDANTIC_SSH_COMMANDS_LIST
+struct CiscoFTDSSHOperationCommandsListModel <<(P,#fc0373) Pydantic Model>> {
+ + commands: List[CiscoFTDSSHOperationCommand]
+}
+!endsub
+
+!startsub CISCO_FTD_PYDANTIC_CREATE_DATA_MODEL
+struct CiscoFTDCreateDataModel <<(P,#fc0373) Pydantic Model>> {
+ name: str
+ ip: str
+ username: str
+ password: str
+ connection_type: str = CONNECTION_CLI_TYPE
+ port: int = DEFAULT_FTD_PORT
+ description: str = ""
+ administrators: List[int] = []
+}
+!endsub
+
+CiscoFTDSSHOperationCommandModel ..> CiscoFTDSSHOperationCommandsListModel
+
+@enduml
\ No newline at end of file
diff --git a/drawings/cisco_ftd/ftd_repository.puml b/drawings/cisco_ftd/ftd_repository.puml
new file mode 100644
index 0000000..e32e062
--- /dev/null
+++ b/drawings/cisco_ftd/ftd_repository.puml
@@ -0,0 +1,21 @@
+@startuml ftd_repository
+
+!includesub ./ftd_model.puml!CiscoFTDModel
+!includesub ./ftd_pydantic.puml!CISCO_FTD_PYDANTIC_CHECK_CONNECTION_DATA
+!includesub ./ftd_pydantic.puml!CISCO_FTD_PYDANTIC_CREATE_DATA_MODEL
+
+!startsub CiscoFTDRepository
+class CiscoFTDRepository {
+ + ftd_instance: CiscoFTD
+ + {static} create_instance(**kwargs)
+ + update_instance(**kwargs)
+ + delete_instance()
+}
+!endsub
+
+CiscoFTDRepository o-- CiscoFTD
+CiscoFTDRepository --> CiscoFTDAuthenticationModel
+CiscoFTDRepository --> CiscoFTDCreateDataModel
+CiscoFTDAuthenticationModel .. CiscoFTDCreateDataModel
+
+@enduml
diff --git a/drawings/cisco_ftd/ftd_ssh_strategy.puml b/drawings/cisco_ftd/ftd_ssh_strategy.puml
new file mode 100644
index 0000000..7aadf9e
--- /dev/null
+++ b/drawings/cisco_ftd/ftd_ssh_strategy.puml
@@ -0,0 +1,16 @@
+@startuml
+
+!includesub ./ftd_pydantic.puml!CISCO_FTD_PYDANTIC_SSH_COMMANDS_LIST
+!includesub ./ftd_pydantic.puml!CISCO_FTD_PYDANTIC_CHECK_CONNECTION_DATA
+
+class CiscoFTDSSHOperation {
+ + connect_data: Dict
+ + commands: Dict
+ + request_data: Dict
+ + perform_operation()
+}
+
+CiscoFTDSSHOperation --> CiscoFTDAuthenticationModel
+CiscoFTDSSHOperation --> CiscoFTDSSHOperationCommandsListModel
+
+@enduml
\ No newline at end of file
diff --git a/drawings/cisco_ftd/model_firewall.puml b/drawings/cisco_ftd/model_firewall.puml
new file mode 100644
index 0000000..da8cace
--- /dev/null
+++ b/drawings/cisco_ftd/model_firewall.puml
@@ -0,0 +1,17 @@
+@startuml
+ class Firewall << (M,#FF7700) Model>> {
+ active_node : ForeignKey
+ administrators : ManyToManyField
+ cluster : BooleanField
+ cluster_data : JSONField
+ description : CharField
+ group : ForeignKey
+ ip : CharField
+ last_status_change : DateTimeField
+ manufacturer : CharField
+ name : CharField
+ objects
+ passive_node : ForeignKey
+ status : CharField
+ }
+@enduml
\ No newline at end of file
diff --git a/drawings/request_center/block_schemes/add_field.puml b/drawings/request_center/block_schemes/add_field.puml
new file mode 100644
index 0000000..d745965
--- /dev/null
+++ b/drawings/request_center/block_schemes/add_field.puml
@@ -0,0 +1,20 @@
+@startuml
+start
+:Добавить новое поле
+на этап запроса;
+if (Поле блочное) then (yes)
+ :Выбор типа блочного поля;
+ :Указание параметров, уникальных
+ для выбранного блочного поля;
+else (no)
+ :Указываем название поля;
+ :Указываем обязательное ли поле;
+ :Указываем дополнительные параметры;
+ if (Тип поля in\n[multiselct, select]) then (yes)
+ :Выбираем источник данных;
+ else (no)
+ endif
+endif
+ :Добавление поля в этап;
+end
+@enduml
diff --git a/drawings/request_center/scheme.puml b/drawings/request_center/scheme.puml
new file mode 100644
index 0000000..5388f53
--- /dev/null
+++ b/drawings/request_center/scheme.puml
@@ -0,0 +1,115 @@
+@startuml
+
+!theme plain
+hide empty methods
+
+!procedure $table($name, $slug)
+entity "$name" as $slug << (T, Orange) table >>
+!endprocedure
+
+!procedure $type($name, $slug)
+entity "$name" as $slug << (E, Cyan) type (enum) >>
+!endprocedure
+
+!procedure $pk($name)
+<&key> $name:
+!endprocedure
+
+!procedure $enum_link($name)
+<&tag> $name:
+!endprocedure
+
+!procedure $fk($name)
+<&key> $name:
+!endprocedure
+
+!procedure $column($name)
+{field} <&chevron-right> $name:
+!endprocedure
+
+!procedure $enum_field($name)
+{field} <&chevron-right> $name
+!endprocedure
+
+
+$table("FIELD", "field") {
+ $pk("ID") INTEGER NOT NULL
+ $enum_link("TYPE") VARCHAR
+ $fk("STEP_ID") INTEGER NOT NULL
+ $fk("BLOCK_FIELD_ID") INTEGER NOT NULL
+ $column("REQUIRED") BOOLEAN
+}
+
+$table("BLOCK_FIELD", "block_field") {
+ $pk("ID") INTEGER NOT NULL
+ $fk("STEP_ID") INTEGER NOT NULL
+ $column("NAME") VARCHAR
+ $enum_link("TYPE") VARCHAR NOT NULL
+ $column("REQUIRED") BOOLEAN
+ $column("FLAGS") JSON
+}
+
+$table("STEP", "step") {
+ $pk("ID") INTEGER NOT NULL
+ $fk("WORKFLOW_ID") INTEGER NOT NULL
+ $column("NAME") VARCHAR
+ $column("DESCRIPTION") TEXT
+ $column("NEED_AGREEMENT") BOOLEAN
+}
+
+$table("RESPONSIBLE", "responsible") {
+ $pk("ID") INTEGER NOT NULL
+ $fk("STEP_ID") INTEGER NOT NULL
+ $column("ASSIGNATION_TYPE") VARCHAR
+ $column("EXECUTION_TYPE") VARCHAR
+ $column("USERS") INTEGER[]
+}
+
+$table("WORKFLOW", "workflow") {
+ $pk("ID") INTEGER NOT NULL
+ $column("NAME") VARCHAR
+ $column("CREATED_AT") TIMESTAMP
+ $enum_link("TYPE") VARCHAR
+ $enum_link("STATUS") VARCHAR
+ $column("DESCRIPTION") TEXT
+}
+
+$type("FIELD_TYPE", "field_type") {
+ $enum_field("select")
+ $enum_field("input")
+ $enum_field("datetime")
+ $enum_field("multiselect")
+ $enum_field("filefield")
+ $enum_field("blockfield")
+}
+
+$type("BLOCK_FIELD_TYPE", "block_field_type") {
+ $enum_field("allow_access_field")
+ $enum_field("object")
+ $enum_field("device")
+}
+
+$type("WORKFLOW_TYPE", "workflow_type") {
+ $enum_field("general")
+ $enum_field("access_change")
+ $enum_field("object_change")
+ $enum_field("custom")
+}
+
+$type("WORKFLOW_STATUS", "workflow_status") {
+ $enum_field("active")
+ $enum_field("inactive")
+ $enum_field("draft")
+}
+
+field::TYPE -- field_type
+field::BLOCK_FIELD_ID }o--|| block_field::ID
+workflow::TYPE -- workflow_type
+workflow::STATUS -- workflow_status
+field::STEP }o--|| step::ID
+block_field::STEP }o--|| step::ID
+block_field::TYPE -- block_field_type
+step::WORKFLOW_ID }|--|| workflow::ID
+responsible::STEP_ID ||--|| step::ID
+
+@enduml
\ No newline at end of file