SmSn Server - synchrony/smsn GitHub Wiki

SmSn follows a client-server pattern in which there are multiple potential clients, and a single server application called SmSn Server. This page assumes that you have already started SmSn server, and contains details on communicating with it.

SmSn Server runs as a standalone Java application and listens on WebSocket port 8182 by default; connect to ws://localhost:8182/smsn.

The following is a simple program in Python (suitable for a Jupyter Notebook) which you can use to experiment with SmSn's WebSocket communication:

import asyncio
import websockets
import json

def toRequestJson(action_json):
  return {
    "op":"eval",
    "processor":"session",
    "args":{
        "language":"smsn",
        "session":"undefined",
        "gremlin":json.dumps(action_json)}}

async def issueSmSnRequest(actionJson, callback):
    serverUrl = "ws://localhost:8182/smsn"

    try:
        async with websockets.connect(serverUrl) as websocket:
            jsonString = json.dumps(toRequestJson(actionJson))

            # Send the JSON string to the WebSocket server
            await websocket.send(jsonString)

            # Receive and print the response from the WebSocket server
            response = await websocket.recv()
            responseJson = json.loads(response)
            if responseJson["status"]["code"] == 200:
                callback(json.loads(responseJson["result"]["data"][0]))
            else:
                print("Error status:")
                print(responseJson["status"])

            callback(response)

    except Exception as e:
        print(f"An error occurred: {e}")

def printResult(result):
    print(f"Result from SmSn server: {result}")

async def smsnSearch(searchTerm, callback=printResult):
    actionJson = {
        "action":"net.fortytwo.smsn.server.actions.Search",
        "filter":{
            "minSource":"private",
            "defaultSource":"private",
            "minWeight":0.0,
            "defaultWeight":0.5},
        "titleCutoff":100,
        "style":"forward",
        "queryType":"FullText",
        "query":searchTerm,
        "height":1}
    await issueSmSnRequest(actionJson, lambda r: callback(r["view"]["children"]))

Now apply the above to a search term, e.g.

await smsnSearch("*hello*")

Available Actions

The server supports the following action classes in net.fortytwo.smsn.server.actions:

Action Description
Search Full-text search by title
GetView Get a tree view of a note and its children
UpdateView Update notes from a tree view
SetProperties Set properties on a note
FindRoots Find notes with no parents
FindIsolatedNotes Find notes with no parents or children
RemoveIsolatedNotes Delete isolated notes
FindDuplicates Find notes with duplicate titles
GetHistory Get VCS commit history
Ping Health check
GetConfiguration Get server configuration

See the Installation guide for setup instructions.

Authentication

SmSn Server supports optional authentication to control access to your knowledge base. When enabled, clients must provide a secret token to gain full access; otherwise they are treated as anonymous users with limited permissions.

Configuration

Add an authentication section to your smsn.yaml:

authentication:
  enabled: true
  token: "your-secret-token-here"
  publicSources:
    - public
    - universal
Field Description
enabled Set to true to enable authentication (default: false)
token Secret token that clients must provide for full access
publicSources List of source names that anonymous users can read

Connecting with Authentication

To authenticate, include the token as a query parameter when connecting:

ws://localhost:8182/smsn?token=your-secret-token-here

Without a valid token (or with authentication.enabled: false), the connection is treated as anonymous.

Permission Model

Operation Authenticated Anonymous
Read from any source
Read from public sources
Search (all sources)
Search (public sources only)
Write operations (SetProperties, UpdateView, etc.)
Import/Export

Security Considerations

  • Use TLS in production: The token is sent in the URL query string. Without TLS, it can be intercepted. Use a reverse proxy (nginx, Caddy) to terminate TLS.
  • Bind to localhost: If not using a reverse proxy, consider binding the server to 127.0.0.1 instead of 0.0.0.0 to prevent remote access.
  • Keep tokens secret: Treat the token like a password. Don't commit it to version control.

Example: Reverse Proxy with Caddy

For secure public access, use Caddy as a reverse proxy:

smsn.yourdomain.com {
    reverse_proxy /smsn localhost:8182
}

Caddy automatically obtains and renews TLS certificates. Clients connect via:

wss://smsn.yourdomain.com/smsn?token=your-secret-token-here