add docs #1

Merged
VLADIMIR merged 2 commits from add_docs into master 2026-08-19 17:15:26 +00:00
8 changed files with 99 additions and 100 deletions
Showing only changes of commit 268b359576 - Show all commits
+3 -3
View File
@@ -41,9 +41,9 @@ make test
## Документация и юридические документы
- [`docs/TERMS.md`](docs/TERMS.md) — Пользовательское соглашение (оферта); раздаётся сервером по постоянному URL `/terms`;
- [`docs/PRIVACY.md`](docs/PRIVACY.md) — Политика конфиденциальности и обработки персональных данных (152-ФЗ); раздаётся сервером по постоянному URL `/privacy`;
- [`docs/CONSENT.md`](docs/CONSENT.md) — текст согласия на обработку ПДн для формы регистрации (URL `/consent`);
- [`docs/TERMS.md`](docs/TERMS.md) — Пользовательское соглашение (оферта); раздаётся сервером по постоянному URL `/api/terms`;
- [`docs/PRIVACY.md`](docs/PRIVACY.md) — Политика конфиденциальности и обработки персональных данных (152-ФЗ); раздаётся сервером по постоянному URL `/api/privacy`;
- [`docs/CONSENT.md`](docs/CONSENT.md) — текст согласия на обработку ПДн для формы регистрации (URL `/api/consent`);
- [`docs/COMPLIANCE.md`](docs/COMPLIANCE.md) — чек-лист приведения сервиса в соответствие с документами.
Юридические эндпоинты:
+3 -3
View File
@@ -128,7 +128,7 @@ service EveningDetectiveServer {
rpc GetTerms(GetTermsReq) returns (GetTermsRsp) {
option (google.api.http) = {
get: "/terms"
get: "/api/terms"
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
tags : "Документы";
@@ -138,7 +138,7 @@ service EveningDetectiveServer {
rpc GetPrivacy(GetPrivacyReq) returns (GetPrivacyRsp) {
option (google.api.http) = {
get: "/privacy"
get: "/api/privacy"
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
tags : "Документы";
@@ -148,7 +148,7 @@ service EveningDetectiveServer {
rpc GetConsent(GetConsentReq) returns (GetConsentRsp) {
option (google.api.http) = {
get: "/consent"
get: "/api/consent"
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
tags : "Документы";
+69 -69
View File
@@ -215,6 +215,29 @@
]
}
},
"/api/consent": {
"get": {
"summary": "Получить текст Согласия на обработку персональных данных",
"operationId": "EveningDetectiveServer_GetConsent",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/evening_detective_serverGetConsentRsp"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"tags": [
"Документы"
]
}
},
"/api/files/upload": {
"post": {
"summary": "Загрузить файл",
@@ -656,6 +679,29 @@
]
}
},
"/api/privacy": {
"get": {
"summary": "Получить текст Политики конфиденциальности",
"operationId": "EveningDetectiveServer_GetPrivacy",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/evening_detective_serverGetPrivacyRsp"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"tags": [
"Документы"
]
}
},
"/api/scenario": {
"post": {
"summary": "Создать сценарий",
@@ -1286,6 +1332,29 @@
]
}
},
"/api/terms": {
"get": {
"summary": "Получить текст Пользовательского соглашения (оферты)",
"operationId": "EveningDetectiveServer_GetTerms",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/evening_detective_serverGetTermsRsp"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"tags": [
"Документы"
]
}
},
"/api/test/echo": {
"post": {
"summary": "Проверить обработку данных",
@@ -1530,75 +1599,6 @@
"Пользователи"
]
}
},
"/consent": {
"get": {
"summary": "Получить текст согласия на обработку персональных данных",
"operationId": "EveningDetectiveServer_GetConsent",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/evening_detective_serverGetConsentRsp"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"tags": [
"Документы"
]
}
},
"/privacy": {
"get": {
"summary": "Получить текст Политики конфиденциальности",
"operationId": "EveningDetectiveServer_GetPrivacy",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/evening_detective_serverGetPrivacyRsp"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"tags": [
"Документы"
]
}
},
"/terms": {
"get": {
"summary": "Получить текст Пользовательского соглашения (оферты)",
"operationId": "EveningDetectiveServer_GetTerms",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/evening_detective_serverGetTermsRsp"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/rpcStatus"
}
}
},
"tags": [
"Документы"
]
}
}
},
"definitions": {
+2 -2
View File
@@ -15,7 +15,7 @@
| 1.1 | Пользовательское соглашение (оферта) | ✅ | `docs/TERMS.md` — заполнить плейсхолдеры, утвердить у юриста |
| 1.2 | Политика конфиденциальности (152-ФЗ) | ✅ | `docs/PRIVACY.md` — заполнить плейсхолдеры, утвердить у юриста |
| 1.3 | Текст согласия на обработку ПДн | ✅ | `docs/CONSENT.md` — встроить в форму регистрации |
| 1.4 | Публикация документов на сайте по постоянным URL | ✅ | RPC `GetTerms`/`GetPrivacy`/`GetConsent` (`api/main.proto`, пути `/terms`, `/privacy`, `/consent`); текст встраивается из `docs/embed.go`; подставить реальные домены в тексты документов |
| 1.4 | Публикация документов на сайте по постоянным URL | ✅ | RPC `GetTerms`/`GetPrivacy`/`GetConsent` (`api/main.proto`, пути `/api/terms`, `/api/privacy`, `/api/consent`); текст встраивается из `docs/embed.go`; подставить реальные домены в тексты документов |
## 2. Акцепт соглашений при регистрации (ст. 428 ГК РФ, ст. 9 152-ФЗ)
@@ -116,7 +116,7 @@
## Порядок действий перед запуском в прод
1. Заполнить плейсхолдеры в `docs/TERMS.md`, `docs/PRIVACY.md`, `docs/CONSENT.md` и утвердить у юриста.
2. Вставить в тексты документов реальные домены (`/terms`, `/privacy`, `/consent`); вставить чекбоксы акцепта, подтверждение отчуждения прав при публикации сценария и кнопку «Удалить аккаунт» во фронтенд.
2. Вставить в тексты документов реальные домены (`/api/terms`, `/api/privacy`, `/api/consent`); вставить чекбоксы акцепта, подтверждение отчуждения прав при публикации сценария и кнопку «Удалить аккаунт» во фронтенд.
3. Подать уведомление в Роскомнадзор (п. 4.2) до начала обработки.
4. Проверить локализацию: БД, S3, SMTP — в РФ.
5. Прогнать `goose up` на staging; добавить интеграционный тест (п. 8.3) — включая сценарий: публикация → удаление запрещено; удаление аккаунта → сценарий остаётся с `author: null`.
+3 -3
View File
@@ -99,7 +99,7 @@ func (s *server) DeleteAccount(ctx context.Context, req *proto.DeleteAccountReq)
}
// GetTerms возвращает текст Пользовательского соглашения (постоянный URL
// /terms, на который ссылается форма регистрации при акцепте).
// /api/terms, на который ссылается форма регистрации при акцепте).
func (s *server) GetTerms(_ context.Context, _ *proto.GetTermsReq) (*proto.GetTermsRsp, error) {
text, err := docs.FS.ReadFile("TERMS.md")
if err != nil {
@@ -109,7 +109,7 @@ func (s *server) GetTerms(_ context.Context, _ *proto.GetTermsReq) (*proto.GetTe
}
// GetPrivacy возвращает текст Политики конфиденциальности (постоянный URL
// /privacy).
// /api/privacy).
func (s *server) GetPrivacy(_ context.Context, _ *proto.GetPrivacyReq) (*proto.GetPrivacyRsp, error) {
text, err := docs.FS.ReadFile("PRIVACY.md")
if err != nil {
@@ -119,7 +119,7 @@ func (s *server) GetPrivacy(_ context.Context, _ *proto.GetPrivacyReq) (*proto.G
}
// GetConsent возвращает текст согласия на обработку персональных данных
// (постоянный URL /consent).
// (постоянный URL /api/consent).
func (s *server) GetConsent(_ context.Context, _ *proto.GetConsentReq) (*proto.GetConsentRsp, error) {
text, err := docs.FS.ReadFile("CONSENT.md")
if err != nil {
+1 -1
View File
@@ -19,7 +19,7 @@ import (
)
// Версии документов, акцепт которых фиксируется. Должны совпадать с
// редакциями, опубликованными по постоянным URL (/terms и /privacy,
// редакциями, опубликованными по постоянным URL (/api/terms и /api/privacy,
// rpc GetTerms/GetPrivacy, текст встраивается из пакета docs): при изменении
// текста документа версия ОБЯЗАНА увеличиваться, иначе повторный акцепт
// не будет зафиксирован как согласие с новой редакцией
+9 -10
View File
@@ -5331,7 +5331,7 @@ const file_main_proto_rawDesc = "" +
"\x17DeleteLastTeamActionReq\x12\x0e\n" +
"\x02id\x18\x01 \x01(\x03R\x02id\"/\n" +
"\x17DeleteLastTeamActionRsp\x12\x14\n" +
"\x05error\x18\x01 \x01(\tR\x05error2\xc8O\n" +
"\x05error\x18\x01 \x01(\tR\x05error2\xd4O\n" +
"\x16EveningDetectiveServer\x12\xa6\x01\n" +
"\x04Ping\x12'.crabs.evening_detective_server.PingReq\x1a'.crabs.evening_detective_server.PingRsp\"L\x92A3\x12)Проверить доступностьb\x06\n" +
"\x04\n" +
@@ -5356,17 +5356,16 @@ const file_main_proto_rawDesc = "" +
"\x04\n" +
"\x00\x12\x00\x82\xd3\xe4\x93\x02\x16:\x01*\"\x11/api/auth/refresh\x12\xe3\x04\n" +
"\rDeleteAccount\x120.crabs.evening_detective_server.DeleteAccountReq\x1a0.crabs.evening_detective_server.DeleteAccountRsp\"\xed\x03\x92A\xc9\x03\n" +
"\"Регистрация и вход\x12SУдалить учётную запись и персональные данные\x1a\xcd\x02Удаляет учётную запись и персональные данные текущего пользователя (ст. 21 152-ФЗ). Требует заголовок X-Password с паролем учётной записи (подтверждение владельца; пароль не передаётся в URL).\x82\xd3\xe4\x93\x02\x1a*\x18/api/auth/delete-account\x12\xf0\x01\n" +
"\bGetTerms\x12+.crabs.evening_detective_server.GetTermsReq\x1a+.crabs.evening_detective_server.GetTermsRsp\"\x89\x01\x92Ax\n" +
"\x12Документы\x12bПолучить текст Пользовательского соглашения (оферты)\x82\xd3\xe4\x93\x02\b\x12\x06/terms\x12\xe6\x01\n" +
"\"Регистрация и вход\x12SУдалить учётную запись и персональные данные\x1a\xcd\x02Удаляет учётную запись и персональные данные текущего пользователя (ст. 21 152-ФЗ). Требует заголовок X-Password с паролем учётной записи (подтверждение владельца; пароль не передаётся в URL).\x82\xd3\xe4\x93\x02\x1a*\x18/api/auth/delete-account\x12\xf4\x01\n" +
"\bGetTerms\x12+.crabs.evening_detective_server.GetTermsReq\x1a+.crabs.evening_detective_server.GetTermsRsp\"\x8d\x01\x92Ax\n" +
"\x12Документы\x12bПолучить текст Пользовательского соглашения (оферты)\x82\xd3\xe4\x93\x02\f\x12\n" +
"/api/terms\x12\xea\x01\n" +
"\n" +
"GetPrivacy\x12-.crabs.evening_detective_server.GetPrivacyReq\x1a-.crabs.evening_detective_server.GetPrivacyRsp\"z\x92Ag\n" +
"\x12Документы\x12QПолучить текст Политики конфиденциальности\x82\xd3\xe4\x93\x02\n" +
"\x12\b/privacy\x12\x81\x02\n" +
"GetPrivacy\x12-.crabs.evening_detective_server.GetPrivacyReq\x1a-.crabs.evening_detective_server.GetPrivacyRsp\"~\x92Ag\n" +
"\x12Документы\x12QПолучить текст Политики конфиденциальности\x82\xd3\xe4\x93\x02\x0e\x12\f/api/privacy\x12\x85\x02\n" +
"\n" +
"GetConsent\x12-.crabs.evening_detective_server.GetConsentReq\x1a-.crabs.evening_detective_server.GetConsentRsp\"\x94\x01\x92A\x80\x01\n" +
"\x12Документы\x12jПолучить текст согласия на обработку персональных данных\x82\xd3\xe4\x93\x02\n" +
"\x12\b/consent\x12\xcb\x01\n" +
"GetConsent\x12-.crabs.evening_detective_server.GetConsentReq\x1a-.crabs.evening_detective_server.GetConsentRsp\"\x98\x01\x92A\x80\x01\n" +
"\x12Документы\x12jПолучить текст Согласия на обработку персональных данных\x82\xd3\xe4\x93\x02\x0e\x12\f/api/consent\x12\xcb\x01\n" +
"\bGetUsers\x12+.crabs.evening_detective_server.GetUsersReq\x1a+.crabs.evening_detective_server.GetUsersRsp\"e\x92AP\n" +
"\x18Пользователи\x124Получить всех пользователей\x82\xd3\xe4\x93\x02\f\x12\n" +
"/api/users\x12\xd6\x01\n" +
+9 -9
View File
@@ -1864,7 +1864,7 @@ func RegisterEveningDetectiveServerHandlerServer(ctx context.Context, mux *runti
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/crabs.evening_detective_server.EveningDetectiveServer/GetTerms", runtime.WithHTTPPathPattern("/terms"))
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/crabs.evening_detective_server.EveningDetectiveServer/GetTerms", runtime.WithHTTPPathPattern("/api/terms"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
@@ -1884,7 +1884,7 @@ func RegisterEveningDetectiveServerHandlerServer(ctx context.Context, mux *runti
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/crabs.evening_detective_server.EveningDetectiveServer/GetPrivacy", runtime.WithHTTPPathPattern("/privacy"))
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/crabs.evening_detective_server.EveningDetectiveServer/GetPrivacy", runtime.WithHTTPPathPattern("/api/privacy"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
@@ -1904,7 +1904,7 @@ func RegisterEveningDetectiveServerHandlerServer(ctx context.Context, mux *runti
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/crabs.evening_detective_server.EveningDetectiveServer/GetConsent", runtime.WithHTTPPathPattern("/consent"))
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/crabs.evening_detective_server.EveningDetectiveServer/GetConsent", runtime.WithHTTPPathPattern("/api/consent"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
@@ -2821,7 +2821,7 @@ func RegisterEveningDetectiveServerHandlerClient(ctx context.Context, mux *runti
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/crabs.evening_detective_server.EveningDetectiveServer/GetTerms", runtime.WithHTTPPathPattern("/terms"))
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/crabs.evening_detective_server.EveningDetectiveServer/GetTerms", runtime.WithHTTPPathPattern("/api/terms"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
@@ -2838,7 +2838,7 @@ func RegisterEveningDetectiveServerHandlerClient(ctx context.Context, mux *runti
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/crabs.evening_detective_server.EveningDetectiveServer/GetPrivacy", runtime.WithHTTPPathPattern("/privacy"))
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/crabs.evening_detective_server.EveningDetectiveServer/GetPrivacy", runtime.WithHTTPPathPattern("/api/privacy"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
@@ -2855,7 +2855,7 @@ func RegisterEveningDetectiveServerHandlerClient(ctx context.Context, mux *runti
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/crabs.evening_detective_server.EveningDetectiveServer/GetConsent", runtime.WithHTTPPathPattern("/consent"))
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/crabs.evening_detective_server.EveningDetectiveServer/GetConsent", runtime.WithHTTPPathPattern("/api/consent"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
@@ -3508,9 +3508,9 @@ var (
pattern_EveningDetectiveServer_Login_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "auth", "login"}, ""))
pattern_EveningDetectiveServer_Refresh_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "auth", "refresh"}, ""))
pattern_EveningDetectiveServer_DeleteAccount_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "auth", "delete-account"}, ""))
pattern_EveningDetectiveServer_GetTerms_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"terms"}, ""))
pattern_EveningDetectiveServer_GetPrivacy_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"privacy"}, ""))
pattern_EveningDetectiveServer_GetConsent_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"consent"}, ""))
pattern_EveningDetectiveServer_GetTerms_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"api", "terms"}, ""))
pattern_EveningDetectiveServer_GetPrivacy_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"api", "privacy"}, ""))
pattern_EveningDetectiveServer_GetConsent_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"api", "consent"}, ""))
pattern_EveningDetectiveServer_GetUsers_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"api", "users"}, ""))
pattern_EveningDetectiveServer_GetUserById_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"api", "users", "id"}, ""))
pattern_EveningDetectiveServer_GetMe_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "users", "me"}, ""))