Command line

Invite a partner ​

Write the agreed terms into a configuration, create the invitation from it, and run the first exchange with your partner.

Command line

For
An IT engineer whose organization creates the invitation
You need
Alcove installed, your input CSV, the terms you agreed on, and an SFTP directory, shared folder or WebRTC
Before this
Agree on terms
Your partner reads
Accept an invitation
Timing
The invitation lasts 1 hour unless you set --expires-in, up to 365d. Each side waits 1 hour for the other, 10 minutes on WebRTC. A 20-record test run takes about 1 minute over a shared folder and about 14 minutes over SFTP.

Set up and invite ​

YouYour partnerBoth of you

1Make a folder for this partner ​

Make one folder for this exchange, put your input file in it as input.csv, and run every command below from that folder. It will hold the configuration (alcove.yaml), the key file (.alcove.key) and each run's results.

WARNING

Keep this folder between runs, and run the exchange from one machine only. The key file changes after every run; if it is lost or a stale copy runs, both of you must start over with a new invitation.

2Write the configuration ​

alcove init writes alcove.yaml from your file's columns and fills the connection block from the address you give it.

If you run the server, set it up first: If you run the SFTP server.

sh
alcove init --identity "Northside Health Plan" sftp://[email protected]/exchanges/plan-coc input.csv

For a port other than 22, put it after the host: sftp://[email protected]:2222/exchanges/plan-coc.

Then put the account's password in a file named passwd in this folder, and add this line under connection.server in alcove.yaml:

yaml
    password: "@passwd"

For an SSH key, write private_key: "@id_ed25519" instead, with the key file in this folder.

You should see: wrote a configuration template to ./alcove.yaml.

3Set the terms in alcove.yaml ​

Make each edit you agreed on. What each one means: Agree on terms.

Columns you send (What each of you sends). Columns alcove init did not recognize are listed, commented out, at the end of the metadata block. Remove the # marks from each one you agreed to send:

yaml
  - name: Renewal.Date
    type: other
    role: payload
    is_payload: true

A column with is_payload: false, or not listed, is not sent.

Your ID column. Set your own ID column, whatever it is called: its entry reads role: identifier. Your result then starts each row with your own ID. With is_payload: false your partner never receives it; to send it for matched records, change that to is_payload: true. Alcove recognizes common ID names, such as id, Client ID, MRN, and case_number (inference table), and writes an entry for the first one with is_payload: false, taking a record number such as case_number only when the file has no other ID column. A name Alcove does not recognize is listed commented out at the end of metadata with is_payload: true. Do not just remove the # marks from its listed entry: that entry sends it. Write its entry as below in place of the listed one, with your column's name. With no ID column, your result holds row numbers only, counting from 0.

yaml
  - name: Client_Number
    type: identifier
    role: identifier
    is_payload: false

Columns you ask your partner for. Optional. Under linkage_terms, add the columns your partner agreed to send, and your partner sees them as a request when accepting; if linkage_terms already has a payload: line, add receive: under it. Without the request, the first exchange records whichever columns your partner sends, and later runs refuse a different list. For example:

yaml
  payload:
    receive:
      - name: Case_Manager_Phone_Number

Keys (What you match on). linkage_terms.linkage_keys holds the Broader matching keys your file supports. To leave out the three less certain keys, delete the entries named LN + FN + DOB, swap(LN, FN) + DOB and split(LN) + FN + DOB, each with every line under it. The comment above linkage_keys that begins "To run the highest-precision rules only" names the further keys to delete.

Who receives the result (Who receives the result). Set linkage_terms.output:

OptionWhat it doesPick it when
expects_output: true, share_with_partner: trueBoth of you get a results file.Usualboth of you act on the matches.
expects_output: true, share_with_partner: falseOnly you get one. You send no columns.Only you need the list. Your partner sees no list, and no count outside a debug log (A list or only a count).
expects_output: false, share_with_partner: trueOnly your partner gets one. Your partner sends no columns, so leave out payload.receive.Only your partner needs the list.

A list or only a count (A list or only a count). For a count, set algorithm: psi-c, delete every key in linkage_keys but one, set every column to is_payload: false, and add no payload.receive.

4Create the invitation ​

alcove invite takes its terms from alcove.yaml and prints the invitation. Run it without -it, so only the invitation goes into the file:

sh
docker run --rm --user "$(id -u):$(id -g)" -v "$PWD":/work ghcr.io/georgetown-mdi/alcove:latest invite --expires-in 2d input.csv > invitation.txt

The invitation lasts 1 hour without --expires-in. Give it time for your partner to accept and for the first exchange: 2d is 2 days, and 365d is the longest.

You should see: derived the invitation's linkage terms from ./alcove.yaml, then the expiry in your local time. .alcove.key is now in the folder.

The terms are fixed once the invitation exists. To change them, delete .alcove.key, which also withdraws the invitation, edit alcove.yaml, and run alcove invite again.

5Send your partner the invitation ​

Send:

  • invitation.txt, as an attachment over encrypted email or your secure file transfer. It runs to about 9,000 to 10,300 characters, so it cannot be read aloud. It holds a one-time secret: anyone who has it can take your partner's place.
  • The page to follow: Accept an invitation for a partner on the command line. For the console or the web app, see If your partner uses the console or the web app.
  • On SFTP: the server's host name and port, their account, the directory, and the server's fingerprint (below, If you run the SFTP server).
  • When you both run the first exchange, before the invitation expires.

6Both of you: run the first exchange ​

Your partner accepts first and, on SFTP or a shared folder, fills in the connection in their alcove.yaml with what you sent in step 5 (Fill in the connection). Then, at the agreed time:

sh
alcove exchange input.csv ./

The first run shows the server's fingerprint and asks Trust this host key for sftp.example.org? [y/N]. Check it against the one from your server's administrator before answering y; Alcove saves it in alcove.yaml. To skip the question, add host_key_fingerprint: SHA256:... under connection.server first.

You should see: exchange complete: 10 records matched, result written to the results file, with your own count, and the command exits 0. If the terms give you no result, you see exchange complete: no result file for you under the agreed terms; exchange record written to ... instead, also with exit 0.

  • Your partner never arrives: after 1 hour (10 minutes on WebRTC) the run exits 69 and says your partner did not arrive. The key file is unchanged; run again.
  • The server refuses your password or key: after 3 retries the run exits 69 with All configured authentication methods failed. Fix the credential; running again unchanged does not help.
  • The run is interrupted: it may print Retry with the same key file; if authentication fails on retry, ask your partner for a new invitation. Either way, run again with the same key file.
  • Any other failure prints the error and the next step, and exits with a code from Exit codes.

Practice, then go live ​

Practice first with a test file: about 20 made-up records under the same column names as your real file. Your partner does the same with theirs. Run steps 1 to 6 with it.

For the real exchange, start again in a new folder, so the test's key file and results stay apart from the real ones.

1Copy the configuration ​

Make a new folder. Copy alcove.yaml and any password or key file into it, and put your real input.csv beside them.

2Invite again ​

From the new folder, run step 4 and send the new invitation as in step 5. On SFTP or a shared folder, check the directory is empty before the real run: a file from another exchange stops it.

3Your partner: accept in a new folder ​

Your partner follows Accept an invitation again, in a new folder with their real file.

If your partner uses the console or the web app ​

The console and the web app run an invitation only if it names where the exchange happens. An invitation from step 4 names it only on the WebRTC channel.

ChannelYour partner uses the web appYour partner uses the console
WebRTCSteps 1 to 6, WebRTC tabSteps 1 to 6, WebRTC tab
SFTP or a shared folderNot possible: the web app runs WebRTC onlyYour partner invites from the console (Invite from the console), and you accept with Accept an invitation. Or, on SFTP, if the default terms are what you agreed on, invite with the server's address on the command, below.

Send the invitation text with Accept with the web app or Accept in the console. In the web app, your partner pastes it under Have an invitation? Paste it here.

1Invite a console partner with the server's address on the command ​

This one command prints the invitation, waits for your partner to accept, and runs the exchange. It takes its terms from your file's columns, not from alcove.yaml: Broader matching, both of you receive the result, a list of matched records, and each column's use as Alcove infers it from its name. No column is sent to your partner, your ID column included. Run it in a new folder holding only input.csv and passwd: it stops if alcove.yaml or .alcove.key is there.

sh
docker run --rm --user "$(id -u):$(id -g)" -v "$PWD":/work ghcr.io/georgetown-mdi/alcove:latest invite --identity "Northside Health Plan" --expires-in 2h --accept-timeout 2h --server-password @passwd --server-host-key-fingerprint SHA256:... sftp://[email protected]/exchanges/plan-coc input.csv ./ > invitation.txt

--accept-timeout is how long it waits for your partner to accept (15 minutes without it). Set --expires-in at least as long, or the invitation expires first. The fingerprint is the server's, from Read the fingerprint. Leave the command running and send invitation.txt: it already holds the whole invitation.

You should see: exchange complete: 10 records matched, result written to the results file, and the command exits 0. It saves alcove.yaml, with the password as "@passwd" and the fingerprint pinned, and .alcove.key, so later runs use alcove exchange input.csv ./ from this folder.

If you run the SFTP server ​

Set these up before you send the invitation.

1Make the accounts ​

Make an account on the server for your partner, and one for you.

2Make the directory ​

Make one directory both accounts can read and write, used by this exchange only. A file from another exchange in it stops the run.

3Read the fingerprint ​

sh
alcove probe-host-key sftp://sftp.example.org

It prints sftp.example.org presented a ... host key with fingerprint SHA256:.... Confirm it against the server itself, then send it to your partner and put it in your own host_key_fingerprint.

More detail: How host-key pinning works, Every connection setting by channel.

What you get ​

FileWhat it holdsShare or keep
invitation.txtThe invitation, with its one-time secret.Send to your partner only
alcove.yamlThe terms and connection.Keep; not secret if credentials are @ file references
.alcove.keyThe shared secret. It changes after every run.Keep private
alcove-results-<time>.csvYour matched records: your ID, row_id (your partner's row number, counting from 0), then the columns your partner sends.Keep private
alcove-record-<time>.jsonThe exchange record of this run.Keep; not secret
alcove-record-<time>.keys.jsonThe values that open the record's checks.Keep private
alcove-record-<time>.terms.jsonBoth parties' agreed terms.Keep; not secret

A count-only run writes no results CSV. All files: Install and run.