Skip to content
Back to skills

Tizen Certificate Manager

ASecurity

Manage Tizen certificates (local self-signed and Samsung online-CA) and signing profiles, including generation, Samsung Account login, distributor selection, profile lifecycle, import, and inspection.

  • 3 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 6, 2026
developmentgoshellbashnodegitapisecurity

Works with

  • claude code
  • terminal
  • cli
  • api

Security analysis

A100/100

Scanned October 6, 2026

npx -y skills add Samsung/tizen-agent-skills --skill tizen-certificate-manager --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Tizen Certificate Manager?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Tizen Certificate Manager
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/samsung-tizen-certificate-manager/badge)](https://www.skillsdirectory.com/skills/samsung-tizen-certificate-manager)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: tizen-certificate-manager
description: Manage Tizen certificates (local self-signed and Samsung online-CA) and signing profiles, including generation, Samsung Account login, distributor selection, profile lifecycle, import, and inspection.
metadata:
  author: Samsung Electronics
  last-updated: "2026-09-18"
  keywords:
    - Samsung TV emulator
    - TV 에뮬레이터 인증서
    - Tizen certificate
    - author certificate
    - tz cert
    - 인증서 생성
    - 타이젠 인증서
    - signing certificate
    - distributor certificate
    - 배포자 인증서
    - Samsung certificate
    - Samsung online-CA
    - Samsung author certificate
    - 삼성 인증서
    - Samsung Account login
---

### Claude Code (서브에이전트 위임)

> Agent tool이 없으면 (예: Cline) 아래 "CLI Runner" 섹션으로 가세요.

1. Agent tool로 `tizen-certificate-manager` 에이전트 호출 (개인 배포 또는 `tizen-sdk-skills:tizen-certificate-manager`)
2. 사용자의 요청을 프롬프트로 전달
3. 서브에이전트의 JSON Envelope를 그대로 사용자에게 전달 — 아래 "결과 보고" 규칙을 따른다
   (fenced `json` 블록으로 원문을 싣고, 그 아래 요약은 1~2줄만)

## Password handling — mandatory

Never ask a user to type, select, paste, or confirm a certificate password in Cline/Claude chat. When a certificate action needs a password, ask only for non-secret fields.

**If the user already wrote the password in the prompt** (e.g. "…with password Passw0rd1"), the rules do not relax: never forward it as `--password`, never write it into a file for them, and never echo it back. This is expected behavior, not a malfunction (issue #99). Do this instead, in order: (1) say in one sentence that the password is now in the chat transcript and recommend choosing a different one for the certificate; (2) present **both** choices below and let the user pick — do not jump straight to creating a password-file template; (3) proceed with the chosen option using only the non-secret values (name, file name, e-mail, …) from the prompt.

**Cline:** run the CLI with the matching hidden-terminal flag and wait for the user to enter it in the terminal.

**Claude Code:** its Bash tool and sub-agents have no interactive TTY. After collecting all non-secret inputs, offer exactly these two choices before running a password-protected action:

1. **Run a command personally.** Give the user one complete copy-paste-ready command with the actual resolved CLI path and every known non-secret value already filled in. Use the matching `--prompt-...` flag. Do **not** give the user `<name>`, `<path>`, `<file>`, or any other placeholder to fill in. Tell them to prefix that exact command with `!` in Claude Code, or run it in another terminal; they press Enter, type the hidden password, and the command completes. **Windows path rule:** on Windows the Bash locate block returns an MSYS path (`/c/Users/...`) that only Git Bash understands; pasted into cmd.exe or PowerShell, Node resolves it as `C:\c\Users\...` and fails with `MODULE_NOT_FOUND`. Before placing the path in the user-facing command, convert it with `cygpath -w "$CLI"` and hand over the result in double quotes, i.e. `node "C:\Users\...\cert-manager-cli.js" ...`; that form works in cmd.exe, PowerShell, and Git Bash (`!` mode) alike. Never hand over the `/c/Users/...` form.
2. **Use a protected environment file.** Ask: **“Would you like me to create an empty protected password-file template? If yes, what absolute file location do you prefer?”** If the user agrees, create and lock down the file at that exact location with the required variable name followed by `=` and **no password**. Tell the user to open it locally, enter the password after `=`, save it, and reply only that it is ready. **Once the user says it is ready, do not read, open, inspect, edit, overwrite, or otherwise modify that file for any reason.** The agent must never read, print, or ask for the file contents. It may receive and use only the file path with the matching `--...-password-file` option.

For a normal certificate password, the agent-created template is `TIZEN_CERTIFICATE_PASSWORD=` and the final file format is `TIZEN_CERTIFICATE_PASSWORD=<password>`. On Linux/macOS, create it with `umask 077` and apply `chmod 600 <file>`; on Windows, restrict the file ACL to the current user. The matching formats are:

- `TIZEN_AUTHOR_CERTIFICATE_PASSWORD=<password>` for `--author-password-file`
- `TIZEN_DISTRIBUTOR_CERTIFICATE_PASSWORD=<password>` for `--distributor-password-file`
- `TIZEN_DISTRIBUTOR2_CERTIFICATE_PASSWORD=<password>` for `--distributor2-password-file`

**Template completion guide:** after the agent creates the template at the chosen path, the user opens it in a local editor, enters the password after `=`, saves it, and replies only that the file is ready. Do not suggest `echo`, `printf`, or a command containing the password, because those may enter shell history. Do not ask the user to paste the line or password into chat.

**Ready-file rule:** after the user fills the password, the file is the user's responsibility. Never use a Read/Edit/Write tool on it. If the CLI reports an invalid password-file format, do not inspect or repair it: tell the user the required one-line format and ask them to correct the file locally, then reply only that it is ready again.

Use only one source for each password: visible argument, hidden prompt, or password file.

Hidden-terminal flags:

- `--prompt-password` for certificate generation, import, and inspection
- `--prompt-author-password` for an author certificate in a signing profile
- `--prompt-distributor-password` for a distributor certificate
- `--prompt-distributor2-password` for distributor key 2

For a local author certificate, ask for the author name only. In Cline, run `generate-author --name <name> --prompt-password`. In Claude Code, offer the two choices above. For option 1, supply the resolved CLI path and actual author name in the command (for example, on Linux/macOS `! node "/home/alex/.claude/plugins/cache/tizen-platform/tizen-sdk-skills/1.0.0/lib/cli/cert-manager-cli.js" generate-author --name "Eden" --prompt-password`; on Windows, where `cygpath -w` turns `/c/Users/alex/.claude/.../cert-manager-cli.js` into `C:\Users\alex\.claude\...\cert-manager-cli.js`, `! node "C:\Users\alex\.claude\plugins\cache\tizen-platform\tizen-sdk-skills\1.0.0\lib\cli\cert-manager-cli.js" generate-author --name "Eden" --prompt-password` — the same command without the `!` prefix runs in cmd.exe or PowerShell), never placeholders. For option 2, offer to create the empty template, ask for the preferred absolute location, then run `generate-author --name <name> --password-file <path>` only after the user says the locally completed file is ready. The terminal input and password-file contents must never be written to chat, command arguments, or an agent response.

## Samsung certificates — TV targets only (mandatory)

A Samsung online-CA certificate (`generate-samsung-author`, `generate-samsung-distributor`,
`import-samsung-certificate`) and the signing profile built from it (`create-samsung-profile`) are
valid **only for Samsung TV targets**: the **TV emulator** (created with
`tizen-create-emulator --profile tv`, which needs the TV SDK from `tizen-tv-sdk-install`) and a real
Samsung TV whose DUID is in the distributor certificate. A standard Tizen emulator
(`--profile tizen` — mobile / wearable / IoT platform images) accepts only the SDK-bundled
distributor certificate; a package signed with a Samsung profile is rejected there with a
certificate error.

1. **Check the target before any Samsung action.** Run the Samsung flow only when the target is
   the TV emulator or a Samsung TV. If the target is a standard Tizen emulator, do not run
   `generate-samsung-*` / `create-samsung-profile`: say in one sentence that Samsung certificates
   are for the TV emulator and Samsung TVs, then use `generate-author` → `create-profile`. If the
   user asked for a Samsung certificate but named no target, ask which target they are signing for
   (TV emulator / Samsung TV, or a standard emulator) before choosing — do not silently substitute
   the local flow. This is the only case in which a Samsung request ends in `generate-author`.
2. **DUIDs come from the TV target.** Run `acquire-duid` / `acquire-duids-all` against the TV
   emulator or TV (`--serial <tv-emulator-serial>`). A DUID taken from a standard emulator yields a
   distributor certificate that cannot be used anywhere.
3. **No TV emulator yet?** Hand off: `tizen-tv-sdk-install` → `tizen-create-emulator --profile tv`
   → `tizen-launch-emulator`, then return to the Samsung flow.
4. **Build and install follow the same split.** A build signed with a Samsung profile
   (`--sign-profile <samsung-profile>`) is installed only on the TV emulator or a registered TV. A
   certificate error when installing it on a standard emulator is the rule working, not a bug: do
   not retry with `sdb root on` and do not import the certificate by hand — rebuild with a local
   profile for that emulator, or switch to the TV emulator.

### CLI Runner (Cline / Claude Code)

**Pick the ONE block for the shell your terminal / tool runs — the prompt tells you: `$` is Bash (Linux, macOS, Claude Code's Git Bash on Windows, Codex on Linux / macOS) → Bash block; `PS C:\…>` is PowerShell (Codex on Windows, Cline PowerShell terminal) → PowerShell block; `C:\…>` is cmd.exe (Cline cmd.exe terminal) → cmd.exe block. Run that block as-is: a block pasted into another shell, or wrapped in `powershell -Command "…"`, is a parse error.**

**Bash — Linux / macOS / Ubuntu, and Windows Git Bash (Claude Code):**

```bash
BASE="$HOME/.cline"; [ -z "${CODEX_THREAD_ID:-}${CODEX_SANDBOX_NETWORK_DISABLED:-}${CODEX_SANDBOX:-}${CODEX_VERSION:-}" ] || BASE="$HOME/.codex"; [ -z "${GEMINI_CLI:-}" ] || BASE="$HOME/.gemini"; [ -z "${CLAUDECODE:-}" ] || BASE="$HOME/.claude"
CLI=$(ls "$BASE"/plugins/cache/tizen-platform/tizen-sdk-skills/*/lib/cli/cert-manager-cli.js 2>/dev/null | sort -V | tail -1) || true
[ -n "$CLI" ] || for d in .claude .cline .codex .gemini; do CLI=$(ls "$HOME/$d"/plugins/cache/tizen-platform/tizen-sdk-skills/*/lib/cli/cert-manager-cli.js 2>/dev/null | sort -V | tail -1) || true; [ -z "$CLI" ] || break; done
node "$CLI" generate-author --name "Jane Dev" --prompt-password
node "$CLI" list-distributors
```

**PowerShell (Codex CLI on Windows, Cline PowerShell terminal) — prefers this harness's own cache, then the newest version. Run all three lines below, in order, in the SAME PowerShell session: the `node` line needs the `$CLI` the lookup line sets (on its own, `node "$CLI" …` becomes `node <first-arg>` and fails with a misleading `MODULE_NOT_FOUND`), so it carries a guard that stops with a clear message when `$CLI` is empty. Never wrap the lines in `powershell -Command "…"` (PowerShell and Git Bash expand `$h`, `$CLI` and `$env:…` before the inner shell runs, so the lookup arrives empty):**

```powershell
$h = ".cline"; if ($env:CODEX_THREAD_ID -or $env:CODEX_SANDBOX_NETWORK_DISABLED -or $env:CODEX_SANDBOX -or $env:CODEX_VERSION) { $h = ".codex" }; if ($env:GEMINI_CLI) { $h = ".gemini" }; if ($env:CLAUDECODE) { $h = ".claude" }
$CLI = $null; foreach ($d in @($h, ".claude", ".cline", ".codex", ".gemini")) { $CLI = Get-ChildItem "$env:USERPROFILE\$d\plugins\cache\tizen-platform\tizen-sdk-skills\*\lib\cli\cert-manager-cli.js" -ErrorAction SilentlyContinue | Sort-Object { [version]$_.Directory.Parent.Parent.Name } | Select-Object -Last 1 -ExpandProperty FullName; if ($CLI) { break } }
if (-not $CLI) { throw 'tizen-sdk-skills runner not found: $CLI is empty. Run the two lookup lines above in THIS PowerShell session first; if they still find nothing, the tizen-sdk-skills plugin is not installed.' }; node "$CLI" generate-author --name "Jane Dev" --prompt-password
```

**Windows — cmd.exe terminal only (Cline with a cmd.exe terminal). `&` and `2>nul` are cmd.exe syntax — in a PowerShell terminal run the PowerShell block above instead; Claude Code on Windows runs Git Bash — use the Bash block above. cmd.exe cannot version-sort, so this only lists every copy: pick your own host's highest version and paste it into the `node "<found-path>"` step below:**

```
cmd /c dir /s /b "%USERPROFILE%\.claude\plugins\cache\tizen-platform\tizen-sdk-skills\*cert-manager-cli.js" 2>nul & dir /s /b "%USERPROFILE%\.cline\plugins\cache\tizen-platform\tizen-sdk-skills\*cert-manager-cli.js" 2>nul & dir /s /b "%USERPROFILE%\.codex\plugins\cache\tizen-platform\tizen-sdk-skills\*cert-manager-cli.js" 2>nul & dir /s /b "%USERPROFILE%\.gemini\plugins\cache\tizen-platform\tizen-sdk-skills\*cert-manager-cli.js" 2>nul & ver >nul
```

Pick the highest-version path (the PowerShell form above already resolved `$CLI`), then:

```
node "<found-path>" generate-author --name "Jane Dev" --prompt-password
```

> **Runner not found?** If none of the `~/.claude`, `~/.cline`, `~/.codex`, `~/.gemini` caches contains the runner, the tizen-sdk-skills plugin is NOT installed on this machine — install it first; do not improvise with other tools. (Contributors working inside the tizen-sdk-skills source repository can use the in-repo runner instead: `node common/lib/cli/<runner>.js`.)

### Codex CLI — Samsung online flows and password prompts (one exec call waits ≤ 30 s)

Codex's exec tool returns after at most 30 s. Local actions (`generate-author`, `list-*`,
`create-profile`, …) finish inside that. The Samsung online actions (`samsung-login`,
`generate-samsung-*`, `create-samsung-profile`, `acquire-duids-all`) are network-bound, and
`samsung-login` opens the system browser and waits **up to 5 minutes** for the human. **The
browser login works under Codex** — as a detached, escalated job (issue #76):

1. `node "$CLI" samsung-login --profile-name <p> --background` **with escalated permissions**
   (the sandbox has no network and would kill the job; inside it the runner refuses with
   `sandbox_blocked`). The receipt returns within a second.
2. Tell the user a Samsung Account browser window opened. Poll
   `node "<same lib/cli dir>/job-cli.js" wait --id <job_id>`; its `progress_tail` carries the
   line `Samsung Account login: opening the system browser … If it did not open, visit: <url>` —
   relay that URL if the user sees no window. Keep polling (≤ 25 s per call, up to 5 min) until
   `job.state` is `done`; the token is cached under `<tizen-sdk-data>/keystore/samsung/<p>/`.
3. Continue with `generate-samsung-author`, `generate-samsung-distributor`,
   `create-samsung-profile`, `acquire-duids-all` — each with `--background`, escalated, polled the
   same way; a valid cached token is reused without another login.

`--prompt-*` flags read the terminal and are refused together with `--background` — use
`--password-file` / `--*-password-file`. Never fall back to a local certificate because of the
sandbox or the browser wait (the only reason to use a local profile instead is a standard-emulator
target — see "Samsung certificates — TV targets only"), and do not send the user to Tizen Studio
or another harness: the flow above is the supported path.

**Codex sandbox (guard rule 12).** Run this runner — and its `--background` form — **with escalated
permissions**: it writes `profiles.xml` and keystore `.pwd` files under `<sdk>-data`, and the Samsung CA / OAuth callback need TCP sockets (the browser login is `samsung-login --background`, escalated), and Codex's default `workspace-write` sandbox blocks TCP sockets, writes
outside the workspace and (Linux) kills detached jobs when the call ends. An envelope with
`error_category: sandbox_blocked` / `sandbox_job_lost`, or a warning starting "Running inside Codex's
sandbox", means exactly that — re-run `suggested_fix.command` (the same command line, `escalate: true`)
with escalated permissions; do not retry inside the sandbox and do not fall back to raw tools.

## Actions

```
node "$CLI" generate-author --name <name> (--prompt-password|--password-file <path>) [--file <fileName>] \
  [--email <email>] [--department <dept>] [--organization <org>] \
  [--city <city>] [--state <state>] [--country <country>]

node "$CLI" list-distributors [--type public|partner|platform] [--version legacy|new]

node "$CLI" create-profile --profile-name <name> --author-cert <path> \
  (--prompt-author-password|--author-password-file <path>) [--distributor-type public|partner|platform] \
  [--distributor-version legacy|new] [--active]

node "$CLI" list-profiles [--profiles-xml <path>]
node "$CLI" set-active-profile --profile-name <name> [--profiles-xml <path>]
node "$CLI" remove-profile --profile-name <name> [--profiles-xml <path>]
node "$CLI" set-distributor2 --profile-name <name> (--prompt-author-password|--author-password-file <path>) \
  [--distributor2-type public|partner|platform] [--distributor2-version legacy|new]
node "$CLI" import-certificate --source <path> [--prompt-password] \
  [--certificate-type author|distributor] [--target-file <name>] [--overwrite]
node "$CLI" inspect-certificate --certificate <path> [--prompt-password]
node "$CLI" get-sdk-data-path

node "$CLI" generate-samsung-author --profile-name <name> --identity <identity> \
  --prompt-password [--department <dept>] [--organization <org>] \
  [--city <city>] [--state <state>] [--country <country>]

node "$CLI" generate-samsung-distributor --profile-name <name> --prompt-password \
  --duid-list <duids> [--duid-file <path>] [--privilege Public|Partner]

node "$CLI" import-samsung-certificate --profile-name <name> --source <path> \
  --prompt-password [--certificate-type author|distributor] [--overwrite]

node "$CLI" create-samsung-profile --profile-name <name> [--privilege Public|Partner] \
  [--prompt-author-password] [--prompt-distributor-password] [--active]

node "$CLI" cancel-samsung-cert

node "$CLI" samsung-login --profile-name <name>
node "$CLI" samsung-reveal-password --profile-name <name>

# DUID utilities
node "$CLI" parse-duids --duid-list <duids>
node "$CLI" import-duids --duid-file <path>
node "$CLI" acquire-duid [--serial <serial>]
node "$CLI" acquire-duids-all
```

1. **generate-author** — runs `tz cert -n <name> -p <password> -f <fileName> [...]` to create a
   local, self-signed Tizen author certificate. No network call, no Samsung account. Password must
   be at least 8 characters with an uppercase letter, a lowercase letter, and a digit — validated
   before `tz` is invoked. `--file` defaults to a sanitized version of `--name` (spaces become `-`,
   path-unsafe characters stripped) and must not already exist. On `cert_already_exists`, do not
   delete or overwrite the certificate: use `list-profiles` to check references, then reuse the
   `.p12` with `create-profile` or retry with a unique `--file`. Output `.p12` is written to
   `<tizen-sdk-data>/keystore/author/<fileName>.p12` regardless of current working directory.
2. **list-distributors** — resolves the SDK's **bundled, pre-built** distributor CA + signer `.p12`
   paths. Nothing is generated, no `tz` call — a pure filesystem read under
   `<sdk-root>/tools/certificate-generator/certificates/distributor/sdk-<type>/`. `--type` is one of
   `public`/`partner`/`platform`; `--version` is `legacy`/`new`. Omit either/both to list all
   matching combos. Not every combo is guaranteed to exist (e.g. `platform` typically has no
   `legacy` variant) — checked via real file existence, not a hardcoded matrix. If both `--type`
   and `--version` are given and that exact combo doesn't exist, returns a
   `distributor_asset_not_found` failure instead of an empty success.
3. **create-profile** — initializes the dynamic SDK-data `profiles.xml` when needed and wraps
   `tz security-profiles add`. It combines an existing author `.p12` with the selected bundled
   distributor certificate (default `public/new`) and can optionally set the profile active.
4. **list-profiles** — lists configured profiles and returns password-free author/distributor
   certificate paths with per-path availability (`available`, `missing`, `unreadable`, or
   `not_file`). Treat `certificate_files_available: false` and
   `unavailable_certificate_paths` as stale/incomplete profile state; do not describe those
   paths as available certificates.
5. **set-active-profile** — sets one existing signing profile active.
6. **remove-profile** — removes one existing profile and reports the remaining profile names.
7. **set-distributor2** — adds or replaces bundled distributor key 2 through a verified temporary
   profiles.xml transaction; the original is replaced only after `tz` succeeds.
8. **import-certificate** — validates `.p12`/`.cer` using the SDK JDK's `keytool`, then copies it
   into the dynamically resolved SDK-data keystore. Existing files require `--overwrite`.
9. **inspect-certificate** — reports parsed X.509 metadata and fingerprints using SDK `keytool`;
   `.p12` requires its password while `.cer` does not.
10. **get-sdk-data-path** — returns all dynamically resolved certificate-manager base paths.

### Samsung online-CA certificates

These are **supported**. They are a different thing from `generate-author`: the certificate is issued
by Samsung's online CA, requires a Samsung Account, and lands under
`<tizen-sdk-data>/keystore/samsung/<profileName>/` — never under `keystore/author/`.

11. **generate-samsung-author** — generates an RSA key pair and PKCS#10 CSR with OpenSSL, obtains a
    Samsung Account access token (opens the system browser for login; reuses a cached token while it
    is still valid), submits the CSR to Samsung `/apis/v3/authors`, and packages the returned
    certificate plus the bundled Samsung VD Author CA into
    `<tizen-sdk-data>/keystore/samsung/<profileName>/author.p12`. The password is stored encrypted
    via the OS credential store as `author.pwd` in the same directory — the flow writes this file
    itself, so the `.pwd` workaround below does **not** apply. Password rules match
    `generate-author`. Requires `--identity` (becomes the certificate `CN`). Never overwrites: an
    existing `author.p12` for that profile name returns `cert_already_exists`.
12. **generate-samsung-distributor** — generates an RSA key pair and a distributor CSR that includes
    DUIDs as subjectAltName URN entries, obtains a Samsung Account access token, submits the CSR to
    Samsung `/apis/v1/distributors` (and `/apis/v3/distributors` for VD mode), and packages the
    returned certificate plus the appropriate Samsung VD CA (public2 or partner2 based on privilege)
    into `<tizen-sdk-data>/keystore/samsung/<profileName>/distributor.p12`. Requires `--duid-list`
    (comma/newline separated DUIDs) or `--duid-file` (path to a file containing DUIDs). `--privilege`
    defaults to `Public`; use `Partner` for partner-level distribution. Password rules match
    `generate-author`. Never overwrites: an existing `distributor.p12` returns `cert_already_exists`.
13. **import-samsung-certificate** — imports an existing Samsung-issued `.p12` file (author or
    distributor) into a Samsung profile directory. Validates the file with SDK `keytool` before
    copying. Stores the password via OS-level secure storage. Use `--certificate-type` to specify
    `author` (default) or `distributor`. Use `--overwrite` to replace an existing certificate.
14. **create-samsung-profile** — creates a signing profile that uses Samsung-issued `author.p12`
    and `distributor.p12` (instead of bundled SDK distributor certs) via `tz security-profiles add`.
    Passwords are decrypted from OS-level secure storage (`.pwd` files) unless `--author-password`
    or `--distributor-password` is provided. Requires that `generate-samsung-author` and
    `generate-samsung-distributor` (or `import-samsung-certificate`) have been run first for the
    profile. Use `--active` to set the profile as active.
15. **cancel-samsung-cert** — aborts any active Samsung Account OAuth authentication flow, closing
    the callback server and clearing the timeout. Use when the user wants to cancel an in-progress
    `generate-samsung-author` or `generate-samsung-distributor` that is waiting for browser login.
16. **samsung-login** — performs only the Samsung Account login and caches the token for a profile.
    Useful to verify credentials separately from certificate generation.
17. **samsung-reveal-password** — decrypts and returns the stored password for a Samsung profile.

### DUID utilities

18. **parse-duids** — parses and normalizes a raw DUID string (comma/newline/whitespace separated):
    trims, uppercases, deduplicates, validates, and caps at 50 entries. Returns `{ duids, skipped,
    truncated }` — `skipped` lists invalid entries, `truncated` is `true` if the 50-DUID cap was hit.
19. **import-duids** — reads a file and parses its contents as DUIDs (same normalization as
    `parse-duids`). Returns the same `{ duids, skipped, truncated }` structure.
20. **acquire-duid** — uses `sdb capability` to extract the DUID from a connected Tizen device. If
    `--serial` is omitted, uses the first connected device. Returns `{ duid, serial, deviceName }`.
21. **acquire-duids-all** — iterates all connected Tizen devices and extracts DUIDs from each.
    Returns `{ duids: [{ duid, serial, deviceName }], errors: [{ serial, error }] }`.

**Do not substitute `generate-author` when the user asks for a Samsung certificate.** A local
self-signed Tizen certificate cannot sign an app for Samsung distribution: it is issued by
`Tizen Developers CA`, not `Samsung VD Author CA`. If the user asks for a Samsung certificate for
the TV emulator or a Samsung TV, run `generate-samsung-author`. The one exception is the target
rule above: when the target is a standard Tizen emulator, a Samsung certificate cannot be used at
all, so say so and use the local flow; when no target was named, ask first. Confirm the result by
checking that `result.cert_path` is under `keystore/samsung/` and that the envelope contains
`user_id` / `auth_source`.

**Browser login is expected.** `generate-samsung-author`, `generate-samsung-distributor`, and
`samsung-login` open the system browser and block until the user completes Samsung Account login, up
to a 5-minute timeout. This is normal — do not treat the pause as a hang, and do not fall back to a
local certificate. On timeout the envelope reports `samsung_auth_timeout`; tell the user to retry and
finish the browser login. Use `cancel-samsung-cert` to abort an in-progress login.

**Complete Samsung profile workflow:** A complete Samsung signing profile requires both an author
and a distributor certificate. The typical workflow is:
1. `generate-samsung-author` — creates `author.p12` + `author.pwd`
2. `acquire-duid` or `acquire-duids-all` — get DUIDs from connected device(s)
3. `generate-samsung-distributor` — creates `distributor.p12` + `distributor.pwd` using the DUIDs
4. `create-samsung-profile` — registers the signing profile with `tz security-profiles add`

Alternatively, if the user already has Samsung-issued `.p12` files (e.g., from Tizen Studio), use
`import-samsung-certificate` for each, then `create-samsung-profile`. Never pair a Samsung author
certificate with a bundled Tizen distributor certificate — always use `create-samsung-profile`
(not `create-profile`) for Samsung profiles.

Exit code: `0` = success envelope, `1` = failure/error envelope (JSON on stdout).

**Success result (generate-author):** `result.cert_path` = the generated `.p12` path,
`result.pwd_path` = the expected `.pwd` sidecar path, `result.pwd_file_exists` = whether `tz cert`
wrote it. This certificate is a **standalone author key** until it is attached with
`create-profile`; `tz build -s <profile>` requires that signing profile.

**Success result (list-distributors):** `result.sdk_root` = the resolved SDK root,
`result.distributors` = `[{ type, version, ca_path, signer_path }]` for every combo that exists on
disk, `result.unavailable` = `[{ type, version }]` for combos that were checked but don't exist
(informational, not an error) — narrower when `--type`/`--version` filters were given.

**Where files are written/read:** `<tizen-sdk-data>/keystore/author/<fileName>.p12` and
`<sdk-root>/tools/certificate-generator/certificates/distributor/...` — but neither
`<tizen-sdk-data>` nor `<sdk-root>` is ever a fixed or hardcoded path. Both are resolved dynamically
at runtime: `<sdk-root>` comes from whatever path is stored in `~/.tizen.sdk.path.config` (written by
`tizen-sdk-init`) — **not** from any `TIZEN_SDK_PATH` / `TIZEN_SDK_ROOT` environment variable — and
`<tizen-sdk-data>` comes from `TIZEN_SDK_DATA_PATH` in `<sdk-root>/sdk.info`. This can resolve to any
drive or directory layout depending entirely on how the specific user installed the SDK — always
read `result.cert_path` / `result.sdk_root` / `result.distributors[].ca_path` from the envelope
rather than assuming a location.

## 결과 보고 — Envelope는 반드시 사용자에게 보여준다

러너의 stdout JSON Envelope는 **도구 결과 안에 있어서 사용자에게는 보이지 않는다**
(Claude Code UI는 Bash/Agent 결과를 "Ran 1 shell command"처럼 접어 둔다). 사용자에게
보이는 것은 최종 답변 텍스트만이므로, 최종 답변은 **어느 실행 경로(서브에이전트 위임 /
CLI Runner 직접 실행)든** 아래 형식을 따른다:

1. Envelope JSON을 **수정·축약 없이 그대로** fenced `json` 블록에 싣는다 (첫 항목).
2. 그 아래에 결과 요약을 **1~2줄**만 덧붙인다 (`result`의 핵심 값 또는 `errors[0].message` 요지).
3. 필요하면 다음 단계 제안을 1줄 추가한다.

- Envelope를 산문 목록으로 풀어 쓰고 JSON을 생략하는 것은 **형식 위반**이다. 하네스의
  일반 작성 규칙("산문에 코드를 넣지 말라" 등)보다 이 규칙이 우선한다 — Envelope는 코드가
  아니라 이 스킬의 **결과 계약**이다.
- 러너를 여러 번 실행했으면 **마지막 실행**의 Envelope를 싣고, 이전 실패는 요약 줄에서
  한 줄로만 언급한다.
- 실패 Envelope도 동일하게 원문을 싣는다. `errors[0].message`/`details`를 다시 타이핑하지
  말고 JSON 안의 것을 그대로 보이게 한다.
- `user_input_required` Envelope는 그대로 보여준 뒤 사용자에게 질문한다.

## Handoff

- **Single-task** (e.g., "타이젠 인증서 만들어줘") → DONE. Report envelope, mention `result.cert_path`.
- **Single-task** (e.g., "배포자 인증서 목록 보여줘") → DONE. Report `result.distributors`
  (and `result.unavailable` if relevant).
- **Single-task** (e.g., "삼성 인증서 만들어줘", "create a Samsung certificate") → first confirm the
  target is the TV emulator or a Samsung TV (see "Samsung certificates — TV targets only"), then
  `generate-samsung-author`. Report `result.cert_path` (under `keystore/samsung/`) and
  `result.user_email`. Standard-emulator target → `generate-author` → `create-profile` instead.
- Samsung flow requested but no TV emulator exists → `tizen-tv-sdk-install` →
  `tizen-create-emulator --profile tv` → `tizen-launch-emulator`
- SDK not installed → `tizen-sdk-install`, then `tizen-sdk-init`

## The `.pwd` password sidecar (`generate-author`)

**Applies to `generate-author` only — never to `generate-samsung-author`.**

On some SDK versions `tz cert` generates the `.p12` author certificate but **does not** create
the companion `.pwd` file (the password sidecar). Without it, `tz security-profiles add` and
`tz build -s <profile>` cannot resolve the author password and packaging fails with an opaque
decryption error (issue #75). The runner now **writes the sidecar itself** when `tz cert` did
not (plain text, mode 600, same content the old manual step wrote) and reports
`result.pwd_file_created: true` plus a warning; `result.pwd_file_exists` is true either way.
Nothing to do by hand.

If the write itself failed (a `warnings` entry says so — typically Codex's sandbox denying
writes under `<tizen-sdk-data>`), re-run `generate-author` **with escalated permissions**; the
existing `.p12` is detected and only the sidecar is added. Restoring it manually is still
possible with the same password:

```bash
echo -n '<password>' > "<tizen-sdk-data>/keystore/author/<fileName>.pwd"
chmod 600 "<tizen-sdk-data>/keystore/author/<fileName>.pwd"
```

The build pre-check (`tizen-build-project`) now refuses to package with a profile whose author
`.p12` has neither a `.pwd` sidecar nor a password stored in `profiles.xml`
(`signing_profile_invalid`, message names the missing file) instead of failing inside `tz`.

Do **not** apply this to a Samsung profile. `generate-samsung-author` writes its own `author.pwd`
containing an OS-encrypted blob, not plaintext; overwriting it with `echo` would corrupt the stored
password. Use `samsung-reveal-password` to check a Samsung profile's password instead.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.