artifacty 0.15.0 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ko.md CHANGED
@@ -312,7 +312,7 @@ ARTIFACTY_HOME=/path/to/shared/store artifacty serve
312
312
 
313
313
  현재 브라우저 서버 URL은 `server.json`에 기록합니다. 서버가 다른 포트를 선택하더라도 MCP 도구는 이 URL을 사용해 올바른 링크를 반환합니다. 기존 `index.json` 저장소는 처음 접근할 때 자동으로 마이그레이션합니다.
314
314
 
315
- 모든 아티팩트 레코드에는 `visibility`(`private`/`team`, 기본값 `team`)와 `ownerUserId`가 있습니다. 마이그레이션할 때는 `publisherUserId`로 소유자 정보를 채웁니다. 적용되는 접근 규칙은 아래 보안 모델 절을 참고하세요.
315
+ 모든 아티팩트 레코드에는 `visibility`(`private`/`team`/`public`, 기본값 `team`)와 `ownerUserId`가 있습니다. 마이그레이션할 때는 `publisherUserId`로 소유자 정보를 채웁니다. 적용되는 접근 규칙은 아래 보안 모델 절을 참고하세요.
316
316
 
317
317
  관리자는 `/admin/backup`에서 백업을 내려받거나 복원할 수 있습니다. 기본 `artifacts` 범위에는 아티팩트 메타데이터와 버전 내용이 들어가며, 사용자·세션·API 토큰 레코드·감사 로그는 포함하지 않습니다. 이 범위의 번들을 복원하면 대상 서버의 아티팩트 레코드를 교체하고 참조되지 않는 버전 파일을 정리합니다. 사용자, 토큰, 감사 이력은 그대로 둡니다.
318
318
 
@@ -385,8 +385,26 @@ artifacty unlink <from-id> derived-from <to-id>
385
385
  ```
386
386
 
387
387
 
388
+ ### 개인 설정 자동 적용
389
+
390
+ 언어와 페이지당 표시 개수는 선택 즉시 적용됩니다. 대시보드 상세 필터는 선택을 바꾸거나 입력 후 다른 곳으로 이동하면 적용됩니다. 검색어는 Enter 또는 검색 버튼으로 실행합니다. 권한·서버 설정·아티팩트 본문 변경은 저장 버튼을 유지합니다. JavaScript를 사용할 수 없으면 적용 버튼이 표시됩니다.
391
+
388
392
  ### 댓글과 리뷰 상태
389
393
 
394
+ 검토 상태는 팀이 아티팩트를 검토했는지, 수정이 필요한지 기록하는 선택 기능입니다. 예를 들어 AI가 만든 배포 계획을 `pending`으로 표시하고, 수정이 필요하면 `changes-requested`, 검토를 마치면 `approved`로 표시할 수 있습니다. 개인 메모처럼 검토가 필요 없는 자료는 기본값인 `none`으로 두면 됩니다.
395
+
396
+ | 상태 | 용도 |
397
+ | --- | --- |
398
+ | `none` | 검토 상태를 지정하지 않음. 기본값입니다. |
399
+ | `pending` | 검토를 기다리는 자료 |
400
+ | `changes-requested` | 수정이 필요한 자료 |
401
+ | `approved` | 검토 후 승인한 자료 |
402
+
403
+ 사용자 계정이 있으면 아티팩트 소유자 또는 관리자만 상태를 바꿀 수 있습니다. 상태는 대시보드 필터와 저장된 뷰에 사용할 수 있습니다. 순서대로 단계를 거쳐야 하는 승인 절차는 아니며, 공개 범위·읽기 권한·수정 권한을 바꾸거나 게시를 막지 않습니다. 댓글을 해결해도 자동으로 승인되지는 않습니다.
404
+
405
+ 승인 후 새 버전을 추가하면 다시 검토하도록 `pending`으로 돌아갑니다. 보존 정책의 **자동 아카이브**는 `approved` 자료를 제외합니다. 승인이 수동 삭제나 모든 보존 작업을 막는 것은 아닙니다.
406
+
407
+
390
408
  새 버전이나 별도 리뷰 아티팩트를 만들지 않고 특정 버전에 피드백을 남길 수 있습니다.
391
409
 
392
410
  - 댓글은 아티팩트와 같은 안전한 Markdown 렌더러를 사용하며, 댓글당 최대 16 KB입니다. 선택 사항인 `anchor`는 표시 위치의 힌트입니다. 텍스트에는 `{ line: 42 }`, JSON/SARIF에는 `{ path: "$.runs[0].results[3]" }`, CSV에는 `{ row: 7 }`을 사용할 수 있습니다. 힌트가 실제 내용과 일치하는지는 검증하지 않습니다.
@@ -438,6 +456,8 @@ ARTIFACTY_RETENTION_ALLOW_PURGE=true artifacty retention run --allow-purge
438
456
  ```
439
457
 
440
458
 
459
+ 보존 정책 화면은 아티팩트 보관·영구 삭제, 이력 제한, 보호 태그를 구분해 표시합니다. 정리를 실행하기 전에 미리보기를 검토하세요.
460
+
441
461
  ### 대시보드 필터와 저장된 뷰
442
462
 
443
463
  `listArtifactsPage`와 이를 사용하는 `/` 대시보드, `GET /api/artifacts`, `artifacty list`, `artifacty_list`는 `q`/`tag`/`sourceAgent`/`relatedTo`/`relation`/`includeArchived` 외에도 다음 필터를 지원합니다.
@@ -543,7 +563,9 @@ curl -s http://127.0.0.1:8787/api/import \
543
563
  ```
544
564
 
545
565
 
546
- 데스크톱에서는 왼쪽 탐색 메뉴를 사용하세요. 화면이 좁으면 **메뉴**를 펼치세요. **아티팩트**와 **알림함**에서 작업을 확인하고, **새로 만들기**와 **가져오기**로 콘텐츠를 추가합니다. 관리자는 **관리**에서 접근 관리(`/admin/access`), 사용자(`/admin/users`), 백업(`/admin/backup`), 보존 정책(`/admin/retention`), Webhook(`/admin/webhooks`), 서버 업데이트(`/admin/update`)를 엽니다. **계정**에는 계정 및 API 토큰(`/account`), 비밀번호 변경(`/account/password`), 로그아웃이 있습니다. API 문서와 언어 선택도 탐색 메뉴에 있습니다.
566
+ 데스크톱에서는 왼쪽 탐색 메뉴를 사용하세요. 접기 버튼을 누르면 아이콘만 표시하며, 브라우저는 이 선택을 `artifacty_sidebar`에 저장합니다. 화면이 좁으면 **메뉴**를 펼치세요. **아티팩트**와 **알림함**에서 작업을 확인하고, **새로 만들기**와 **가져오기**로 콘텐츠를 추가합니다. 관리자는 **관리**에서 접근 관리(`/admin/access`), 사용자(`/admin/users`), 백업(`/admin/backup`), 보존 정책(`/admin/retention`), Webhook(`/admin/webhooks`), 서버 업데이트(`/admin/update`)를 엽니다. **계정**에는 계정 및 API 토큰(`/account`), 비밀번호 변경(`/account/password`), 로그아웃이 있습니다. API 문서와 언어 선택도 탐색 메뉴에 있습니다.
567
+
568
+ 하단 페이지 탐색에서 페이지당 10, 25, 50, 100개를 선택할 수 있습니다. 기본값은 50개입니다. 크기를 바꾸면 첫 페이지로 돌아가며 필터와 언어는 유지합니다.
547
569
 
548
570
  브라우저 관련 경로는 다음과 같습니다.
549
571
 
@@ -558,7 +580,7 @@ curl -s http://127.0.0.1:8787/api/import \
558
580
  - `/api/admin/backup?scope=artifacts|full`: 관리자 전용 백업 JSON 다운로드입니다.
559
581
  - `/api/admin/backup/import`: 관리자 전용 백업 복원입니다. 원본 번들 또는 `{ bundle, confirm, forceUsers }`를 받습니다.
560
582
  - `/api/audit`: 감사 이벤트를 조회합니다.
561
- - `/openapi.json`: 모든 `/api/*` 경로와 `/mcp`를 다루는 OpenAPI 3.1 명세입니다. `/docs/api`는 같은 경로의 참고 문서를 서버에서 렌더링합니다. 둘 다 인증 없이 볼 수 있습니다.
583
+ - `/openapi.json`: 모든 `/api/*` 경로와 `/mcp`를 다루는 OpenAPI 3.1 명세입니다. `/docs/api`는 같은 경로의 참고 문서를 서버에서 렌더링합니다. 둘 다 인증 없이 볼 수 있습니다. API 참조는 펼칠 수 있는 영역으로 엔드포인트를 묶고 검색, 요청·응답 예제, OpenAPI에서 생성한 복사용 curl 명령어를 제공합니다. 읽기 전용 안내이며 실제 요청을 보내는 “Try it” 기능은 없습니다. 대시보드와 같은 브라우저 테마 설정을 사용합니다.
562
584
 
563
585
  목록 API는 `limit`, `offset` 페이지네이션을 지원합니다. 응답은 최상위 `artifacts` 배열을 유지하며 `pagination`, `search` 메타데이터를 포함합니다.
564
586
 
@@ -592,9 +614,29 @@ curl -s http://127.0.0.1:8787/api/artifacts/<id> \
592
614
 
593
615
  브라우저 편집기는 숨겨진 `expectedVersion` 필드를 보냅니다. 다른 에이전트가 먼저 수정했다면 충돌 안내와 diff 보기 링크를 표시합니다.
594
616
 
617
+ ## 사용자 관리와 이메일
618
+
619
+ 관리자는 `/admin/users`의 사용자 행에서 역할을 변경할 수 있습니다. 마지막 활성 관리자는 일반 사용자로 변경할 수 없습니다. 관리자에서 일반 사용자로 바꾸면 기존 토큰의 `admin` 범위가 남아 있어도 실제 관리자 접근 권한을 유지하지 못합니다.
620
+
621
+ 비밀번호를 재설정하면 임시 비밀번호를 만들고 다음 로그인 때 변경하도록 합니다. 세션은 폐기하지만 API 토큰은 현재 권한에 따라 계속 사용할 수 있습니다. 선택적인 재설정 이메일은 `/admin/email`에서 설정하세요. 자세한 내용은 [SMTP와 비밀번호 재설정](docs/ko/smtp.md)을 참고하세요. `secrets/smtp.key`는 JSON 백업이나 업그레이드 스냅샷에 포함하지 않으므로 별도로 백업하세요.
622
+
623
+ ### 아티팩트 공개 범위
624
+
625
+ 퍼블릭 서버 모드에서는 `public` 아티팩트를 로그인 없이 읽을 수 있지만 수정할 수는 없습니다. `team`은 인증이 필요하며, `private`은 소유자와 관리자만 접근합니다. 프라이빗 서버 모드에서는 명시적인 공유 규칙을 적용합니다. `public`이나 `team`을 선택해도 익명 접근을 허용하지 않습니다. 기본값은 계속 `team`입니다. 기존 팀 아티팩트도 더 이상 익명으로 조회할 수 없습니다. 익명 조회가 목적이라면 `public`을 명시적으로 선택하세요.
626
+
627
+ 접근 미리보기는 설정을 저장하지 않고 익명의 읽기 전용 접근을 보여줍니다. 미리보기 결과는 접근 정책을 변경하지 않습니다.
628
+
595
629
  ## 화면 언어
596
630
 
597
- 브라우저 UI의 기본 언어는 영어입니다. `http://127.0.0.1:8787/new?lang=ko`처럼 브라우저 경로에 `?lang=ko`를 추가하면 한국어를 사용합니다. 폼과 앱 내부 링크는 선택한 언어를 유지합니다. 영문 가이드를 기본으로 제공하며, 한국어 가이드는 [문서 안내](docs/ko/README.md)에서 찾을 수 있습니다. 영어·한국어 문서는 [문서 작성 가이드](docs/ko/writing-style.md)를 따릅니다. 한국어는 자연스러운 어순과 표현을 사용합니다.
631
+ 영어와 한국어는 기본 제공 언어입니다. 관리자는 **관리 → 언어 관리**(`/admin/languages`)에서 설치된 언어를 활성화하고 기본 언어를 선택합니다. 같은 화면에서 사용자 JSON 팩을 가져오거나 템플릿을 내려받을 수 있습니다. 선택 메뉴에는 언어의 고유 이름을 표시합니다. 일부만 번역한 팩은 빠진 문구를 영어로 표시합니다. 검증 규칙, 제한, 백업 동작은 [언어 팩](docs/ko/language-packs.md)을 참고하세요.
632
+
633
+ 브라우저는 직접 지정한 `?lang=<locale>`, 1년간 유지하는 언어 쿠키, 저장한 관리자 기본 언어 순으로 활성화된 언어를 선택합니다. 비활성화된 선택은 무시합니다. 설정을 저장하기 전에는 `ARTIFACTY_LOCALE=en` 또는 `ko`가 초기 기본값이며, 지정하지 않으면 영어를 사용합니다. `Accept-Language`는 무시합니다. 활성화된 영어를 직접 선택하면 한국어 설정보다 우선합니다. 해당 브라우저의 쿠키를 지우면 현재 기본 언어로 돌아갑니다.
634
+
635
+ 탐색 메뉴, 인증, 계정, 관리 화면, 백업, 버전 복구, CSV·SARIF 조작 화면을 번역합니다. 명령어, API·MCP 식별자, 저장된 아티팩트 내용은 바꾸지 않습니다. 안내 문서는 [영어](docs/README.md)와 [한국어](docs/ko/README.md)로 제공합니다.
636
+
637
+ 모니터, 해, 달 버튼으로 시스템, 밝게, 어둡게 테마를 선택합니다. 각 아이콘에는 접근 가능한 이름이 있습니다. 브라우저는 선택을 `artifacty_theme`에 저장합니다. 시스템은 운영체제의 설정을 따릅니다.
638
+
639
+ UI 조작 요소는 Bootstrap 5.3.8의 폼, 버튼, 버튼 그룹만 선택해 컴파일하고 Tabler 3.49 아이콘을 사용합니다. CDN 없이 로컬 자산을 제공합니다. Bootstrap, Tabler, Sass는 개발 의존성입니다. 생성한 자산을 다시 만들려면 `npm run build:ui`를 사용하세요. 애플리케이션은 서버 렌더링 UI를 유지합니다.
598
640
 
599
641
  스키마와 저장소의 주요 사항은 다음과 같습니다.
600
642
 
@@ -616,7 +658,7 @@ curl -s http://127.0.0.1:8787/api/artifacts/<id> \
616
658
 
617
659
  이 기능은 SQLite 저장소를 버전 10으로 업그레이드합니다. 이전 빌드는 접근 정책을 무시하는 대신 업그레이드된 저장소를 열지 않습니다.
618
660
 
619
- 관리자는 **관리 → 접근 관리**(`/admin/access`)에서 재시작 없이 서버 접근 모드를 변경할 수 있습니다. 기존 설치의 기본값은 **퍼블릭**입니다. 팀 공개 아티팩트는 로그인 없이 대시보드에서 볼 수 있고, 비공개 아티팩트는 소유자와 관리자만 접근합니다. 퍼블릭 모드에서도 API 인증과 쓰기 보호는 적용됩니다.
661
+ 관리자는 **관리 → 접근 관리**(`/admin/access`)에서 재시작 없이 서버 접근 모드를 변경할 수 있습니다. 기존 설치의 기본값은 **퍼블릭**입니다. `public` 아티팩트는 로그인 없이 읽기 전용으로 볼 수 있으며, `team`은 인증이 필요합니다. 비공개 아티팩트는 소유자와 관리자만 접근합니다. 퍼블릭 모드에서도 API 인증과 쓰기 보호는 적용됩니다.
620
662
 
621
663
  **프라이빗** 모드에서는 브라우저 방문자가 로그인해야 합니다. 소유자·관리자 또는 직접이나 팀을 통해 권한을 받은 사용자만 아티팩트를 읽을 수 있습니다. 기존 `team` 공개 범위가 모든 사용자에게 접근을 허용하지는 않습니다. 공유 권한은 **읽기**, **댓글**, **편집**을 지원합니다. 댓글 권한은 피드백 작성과 자신의 댓글 해결을 허용하며, 편집 권한은 버전 추가도 허용합니다. 직접 부여한 권한과 팀 권한 중 가장 높은 권한이 적용됩니다. 소유권, 공유, 아카이브, 리뷰 상태 관리는 소유자와 관리자에게 남습니다. 관리자는 소유자가 없는 기존 아티팩트에도 접근해 소유자를 지정하거나 공유할 수 있습니다.
622
664
 
@@ -640,7 +682,7 @@ curl -s http://127.0.0.1:8787/api/artifacts/<id> \
640
682
 
641
683
  전체 백업에는 모드, 네트워크 설정, 팀, 구성원, 공유 권한, 알림함 항목이 포함됩니다. 확정 대기 중인 네트워크 상태와 공유 링크 토큰은 내보내지 않습니다. 아티팩트 전용 복원은 공유 권한을 복원하지 않으며, 기존 권한을 대체한다면 확인이 필요합니다. 프라이빗 서버에 전체 백업을 복원하면 백업이 퍼블릭이었더라도 프라이빗을 유지하고 기존 네트워크 정책도 보존합니다.
642
684
 
643
- 퍼블릭으로 다시 전환하면 팀 공개 아티팩트를 로그인 없이 읽을 수 있습니다. 나중에 프라이빗으로 돌아갈 때 사용할 명시적 공유 권한은 유지합니다.
685
+ 퍼블릭으로 다시 전환하면 `public` 아티팩트를 로그인 없이 읽을 수 있습니다. `team`은 계속 인증이 필요합니다. 나중에 프라이빗으로 돌아갈 때 사용할 명시적 공유 권한은 유지합니다.
644
686
 
645
687
  ## 공유 링크와 알림함
646
688
 
@@ -676,7 +718,7 @@ artifacty samples remove
676
718
  - API 토큰은 타이밍 공격에 안전한 다이제스트 비교로 검사합니다.
677
719
  - 개인 API 토큰은 `read`, `write`, `admin` 권한 범위를 지원하며 기본값은 `read`+`write`입니다. `/account`에서 생성할 때 선택합니다. `admin`은 관리자 토큰에만 부여할 수 있습니다. 각 `/api/*` 경로에는 해당 토큰 범위가 필요합니다. 공용 `ARTIFACTY_API_TOKEN`과 브라우저 세션은 전체 범위를 가집니다.
678
720
  범위 검사가 실패하면 `403`과 `code: "scope_denied"`를 반환하고 빈도를 제한한 `token-scope-denied` 감사 로그를 기록합니다. `write`가 없는 MCP 토큰의 `tools/list`에서는 쓰기 도구를 숨깁니다. 직접 호출해도 `structuredContent.code: "scope_denied"` 오류가 납니다.
679
- - 계정이 하나라도 있으면 각 아티팩트에는 `visibility`(`private` 또는 `team`, 기본값 `team`)와 `ownerUserId`가 있습니다. 퍼블릭 접근 모드의 `team`은 인증된 주체가 읽고 쓸 수 있습니다. 다만 `ARTIFACTY_TEAM_WRITE=owner`이면 쓰기는 소유자·관리자로 제한합니다. `private`은 소유자·관리자만 읽고 쓰며, 다른 사용자의 조회에는 존재 여부를 숨기기 위해 403 대신 404를 반환합니다. 아카이브, 복원, 공개 범위·소유권 변경은 공개 범위와 무관하게 소유자·관리자만 할 수 있습니다. 공용 `ARTIFACTY_API_TOKEN`이나 첫 계정 생성 전 요청에는 개인 신원이 없으며 익명 팀 주체로 처리합니다. `team`은 읽고 쓸 수 있지만 `private`은 보지 못합니다. 계정이 전혀 없는 단일 사용자 모드에서는 이 검사를 생략해 기존 공개 범위 기능 이전의 동작을 유지합니다. 공개 범위·소유권 변경에는 `POST /api/artifacts/:id/visibility`, `POST /api/artifacts/:id/owner`, CLI의 `artifacty visibility <id> private|team`, MCP의 `artifacty_set_visibility`를 사용합니다.
721
+ - 계정이 하나라도 있으면 아티팩트는 `visibility`(`public`, `team`, `private`, 기본값 `team`)와 `ownerUserId`를 사용합니다. 퍼블릭 서버 모드에서 `public`은 익명 읽기 전용 접근, `team`은 인증된 접근, `private`은 소유자·관리자 접근을 허용합니다. 쓰기와 소유자 관리 작업은 권한을 확인합니다. 프라이빗 모드에서는 명시적인 공유로 접근을 제어합니다. 제한된 조회에는 존재 여부를 숨기기 위해 404를 반환합니다. 계정이 없는 단일 사용자 모드는 별도의 로컬 동작입니다. 공개 범위·소유권 변경에는 `POST /api/artifacts/:id/visibility`, `POST /api/artifacts/:id/owner`, `artifacty visibility <id> private|team|public`, `artifacty_set_visibility`를 사용합니다.
680
722
  - HTTP와 HTTP MCP 요청은 `(token or user or remote address, bucket)` 조합(토큰·사용자·원격 주소 중 하나와 버킷)별로 고정된 1분 구간에서 횟수를 제한합니다. `write`는 변경 경로에 기본 분당 120회(`ARTIFACTY_RATE_WRITE_PER_MIN`), `auth`는 `/login`에 주소별 분당 10회(`ARTIFACTY_RATE_AUTH_PER_MIN`), `search`는 `GET /api/artifacts?q=`에 분당 300회(`ARTIFACTY_RATE_SEARCH_PER_MIN`)입니다. 루프백 바인딩에서는 `ARTIFACTY_RATE_LIMIT=always`가 없으면 비활성화하며, `ARTIFACTY_RATE_LIMIT=off`이면 항상 비활성화합니다. 한도를 넘으면 `429`, `Retry-After` 헤더, `code: "rate_limited"`를 반환하고 빈도를 제한한 `rate-limited` 감사 로그를 남깁니다.
681
723
  - localhost 외부에 바인딩하려면 `ARTIFACTY_SHARE_MODE=lan` 또는 `team`과 `ARTIFACTY_API_TOKEN`이 모두 필요합니다.
682
724
  - 외부 공유는 신뢰할 수 있는 LAN이나 VPN 세션을 위한 기능입니다. `0.0.0.0`보다 특정 인터페이스 IP를 사용하고 React 렌더링은 비활성화하세요. [네트워크 공유](docs/ko/network-sharing.md)를 참고하세요.
@@ -717,7 +759,7 @@ Artifacty가 읽는 모든 `ARTIFACTY_*` 변수를 아래에 정리했습니다.
717
759
  | `ARTIFACTY_MCP_HTTP` | `true`이면 실행 중인 서버에 HTTP MCP도 제공 | `false` |
718
760
  | `ARTIFACTY_MCP_TIMEOUT_MS` | 브리지 모드 MCP HTTP 요청 시간 제한 | `30000` |
719
761
  | `ARTIFACTY_API_TOKEN` | HTTP API와 LAN/팀 공유에 필요한 공용 토큰 | — |
720
- | `ARTIFACTY_LOCALE` | 요청이 언어를 지정하지 않을 때 사용할 UI 언어(`en`, `ko` 등) | `en` |
762
+ | `ARTIFACTY_LOCALE` | 관리자 언어 설정을 저장하기 전의 초기 UI 기본값(`en` 또는 `ko`) | `en` |
721
763
  | `ARTIFACTY_EMBEDDINGS_URL` | OpenAI 호환 임베딩 엔드포인트의 기본 URL. 의미·하이브리드 검색 활성화 | — |
722
764
  | `ARTIFACTY_EMBEDDINGS_MODEL` | 임베딩 모델 이름 | 제공자 기본값 |
723
765
  | `ARTIFACTY_EMBEDDINGS_API_KEY` | OpenAI 호환 제공자의 API 키. 로그나 저장소에 남기지 않음 | — |
package/README.md CHANGED
@@ -304,7 +304,7 @@ Artifacty stores metadata in `artifacty.sqlite`. Normal create and update operat
304
304
 
305
305
  Artifacty writes the current browser server URL to `server.json`. MCP tools use this URL to return correct links when the server selects another port. On first access, Artifacty automatically migrates existing `index.json` stores.
306
306
 
307
- Every artifact row carries a `visibility` (`private`/`team`, default `team`) and an `ownerUserId`, backfilled from the artifact's `publisherUserId` on migration. See the Security Model section below for the access rules these enforce.
307
+ Every artifact row carries a `visibility` (`private`/`team`/`public`, default `team`) and an `ownerUserId`, backfilled from the artifact's `publisherUserId` on migration. See the Security Model section below for the access rules these enforce.
308
308
 
309
309
  Administrators can download and restore backups from `/admin/backup`. The
310
310
  default `artifacts` scope contains artifact metadata and version contents,
@@ -390,8 +390,26 @@ artifacty show <artifact-id> --relations
390
390
  artifacty unlink <from-id> derived-from <to-id>
391
391
  ```
392
392
 
393
+ ### Automatic application of preferences
394
+
395
+ Language and page-size selections apply immediately. Advanced dashboard filters apply when a selection changes or an edited field loses focus. Search text still uses Enter or Search. Changes to permissions, server settings, and artifact content retain explicit save actions. If JavaScript is unavailable, the Apply buttons remain available.
396
+
393
397
  ### Comments and review status
394
398
 
399
+ Review status is optional. Use it to record whether a team has reviewed an artifact or requested changes. For example, mark an AI-generated release plan as `pending`, use `changes-requested` when it needs revision, and set `approved` after review. Leave personal notes or other material that does not need review at the default, `none`.
400
+
401
+ | Status | Purpose |
402
+ | --- | --- |
403
+ | `none` | No review status assigned. This is the default. |
404
+ | `pending` | Waiting for review |
405
+ | `changes-requested` | Needs revision |
406
+ | `approved` | Approved after review |
407
+
408
+ When user accounts exist, only the artifact owner or an administrator can change this status. Use it in dashboard filters and saved views. It does not enforce a sequence of approval steps, change visibility or read/write permissions, or block publication. Resolving comments does not automatically approve an artifact.
409
+
410
+ Appending a version after approval resets the status to `pending` for another review. The retention policy's **automatic archiving** excludes `approved` artifacts. Approval does not prevent manual deletion or all retention operations.
411
+
412
+
395
413
  Add feedback to a specific version without publishing a new version or a separate review artifact:
396
414
 
397
415
  - Comments use the same sanitized Markdown renderer as artifact content. Each comment has a 16 KB limit. The optional `anchor` field provides a display hint: `{ line: 42 }` for text, `{ path: "$.runs[0].results[3]" }` for JSON/SARIF, or `{ row: 7 }` for CSV. Artifacty does not validate the hint against the content.
@@ -440,6 +458,8 @@ artifacty retention run --dry-run
440
458
  ARTIFACTY_RETENTION_ALLOW_PURGE=true artifacty retention run --allow-purge
441
459
  ```
442
460
 
461
+ The retention screen groups artifact archive/purge settings, history limits, and protected tags. Review the preview before running cleanup.
462
+
443
463
  ### Dashboard Filters and Saved Views
444
464
 
445
465
  `listArtifactsPage` (and every surface built on it — the `/` dashboard, `GET /api/artifacts`, `artifacty list`, and `artifacty_list`) accepts these filters in addition to `q`/`tag`/`sourceAgent`/`relatedTo`/`relation`/`includeArchived`:
@@ -538,7 +558,9 @@ curl -s http://127.0.0.1:8787/api/import \
538
558
  }'
539
559
  ```
540
560
 
541
- On desktop, use the navigation rail. On narrower screens, open **Menu**. **Artifacts** and **Inbox** lead to your work; **New** and **Import** create or bring in content. Administrators use **Administration** for Access (`/admin/access`), Users (`/admin/users`), Backup (`/admin/backup`), Retention (`/admin/retention`), Webhooks (`/admin/webhooks`), and Server update (`/admin/update`). **Account** contains Account & API tokens (`/account`), password changes (`/account/password`), and sign-out. API docs and language selection are also in the navigation.
561
+ On desktop, use the navigation rail. Use its collapse button to switch to an icon rail; the browser saves this choice as `artifacty_sidebar`. On narrower screens, open **Menu**. **Artifacts** and **Inbox** lead to your work; **New** and **Import** create or bring in content. Administrators use **Administration** for Access (`/admin/access`), Users (`/admin/users`), Backup (`/admin/backup`), Retention (`/admin/retention`), Webhooks (`/admin/webhooks`), and Server update (`/admin/update`). **Account** contains Account & API tokens (`/account`), password changes (`/account/password`), and sign-out. API docs and language selection are also in the navigation.
562
+
563
+ The bottom pager offers 10, 25, 50, or 100 items per page; the default is 50. Changing the page size returns to the first page and preserves filters and language.
542
564
 
543
565
  Browser routes:
544
566
 
@@ -553,7 +575,7 @@ Browser routes:
553
575
  - `/api/admin/backup?scope=artifacts|full`: administrator-only backup JSON download.
554
576
  - `/api/admin/backup/import`: administrator-only backup restore. Accepts the raw bundle or `{ bundle, confirm, forceUsers }`.
555
577
  - `/api/audit`: list audit events.
556
- - `/openapi.json`: machine-readable OpenAPI 3.1 document for every `/api/*` route and `/mcp`; `/docs/api`: server-rendered human-readable reference for the same routes. Both require no authentication.
578
+ - `/openapi.json`: machine-readable OpenAPI 3.1 document for every `/api/*` route and `/mcp`; `/docs/api`: server-rendered human-readable reference for the same routes. Both require no authentication. The API reference groups endpoints in expandable sections, with search, request/response examples, and copyable curl commands generated from OpenAPI. It is read-only and has no live “Try it” execution. It uses the same saved browser theme as the dashboard.
557
579
 
558
580
  List APIs support pagination with `limit` and `offset`. Responses keep the top-level `artifacts` array and include `pagination` and `search` metadata:
559
581
 
@@ -584,9 +606,29 @@ If the artifact's `latestVersion` no longer matches, the update is rejected with
584
606
 
585
607
  The browser editor sends a hidden `expectedVersion` field. If another agent updated the artifact first, the editor shows a conflict banner with a link to the diff view.
586
608
 
609
+ ## User administration and email
610
+
611
+ At `/admin/users`, administrators can change a user's role inline. The last active administrator cannot be demoted. After demotion, existing tokens cannot retain effective administrator access through an old `admin` scope.
612
+
613
+ Password reset generates a temporary password, forces a change at the next login, and revokes sessions. API tokens remain valid subject to current permissions. Configure optional reset emails at `/admin/email`; see [SMTP and password reset](docs/smtp.md). Back up `secrets/smtp.key` separately: neither JSON backups nor upgrade snapshots include it.
614
+
615
+ ### Artifact visibility
616
+
617
+ In public server mode, `public` artifacts allow anonymous read-only access. `team` artifacts require authentication, and `private` artifacts remain restricted to the owner and administrators. In private server mode, explicit sharing rules apply; choosing `public` or `team` does not grant anonymous access. The default remains `team`. Existing team artifacts no longer allow anonymous browsing; select `public` explicitly if that is intended.
618
+
619
+ The Access preview shows anonymous read-only access without saving configuration. Preview results do not change the access policy.
620
+
587
621
  ## Interface Language
588
622
 
589
- The browser UI defaults to English. Add `?lang=ko` to any browser route to use Korean, for example `http://127.0.0.1:8787/new?lang=ko`. Forms and in-app links preserve the selected language. The current product guides are in English. English and Korean documentation follow the [documentation writing guide](docs/writing-style.md). Korean prose should use natural Korean phrasing.
623
+ English and Korean are built in. Administrators can enable installed languages and choose the default at **Administration → Languages** (`/admin/languages`). Import custom JSON packs or download the template there. The selector displays native language names. Partial packs use English for missing messages. See [language packs](docs/language-packs.md) for validation, limits, and backup behavior.
624
+
625
+ The browser uses enabled choices in this order: explicit `?lang=<locale>`, its one-year language cookie, then the saved administrator default. Disabled choices are ignored. Before settings are saved, `ARTIFACTY_LOCALE=en` or `ko` supplies the initial default; otherwise it is English. `Accept-Language` is ignored. Selecting enabled English explicitly overrides a Korean preference. Clearing the browser-specific cookie returns to the current default.
626
+
627
+ Translations cover navigation, authentication, accounts, administration, backup, version repair, and CSV/SARIF controls. Commands, API/MCP identifiers, and stored artifact content are unchanged. Guides are available in [English](docs/README.md) and [Korean](docs/ko/README.md).
628
+
629
+ The monitor, sun, and moon buttons select System, Light, and Dark themes. Each icon has an accessible label. The browser stores the choice as `artifacty_theme`. System follows the operating system preference.
630
+
631
+ UI controls use selectively compiled Bootstrap 5.3.8 forms, buttons, and button groups, with Tabler 3.49 icons. Assets are served locally without a CDN. Bootstrap, Tabler, and Sass are development dependencies; rebuild the generated assets with `npm run build:ui`. The application keeps its server-rendered UI.
590
632
 
591
633
  Schema and storage:
592
634
 
@@ -611,7 +653,7 @@ upgraded store rather than ignoring its access policy.
611
653
 
612
654
  Administrators can open **Administration → Access** (`/admin/access`) to change the
613
655
  server's access mode without restarting it. Existing installations default to
614
- **public** mode, preserving anonymous dashboard access to team-visible artifacts;
656
+ **public** mode. Explicitly public artifacts permit anonymous read-only access; team artifacts require authentication;
615
657
  artifacts marked private remain restricted to their owner and administrators.
616
658
  API authentication and write protection still apply in public mode.
617
659
 
@@ -669,8 +711,8 @@ they require confirmation. Restoring a full backup into a private server
669
711
  keeps it private even if the backup was public, and an existing network policy
670
712
  is preserved.
671
713
 
672
- If you switch back to public mode, anonymous visitors can read team-visible
673
- artifacts again. Artifacty retains explicit sharing grants for a later return
714
+ If you switch back to public mode, anonymous visitors can read explicitly public
715
+ artifacts. Team artifacts still require authentication. Artifacty retains explicit sharing grants for a later return
674
716
  to private mode.
675
717
 
676
718
  ## Share Links and Inbox
@@ -724,7 +766,7 @@ manuals with the intended users or teams from each artifact's Sharing page.
724
766
  - API token checks use timing-safe digest comparison.
725
767
  - Personal API tokens support `read`, `write`, and `admin` scopes. The default is `read`+`write`. Select scopes when creating a token at `/account`. Only administrator tokens can receive `admin`. Each `/api/*` route requires the matching token scope. The shared `ARTIFACTY_API_TOKEN` and browser sessions have full scopes.
726
768
  If a scope check fails, the server returns `403` with `code: "scope_denied"`. It also writes a rate-limited `token-scope-denied` audit row. For MCP tokens without `write`, `tools/list` omits tools that change data. Calls to those tools return `structuredContent.code: "scope_denied"`.
727
- - Once any user account exists, every artifact has a `visibility` (`private` or `team`, defaulting to `team`) and an `ownerUserId`. In public access mode, `team` is readable and writable by any authenticated principal (unless `ARTIFACTY_TEAM_WRITE=owner` restricts writes to the owner or an admin). `private` is readable and writable only by its owner or an admin; reads by anyone else 404 instead of 403 so the artifact's existence isn't leaked. Archiving, restoring, and changing visibility or ownership always require the owner or an admin, regardless of visibility. A shared `ARTIFACTY_API_TOKEN` (or any request before the first user account is created) has no personal identity and is treated as an anonymous team principal: it can read and write `team` artifacts but never sees `private` ones. In single-user mode (no user accounts at all) every check is bypassed, matching pre-visibility behavior. Change visibility and ownership with `POST /api/artifacts/:id/visibility` and `POST /api/artifacts/:id/owner`, the `artifacty visibility <id> private|team` CLI command, or the `artifacty_set_visibility` MCP tool.
769
+ - Once any user account exists, artifacts use `visibility` (`public`, `team`, or `private`, default `team`) and `ownerUserId`. In public server mode, `public` allows anonymous read-only access; `team` requires authentication; `private` permits only the owner or administrator. Writes and owner-management operations remain permission-checked. In private mode, explicit sharing controls access. Restricted reads return 404 to avoid disclosing existence. The no-account single-user mode remains a separate local behavior. Change visibility or ownership through `POST /api/artifacts/:id/visibility`, `POST /api/artifacts/:id/owner`, `artifacty visibility <id> private|team|public`, or `artifacty_set_visibility`.
728
770
  - HTTP and MCP-over-HTTP requests are rate limited per `(token or user or remote address, bucket)` in fixed one-minute windows: `write` (mutating routes, default 120/min, `ARTIFACTY_RATE_WRITE_PER_MIN`), `auth` (`/login`, default 10/min per address, `ARTIFACTY_RATE_AUTH_PER_MIN`), and `search` (`GET /api/artifacts?q=`, default 300/min, `ARTIFACTY_RATE_SEARCH_PER_MIN`). Rate limiting is disabled on a loopback bind unless `ARTIFACTY_RATE_LIMIT=always`, and always disabled with `ARTIFACTY_RATE_LIMIT=off`. Exceeding a limit returns `429` with a `Retry-After` header, `code: "rate_limited"`, and a rate-limited `rate-limited` audit row.
729
771
  - Binding outside localhost requires both `ARTIFACTY_SHARE_MODE=lan` or `team` and `ARTIFACTY_API_TOKEN`.
730
772
  - Non-local sharing is intended for trusted LAN or VPN sessions. Prefer a specific interface IP over `0.0.0.0`, keep React rendering disabled, and see [docs/network-sharing.md](docs/network-sharing.md).
@@ -765,7 +807,7 @@ The table lists every `ARTIFACTY_*` variable that Artifacty reads. `node src/cli
765
807
  | `ARTIFACTY_MCP_HTTP` | Set `true` to also expose MCP over HTTP on the running server | `false` |
766
808
  | `ARTIFACTY_MCP_TIMEOUT_MS` | Bridge-mode MCP HTTP request timeout | `30000` |
767
809
  | `ARTIFACTY_API_TOKEN` | Shared token required for HTTP API and LAN/team sharing | — |
768
- | `ARTIFACTY_LOCALE` | Default UI locale (e.g. `en`, `ko`) when a request does not specify one | `en` |
810
+ | `ARTIFACTY_LOCALE` | Initial UI default (`en` or `ko`) before administrator language settings are saved | `en` |
769
811
  | `ARTIFACTY_EMBEDDINGS_URL` | openai-compatible embeddings endpoint base URL; enables semantic/hybrid search | — |
770
812
  | `ARTIFACTY_EMBEDDINGS_MODEL` | Embeddings model name | provider default |
771
813
  | `ARTIFACTY_EMBEDDINGS_API_KEY` | API key for the openai-compatible provider; never logged or stored | — |
@@ -6,3 +6,56 @@ Artifacty includes CodeMirror 6 packages for the browser editor.
6
6
  - Lezer parser packages used by CodeMirror are distributed under the MIT License.
7
7
 
8
8
  The installed package metadata and license files are retained through npm dependency installation.
9
+
10
+ ## Bootstrap 5.3.8
11
+
12
+ Artifacty includes selected generated assets from this package.
13
+
14
+ The MIT License (MIT)
15
+
16
+ Copyright (c) 2011-2025 The Bootstrap Authors
17
+
18
+ Permission is hereby granted, free of charge, to any person obtaining a copy
19
+ of this software and associated documentation files (the "Software"), to deal
20
+ in the Software without restriction, including without limitation the rights
21
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22
+ copies of the Software, and to permit persons to whom the Software is
23
+ furnished to do so, subject to the following conditions:
24
+
25
+ The above copyright notice and this permission notice shall be included in
26
+ all copies or substantial portions of the Software.
27
+
28
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
33
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
34
+ THE SOFTWARE.
35
+
36
+
37
+ ## Tabler Icons 3.49.0
38
+
39
+ Artifacty includes selected generated assets from this package.
40
+
41
+ MIT License
42
+
43
+ Copyright (c) 2020-2026 Paweł Kuna
44
+
45
+ Permission is hereby granted, free of charge, to any person obtaining a copy
46
+ of this software and associated documentation files (the "Software"), to deal
47
+ in the Software without restriction, including without limitation the rights
48
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
49
+ copies of the Software, and to permit persons to whom the Software is
50
+ furnished to do so, subject to the following conditions:
51
+
52
+ The above copyright notice and this permission notice shall be included in all
53
+ copies or substantial portions of the Software.
54
+
55
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
56
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
57
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
58
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
59
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
60
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
61
+ SOFTWARE.
package/docs/README.md CHANGED
@@ -4,11 +4,17 @@ English | [한국어](ko/README.md)
4
4
 
5
5
  Start with the [project README](../README.md) for installation, features, CLI commands, and environment variables.
6
6
 
7
+ ## Browser language
8
+
9
+ Administrators enable installed languages and choose the default at `/admin/languages`. Enabled URL choices take priority over the browser cookie, then the saved default. Before settings are saved, the initial default comes from `ARTIFACTY_LOCALE` or English. Disabled choices and `Accept-Language` are ignored. See [language packs](language-packs.md) for imports and fallback rules. UI translations do not translate commands, API/MCP identifiers, or stored artifact content.
10
+
7
11
  ## User and operator guides
8
12
 
9
13
  | Document | English | 한국어 |
10
14
  | --- | --- | --- |
11
15
  | Installation and feature reference | [README](../README.md) | [README](../README.ko.md) |
16
+ | Language packs | [Guide](language-packs.md) | [언어 팩](ko/language-packs.md) |
17
+ | SMTP and password reset | [Guide](smtp.md) | [SMTP와 비밀번호 재설정](ko/smtp.md) |
12
18
  | Agent integrations | [Guide](integrations.md) | [연동 안내](ko/integrations.md) |
13
19
  | Network sharing | [Guide](network-sharing.md) | [네트워크 공유](ko/network-sharing.md) |
14
20
  | Upgrade snapshots and recovery | [Guide](upgrade-backups.md) | [업데이트 백업과 복구](ko/upgrade-backups.md) |
package/docs/ko/README.md CHANGED
@@ -4,11 +4,17 @@
4
4
 
5
5
  설치 방법, 전체 기능, CLI 명령과 환경 변수는 [한국어 README](../../README.ko.md)에서 확인하세요.
6
6
 
7
+ ## 브라우저 화면 언어
8
+
9
+ 관리자는 `/admin/languages`에서 설치된 언어를 활성화하고 기본 언어를 선택합니다. 활성화된 URL 선택, 브라우저 쿠키, 저장한 기본값 순으로 적용합니다. 설정을 저장하기 전에는 `ARTIFACTY_LOCALE` 또는 영어가 초기 기본값입니다. 비활성화된 선택과 `Accept-Language`는 무시합니다. 가져오기와 대체 언어 규칙은 [언어 팩](language-packs.md)을 참고하세요. UI 번역은 명령어, API·MCP 식별자, 저장된 아티팩트 내용을 번역하지 않습니다.
10
+
7
11
  ## 사용자·운영자 안내
8
12
 
9
13
  | 문서 | 한국어 | English |
10
14
  | --- | --- | --- |
11
15
  | 설치와 기능 참조 | [README](../../README.ko.md) | [README](../../README.md) |
16
+ | 언어 팩 | [안내](language-packs.md) | [Guide](../language-packs.md) |
17
+ | SMTP와 비밀번호 재설정 | [안내](smtp.md) | [Guide](../smtp.md) |
12
18
  | 에이전트 연동 | [연동 안내](integrations.md) | [Guide](../integrations.md) |
13
19
  | 네트워크 공유 | [안내](network-sharing.md) | [Guide](../network-sharing.md) |
14
20
  | 업데이트 백업과 복구 | [안내](upgrade-backups.md) | [Guide](../upgrade-backups.md) |
@@ -0,0 +1,40 @@
1
+ # 언어 팩
2
+
3
+ [English](../language-packs.md) | 한국어
4
+
5
+ <!-- 번역 기준: 동일 변경의 docs/language-packs.md -->
6
+
7
+ ## 사용할 언어 선택
8
+
9
+ 관리자로 **관리 → 언어 관리**(`/admin/languages`)를 여세요. 설치된 언어 중 사용자가 선택할 언어를 활성화하세요. 활성화한 언어를 기본 언어로 선택한 뒤 저장하세요. 최소 한 언어는 활성화해야 합니다. 언어 선택 메뉴에는 각 언어의 고유 이름이 표시됩니다.
10
+
11
+ 영어와 한국어는 기본 제공 언어입니다. 설정을 한 번도 저장하지 않았다면 `ARTIFACTY_LOCALE=en` 또는 `ko`가 초기 기본 언어를 정합니다. 환경 변수 설정이 없으면 영어를 사용합니다. 관리자가 설정을 저장하면 초기 기본값 대신 저장한 설정을 사용합니다.
12
+
13
+ 브라우저는 직접 지정한 `?lang=<locale>`, 브라우저에 저장된 쿠키, 관리자 기본 언어 순으로 활성화된 언어를 선택합니다. 비활성화했거나 설치하지 않은 언어는 무시합니다. 활성화된 영어를 직접 선택하면 한국어 쿠키나 기본값보다 우선합니다. `Accept-Language`로 언어를 선택하지 않습니다. 쿠키는 해당 브라우저에 1년간 유지합니다. 쿠키를 지우면 관리자 기본 언어를 사용합니다. 설정을 저장한 적이 없다면 초기 환경 변수 설정 또는 영어를 사용합니다.
14
+
15
+ ## 사용자 언어 팩 가져오기
16
+
17
+ 1. `/admin/languages/template`에서 JSON 템플릿을 내려받으세요.
18
+ 2. 새 언어의 `locale`과 `nativeName`을 지정하세요.
19
+ 3. `messages`의 항목을 번역하세요.
20
+ 4. `/admin/languages`의 가져오기 입력란에 JSON을 붙여 넣으세요.
21
+ 5. 언어 팩을 가져오세요.
22
+ 6. 언어 설정에서 가져온 언어를 활성화하세요.
23
+
24
+ 일부 항목만 번역한 일본어 팩은 다음과 같이 작성할 수 있습니다.
25
+
26
+ ```json
27
+ {
28
+ "locale": "ja",
29
+ "nativeName": "日本語",
30
+ "messages": {
31
+ "nav.artifacts": "アーティファクト"
32
+ }
33
+ }
34
+ ```
35
+
36
+ 번역하지 않은 메시지는 영어로 표시합니다. 가져올 때는 현재 등록된 메시지 키만 허용합니다. 번역에는 영어 메시지의 자리표시자 이름을 그대로 유지해야 합니다. 예를 들어 `{count}`를 바꾸면 안 됩니다. 키나 자리표시자가 잘못되면 가져오기를 거부합니다. 애플리케이션 업데이트 후 기존 키가 없어지거나 자리표시자가 바뀌면, 저장된 해당 번역을 읽을 때 무시하고 현재 영어 메시지를 표시합니다.
37
+
38
+ 사용자 팩으로 기본 제공 언어인 `en`이나 `ko`를 교체할 수 없습니다. 기존 사용자 언어와 같은 로케일을 가져오면 해당 팩을 교체합니다. 사용자 팩은 최대 16개, 팩당 512 KiB, 전체 설정은 4 MiB까지 허용합니다. 크기는 UTF-8 JSON 바이트로 계산합니다. 언어 설정과 팩 메타데이터는 전체 백업에 포함합니다.
39
+
40
+ 언어 팩은 UI 문구를 번역합니다. 명령어, API·MCP 식별자, 저장된 아티팩트 내용은 번역하지 않습니다. [화면 언어 안내](../../README.ko.md#화면-언어)를 참고하세요.
@@ -4,6 +4,23 @@
4
4
 
5
5
  # 네트워크 공유
6
6
 
7
+ ## IP 대역과 공유 링크
8
+
9
+ **관리자 → 접근 관리 → 네트워크 접근**에서 허용할 IP 또는 CIDR을 한 줄에
10
+ 하나씩 입력합니다. 쉼표로 구분해도 됩니다. 비워두면 모든 주소를 허용합니다.
11
+ 현재 접속 IP를 포함해 저장한 뒤 120초 안에 확정하세요. 확정하지 않으면
12
+ 기한이 지난 후 다음 접근 시 이전 설정으로 돌아갑니다.
13
+
14
+ **허용 IP 대역 밖에서도 공유 링크 열람 허용**은 기본적으로 꺼져 있습니다.
15
+ 켜면 허용 대역 밖에서도 유효한 공유 링크로 해당 아티팩트를 읽을 수 있습니다.
16
+ 예외는 공유 페이지와 해당 원본 콘텐츠에만 적용합니다. 대시보드·검색·API·MCP와
17
+ 일반 아티팩트 주소는 계속 제한합니다. 만료되거나 취소된 링크는 사용할 수
18
+ 없습니다. 비공개 모드에서는 별도의 비공개 모드 공유 허용 설정도 켜야 합니다.
19
+ 이 옵션도 IP 대역과 함께 저장하며, 같은 확정·되돌리기 절차를 따릅니다.
20
+
21
+ 접근 판단에는 전달 헤더가 아닌 직접 연결된 IP를 사용합니다. 리버스 프록시를
22
+ 거치면 프록시 IP를 보므로, 필요한 경우 프록시에서 클라이언트 IP를 제한하세요.
23
+
7
24
  Artifacty는 아티팩트를 로컬에 저장합니다. 기본적으로 서버는 한 컴퓨터에서 사용하도록 `127.0.0.1`에 바인딩합니다. 짧은 공유 세션을 위해 로컬 외부 주소에 바인딩할 수 있습니다. 이 경우 다른 컴퓨터에서도 서버에 접근할 수 있습니다.
8
25
 
9
26
  ## 권장 기본 설정
@@ -0,0 +1,27 @@
1
+ # SMTP와 비밀번호 재설정
2
+
3
+ [English](../smtp.md) | 한국어
4
+
5
+ <!-- 번역 기준: 동일 변경의 docs/smtp.md -->
6
+
7
+ ## 이메일 설정
8
+
9
+ 관리자로 **관리 → 이메일 / SMTP**(`/admin/email`)을 여세요. SMTP 호스트, 포트, 발신자 주소, TLS 방식을 입력하세요. 설정이 준비되면 발송을 활성화하세요. 사용 중인 메일 서비스의 설정을 사용하세요. 이 안내에는 메일 제공업체의 인증 정보를 포함하지 않습니다.
10
+
11
+ TLS 또는 STARTTLS가 필수입니다. Artifacty는 서버 인증서를 검증하며, 보안 연결에 실패해도 암호화하지 않은 연결로 전환하지 않습니다. 사용자 이름을 비우면 SMTP 인증을 사용하지 않고 저장한 비밀번호도 삭제합니다. 사용자 이름이 있는 상태에서 비밀번호 입력란을 비우면 기존 비밀번호를 유지합니다.
12
+
13
+ ## 사용자 비밀번호 재설정
14
+
15
+ 관리자는 `/admin/users`에서 사용자 비밀번호를 재설정할 수 있습니다. 임시 비밀번호를 생성하고 다음 로그인 때 비밀번호를 변경하도록 합니다. 해당 사용자의 세션은 폐기하지만 기존 API 토큰은 유지합니다.
16
+
17
+ SMTP 발송을 활성화했다면 임시 비밀번호를 사용자의 이메일 주소로 보냅니다. SMTP 서버가 메시지를 수락해도 받은편지함 도착을 보장하지는 않습니다. 실패하거나 발송 여부가 불확실하면 자동으로 재시도하지 않습니다. 메시지가 이미 수락되었을 수 있기 때문입니다. 관리자 결과 화면에 한 번 표시하는 임시 비밀번호를 직접 전달하세요. 이메일을 다시 보내기 위한 목적으로 비밀번호를 다시 재설정하지 마세요.
18
+
19
+ ## 암호화 키 보호
20
+
21
+ SMTP 설정 전체를 AES-256-GCM으로 암호화해 SQLite에 저장합니다. 별도 키는 `ARTIFACTY_HOME/secrets/smtp.key`에 있습니다. POSIX 환경에서는 디렉터리 권한이 `700`, 키 파일 권한이 `600`이어야 합니다.
22
+
23
+ 전체 JSON 백업에는 암호화된 설정을 포함하지만 키는 포함하지 않습니다. 업그레이드 스냅샷에도 키를 포함하지 않습니다. 같은 홈에 복원하면 기존 키를 그대로 둡니다. 새 홈으로 이전하거나 복원할 때는 원래 키를 별도로 백업하고 비공개 권한을 유지해 옮기세요.
24
+
25
+ 키를 잃어버리면 암호화된 설정을 복구할 수 없습니다. 설정을 바꾸기 전에 원래 키를 복원하세요. 이전 설정을 복호화하려고 새 키를 생성하지 마세요. 키 백업은 비공개로 보관하고 공유하는 백업 번들과 분리하세요.
26
+
27
+ 저장소 복원 절차는 [업그레이드 스냅샷과 복구](upgrade-backups.md)를 참고하세요.
@@ -0,0 +1,38 @@
1
+ # Language packs
2
+
3
+ English | [한국어](ko/language-packs.md)
4
+
5
+ ## Choose available languages
6
+
7
+ As an administrator, open **Administration → Languages** (`/admin/languages`). Enable the installed languages that users can select. Choose an enabled language as the default, then save. At least one language must remain enabled. The selector displays each language's native name.
8
+
9
+ English and Korean are built in. Before any settings are saved, `ARTIFACTY_LOCALE=en` or `ko` sets the initial default; otherwise it is English. Saved administrator settings replace this initial default.
10
+
11
+ The browser uses the first enabled choice in this order: explicit `?lang=<locale>`, the saved browser cookie, then the administrator default. Disabled or uninstalled choices are ignored. An explicit enabled English choice overrides a Korean cookie or default. `Accept-Language` does not select the language. The cookie lasts one year and belongs to that browser. Clearing it restores the administrator default, or the initial environment/English default if settings have never been saved.
12
+
13
+ ## Import a custom pack
14
+
15
+ 1. Download the JSON template from `/admin/languages/template`.
16
+ 2. Set `locale` and `nativeName` for the new language.
17
+ 3. Translate entries in `messages`.
18
+ 4. Paste the JSON into the import field at `/admin/languages`.
19
+ 5. Import the pack.
20
+ 6. Enable the imported language in the language settings.
21
+
22
+ A partial Japanese pack can contain:
23
+
24
+ ```json
25
+ {
26
+ "locale": "ja",
27
+ "nativeName": "日本語",
28
+ "messages": {
29
+ "nav.artifacts": "アーティファクト"
30
+ }
31
+ }
32
+ ```
33
+
34
+ Missing messages use English. Imports accept only current known message keys. Each translation must preserve the placeholder names from its English message, such as `{count}`. Invalid keys or placeholders reject the import. After an application update, obsolete stored keys or changed placeholders are ignored on read and use the current English fallback.
35
+
36
+ Custom packs cannot replace built-in `en` or `ko`. Importing an existing custom locale replaces that pack. Limits are 16 custom packs, 512 KiB per pack, and 4 MiB for the combined settings. These limits count UTF-8 JSON bytes. Language settings and pack metadata are included in full backups.
37
+
38
+ Language packs translate UI text. They do not translate commands, API/MCP identifiers, or stored artifact content. See the [interface language reference](../README.md#interface-language).
@@ -44,6 +44,24 @@ Artifacty does not terminate TLS. Do not expose it directly on the public intern
44
44
 
45
45
  If Artifacty binds outside loopback, startup output warns that other machines can reach the server. The warning also states that Artifacty does not provide TLS. Background `serve` returns the warning in JSON. Foreground `serve` and `src/server.js` also write it to stderr.
46
46
 
47
+ ## IP ranges and shared links
48
+
49
+ In **Administration → Access → Network access**, enter one allowed IP address
50
+ or CIDR per line. Commas also work. An empty list allows all addresses. Include
51
+ your current connection IP, save, then confirm within 120 seconds. Otherwise,
52
+ the previous policy is restored on the next access after the deadline.
53
+
54
+ **Allow shared links outside these IP ranges** is off by default. Enable it to
55
+ let people outside the allowed ranges read an artifact through its valid shared
56
+ link. Only the shared page and its raw content are exempt. The dashboard,
57
+ search, API, MCP, and ordinary artifact URLs remain restricted. Expired or
58
+ revoked links do not grant access. Private mode still requires the separate
59
+ setting that permits shared links in private mode. Saving this option uses the
60
+ same confirmation and rollback process as the IP ranges.
61
+
62
+ Rules use the direct socket peer, not forwarded IP headers. With a reverse
63
+ proxy, that peer is the proxy; enforce client IP ranges at the proxy when needed.
64
+
47
65
  ## Browser Write Behavior
48
66
 
49
67
  Remote browsers can read pages allowed by the current access mode and artifact permissions. To submit a browser form, the request origin must match the Artifacty host. For example, `Origin: http://10.0.0.50:8787` matches `Host: 10.0.0.50:8787`. Routes that change data reject cross-origin browser requests to reduce CSRF risk. For scripts and agents, use API or MCP writes with an explicit token header.
@@ -12,8 +12,9 @@ Every feature follows these architecture rules:
12
12
  - Treat artifact content as untrusted.
13
13
  - Add no runtime dependency unless the section explicitly permits it.
14
14
 
15
- Status recorded on 2026-09-04: all sections below were implemented, and
16
- `STORE_VERSION` was `8`. The original planning text follows.
15
+ Status recorded on 2026-09-04: the original sections 1–21 were implemented, and
16
+ `STORE_VERSION` was `8`. Their original planning text follows. Section 22 is a
17
+ new proposal deferred to the next version; it is not a current capability.
17
18
 
18
19
  Store schema changes increase `STORE_VERSION` (originally `4`). They use the
19
20
  existing `ensureColumn` / `CREATE TABLE IF NOT EXISTS` migration path. Older
@@ -42,6 +43,7 @@ stores upgrade on first access.
42
43
  19. [OpenAPI Specification](#19-openapi-specification)
43
44
  20. [MCP Protocol Refresh](#20-mcp-protocol-refresh)
44
45
  21. [Delivery Plan](#21-delivery-plan)
46
+ 22. [Optional Artifact Encryption at Rest — Planned](#22-optional-artifact-encryption-at-rest--planned)
45
47
 
46
48
  ---
47
49
 
@@ -987,3 +989,30 @@ If the artifact envelope changes, use a `v2` schema document. Increase
987
989
  check.
988
990
  - `/raw` always returns the stored bytes unchanged.
989
991
  - No generated MCP config hard-codes `http://127.0.0.1:8787`.
992
+
993
+
994
+ ---
995
+
996
+ ## 22. Optional Artifact Encryption at Rest — Planned
997
+
998
+ **Status (2026-10-14): deferred to the next version. Design and implementation
999
+ are pending.** This is a substantial storage change, not a current feature.
1000
+ Existing SMTP configuration encryption does not encrypt artifact data.
1001
+
1002
+ An administrator should be able to opt in or turn encryption off. Each change
1003
+ must migrate the existing store between encrypted and plaintext states; a
1004
+ setting that affects only future writes is insufficient. The design must cover
1005
+ artifact/version blobs and bundle assets, metadata, and search indexes, including
1006
+ any retained plaintext copies or derived data. Cipher and storage choices remain
1007
+ open until the full design is reviewed.
1008
+
1009
+ Before migration, create and verify a recovery backup and check available disk
1010
+ space. Hold an exclusive write lock across HTTP, CLI, MCP, and background writers.
1011
+ Verify file references, hashes, and database/index integrity before committing
1012
+ the new state. Define how failures and interrupted migrations recover without
1013
+ leaving a mixed or silently unreadable store.
1014
+
1015
+ Keep encryption keys and recovery material separately secured. The design must
1016
+ specify key backup, restore to a new home, key-loss behavior, and whether disabling
1017
+ encryption leaves any recoverable plaintext or ciphertext copies. Review backup,
1018
+ retention, and recovery behavior before implementing the administrator control.