Skip to content
Back to skills

Update Publist

BSecurity

Add or update a publication on the personal page and deposit on HAL via SWORD. Gated on user payload review before any outward API call.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 19, 2026
content-marketinggoshellgitapi

Works with

  • terminal
  • api

Security analysis

B88/100
  • criticalSends environment variables or credentials to an external URL

Pro scans all 2 files and shows the line behind each finding

Scanned October 19, 2026

npx -y skills add MinhHaDuong/ImperialDragonHarness --skill update-publist --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Update Publist?

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

Security grade badge for Update Publist
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/minhhaduong-update-publist/badge)](https://www.skillsdirectory.com/skills/minhhaduong-update-publist)

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: update-publist
description: "Add or update a publication on the personal page and deposit on HAL via SWORD. Gated on user payload review before any outward API call."
disable-model-invocation: true
user-invocable: true
argument-hint: "<pdf-path> [--hal-only] [--page-only]"
---

# Update publication list

For helper commands, set `IDH_ROOT="$(cd -P "$(dirname "<loaded-SKILL.md>")/../.." && pwd -P)"` in the same shell call. Replace `<loaded-SKILL.md>` with the absolute path the runtime supplied for this skill. This follows a projected skill symlink to the canonical checkout; do not derive the helper root from the project cwd.

Two independent steps, either runnable alone via flags (`--page-only`
runs Step 1 only; `--hal-only` runs Step 2 only). Both are
outward-facing and irreversible once completed — every mutation requires
explicit user confirmation before execution.

## Step 1: Personal page (`~/CNRS/html/`)

This directory is NOT a git repo. It deploys over FTP.

1. Copy the PDF into `files/`, naming it `HaDuong-YYYY-Topic.pdf`.
   Use a `-EN` suffix for English translations.

2. Add the BibTeX entry to `src/Ha-Duong.bib`. The page section is
   driven by the entry type:
   - `inproceedings` maps to Scientific communications
   - `unpublished` maps to Teaching and conferences
   - See `TYPE_HEADINGS` in `src/bib2htm.py` for the full mapping.
   Required fields: `file = {files/HaDuong-YYYY-Topic.pdf}`. Add
   `eprint = {https://hal.science/hal-XXXXXXXvN}` after HAL deposit.

   Pick the type from the publication's *status*, not its venue:

   | Status | Type | Notes |
   |--------|------|-------|
   | Peer-reviewed and accepted | `@article` | `journaltitle`, `doi` |
   | Under review / preprint | `@techreport` | `type` = "Preprint, under review at {Journal}". **No** `institution` field |
   | CIRED Working Paper series | `@techreport` | The only case that gets `institution = {CIRED}` |
   | Conference presentation | `@inproceedings` | `booktitle`, `location`, `date` |
   | Dataset | `@misc` | `howpublished = {Zenodo}`, `doi` |
   | Book | `@book` | `publisher`, `isbn` |

   The preprint/CIRED-WP split is the one that gets fixed wrong: an
   `institution` field on a preprint makes the page render it as
   CIRED-published work it is not.

   Field conventions: `doi` bare, no URL prefix (`10.5281/zenodo.19097045`);
   `date` in ISO form (`2026-03-18`); `eprint` the full HAL URL.

3. **Translation pairs.** For a translated work:
   - The translation key gets an `:EN` suffix.
   - On the translation: `related = {OriginalKey}`,
     `relatedtype = {translationof}`.
   - On the original: `related = {TranslationKey:EN}`,
     `relatedtype = {translatedin}`.
   - The renderer merges them into one item (translation first, original
     bracketed). Disambiguate identical titles with a marker like
     "(En francais)".

4. Build and verify:
   ```
   cd ~/CNRS/html && make index.html && make files/Ha-Duong.bib
   ```
   Verify the entry appears in the correct section (`grep` the output).

5. **Publish (user confirmation required):**
   ```
   make sync
   ```
   This runs FTP using credentials from `~/.netrc`. Show the user what
   will be synced and wait for explicit confirmation before running.

## Step 2: HAL deposit via SWORD

Credentials: `HAL_ID` and `HAL_PASSWORD` live in `~/.config/keys/hal.env` and
are resolved **at point of use**, one variable per call, by
`"$IDH_ROOT/skills/update-publist/resolve_hal_credentials.sh"` — see § 2c, which
is the only place in this skill that runs it.

The ambient environment is **no longer consulted**: a `HAL_ID` or
`HAL_PASSWORD` already exported in the shell does not take precedence and has
no effect at all. That is deliberate. Their presence used to depend on the
`KEYS=` selection in force, and a project `KEYS=` **replaces** the harness one
rather than adding to it (ticket 0360), so the deposit failed as an ordinary
HAL auth error whenever it was run from a project whose `.env` carried its own
`KEYS=` line. Point-of-use resolution bypasses that layer, so there is nothing
left to probe for before starting: the resolver itself fails loud and named,
and covers the cases a presence probe never did (missing or malformed
`hal.env`, a variable defined but empty).

**Never echo, display, log, or commit credential values.** Pass them
to curl via a chmod-600 temporary config file (`curl -K`), never on the
command line. Mask `<hal:password>` in any displayed API response.

### Pre-upload PDF review (GATE)

Read **every page** of the PDF with vision before building any metadata.
This checks the *document*; the 2b gate checks the *payload*, and neither
substitutes for the other — a well-formed TEI can wrap an anonymized draft.

- The author's name appears in the document (no "[Anonymous]", no
  anonymized review version).
- Affiliations are present and will match the HAL metadata.
- No placeholder text and no draft watermark contradicting the deposit
  status.
- The file is complete: all pages, figures and tables render.
- Nothing sensitive is embedded — API keys, personal addresses beyond
  the correspondence one.

Guidelines: https://doc.hal.science/en/deposit/

Only proceed once the review passes.

### 2a. Prepare the TEI metadata

Use the AOfr TEI format (template reference:
`https://api.archives-ouvertes.fr/documents/all.xml`).

Before choosing doctype and domain, check the author's previous deposits
via the public search API to follow established conventions:
```
curl -s 'https://api.archives-ouvertes.fr/search/hal/?q=authIdHal_s:minh-ha-duong&fl=docType_s,domain_s&rows=5'
```

Standard values for this author:
- Structure: `#struct-1380080` (CIRED). **Verified against the HAL ref API,
  2026-07-27** — a fork of this skill carried `struct-1002424`, which
  resolves to ECOSYS, an unrelated laboratory. Do not "correct" this id
  from another document; re-verify it instead:
  `curl -s 'https://api.archives-ouvertes.fr/ref/structure/?q=docid:1380080&fl=docid,name_s,acronym_s&wt=json'`
- ORCID: `0000-0001-9988-2100`
- idhal: `minh-ha-duong`
- Typology: `COMM` for a conference talk (adjust per doctype)
- Stamps: CIRED, CNRS
- Domains: `shs.eco`, `shs.hisphilso` (adjust per paper)
- File reference in the TEI:
  `<ref type="file" target="paper.pdf" subtype="author" n="1"/>`

For a journal article, resolve the journal's HAL id rather than typing
the title into the TEI:
```
curl -s 'https://api.archives-ouvertes.fr/ref/journal/?q=title_t:{name}&fl=docid,title_s,valid_s&wt=json'
```
Use the `docid` as `halJournalId`, and prefer an entry whose `valid_s`
is `VALID`.

### 2b. Assemble and review the payload

Build `meta.xml` (the TEI document) and zip it with the PDF.

**MANDATORY GATE: show the user the full assembled payload** — the
complete `meta.xml` TEI content and the zip manifest — and wait for
explicit confirmation before any API call. The user reviews:
- TEI well-formedness and field accuracy
- Correct structure reference (`#struct-1380080`)
- Correct typology and domain
- Correct idhal

Do NOT proceed to the POST without user approval.

### 2c. Deposit

Resolve the two credentials immediately before building `$TMPCONFIG`, into
shell variables that go into that chmod-600 file and nowhere else:

```
RESOLVE="$IDH_ROOT/skills/update-publist/resolve_hal_credentials.sh"
HAL_ID_VALUE="$("$RESOLVE" HAL_ID)" || exit $?
HAL_PASSWORD_VALUE="$("$RESOLVE" HAL_PASSWORD)" || exit $?
```

**Guard each call separately, and let the resolver's stderr reach you** — do
not redirect it away, and do not collapse the two calls into one unguarded
line. A partial resolution (`HAL_ID` resolves, `HAL_PASSWORD` does not) builds
a half-empty config and comes back as an HAL *auth* error, one layer away from
the real cause.

**The stderr line is what tells you what went wrong**, and it is the one to
read back to the user: one line naming the VARIABLE and the FILE, never a
value. The exit code is a coarse companion — `1` bad argument, `2` keystore
file missing, unreadable, not a regular file or over the size cap, `3` keystore
file could not be sourced or did not run to completion, `4` variable absent or
defined-but-empty, `5` value spans more than one line — and `|| exit $?` above
is what keeps it, rather than flattening every case to 1.

```
curl -K "$TMPCONFIG" \
  -X POST https://api.archives-ouvertes.fr/sword/hal/ \
  -H 'Content-Type: application/zip' \
  -H 'Content-Disposition: attachment; filename=deposit.zip' \
  -H 'Packaging: http://purl.org/net/sword-types/AOfr' \
  --data-binary @deposit.zip
```

Where `$TMPCONFIG` is created with `mktemp` in `/tmp` (outside the
repo tree), chmod-600'd, and cleaned up via `trap 'rm -f "$TMPCONFIG"' EXIT`
so it is deleted even on error or interruption. Write it with a redirect —
never by echoing the line to the terminal first:
```
_kesc() { local s=${1//\\/\\\\}; printf '%s' "${s//\"/\\\"}"; }
printf 'user = "%s:%s"\n' "$(_kesc "$HAL_ID_VALUE")" "$(_kesc "$HAL_PASSWORD_VALUE")" \
  > "$TMPCONFIG"
```
Two properties of that line, both load-bearing. `printf` is a shell builtin, so
the values never reach a process argv where `ps -ef` could read them — which
`echo` via an external command, or `curl -u user:pass`, would. And a `curl -K`
quoted string is backslash-escaped, so a `"` or `\` inside a password would
otherwise terminate the string and turn the rest of the credential into curl
*directives*; `_kesc` escapes both, backslash first.

`_kesc` handles the quoting layer and only that layer. The other way a value
can break this file is a **line** boundary — `curl -K` parses one directive per
line, so an embedded newline truncates the credential and feeds its tail to
curl as a directive, and no amount of quoting reaches below that. That case is
refused upstream, by the resolver, with exit `5`; do not try to escape it here.

**Dry run first.** The same request with `-H "X-test: 1"` validates the
package without creating a record. Run it, read the response, and only
then repeat without the header.

**Updating an existing deposit** is the same request as a `PUT` to
`https://api.archives-ouvertes.fr/sword/hal/{hal-id}`. Use it rather
than a second POST — a second POST creates a duplicate record, and
duplicates need moderator action to merge.

The SWORD acknowledgement means "stored in workspace" — moderation
status is confirmed by HAL's email, not the API response.

### 2d. Post-deposit

After a successful deposit, update the BibTeX entry in
`src/Ha-Duong.bib` with the `eprint` field pointing to the new HAL
record, then rebuild the personal page (Step 1.4-1.5).

If the run happened inside a project that tracks HAL ids in its
`STATE.md`, update them there too — a stale HAL id in project state is
the usual way a second deposit gets made for a record that already
exists.

## Credential safety rules

These are non-negotiable:
- Never display `HAL_ID` or `HAL_PASSWORD` values in chat output.
- Never include credentials in git-tracked files.
- Pass credentials to curl via `-K` with a chmod-600 temp file only.
- Mask any credential that appears in API responses before displaying.
- Delete temp credential files immediately after use.

Files in this skill

  • SKILL.md10.9 KB
  • resolve_hal_credentials.sh9 KB

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.