Providing files, and giving them back

Brigitte Bigi

Problem and scope

Description

The apps of swapp process files. They do not choose them: the files come from the working context of the person, not from the tool she happens to be using. What carries them is a workspace, and a workspace does not fill itself.

The person has her files where she works. SPPAS runs where it is installed, which is her own machine or a server, and the two are not always the same one. Everything to be settled follows from that gap: how a file she holds gets to where an app reads it, how she says which ones are to be treated, and how what an app produced comes back to her.

An app asks for what it needs and treats what it receives, and it says for itself whether what it received is enough. What it asks for, and what the person gives, is the whole of the question.

Needs

The needs are those of the person. They name no technique: the means of satisfying them belong to the levels below.

  • B1 — To have an app work on the checked files of the workspace, without checking them again in every app.
  • B2 — To give files to SPPAS, and to check among them those an app is to treat.
  • B5 — To have SPPAS read the files she gives it, whether or not it runs on her machine.
  • B6 — To know that nothing of what was given is kept.
  • B7 — To know what quantity of files SPPAS accepts.
  • B8 — To know what size of file SPPAS accepts.
  • B9 — To find what an app produced among her own files, ready for the next thing she does with them.
  • B11 — To know which files SPPAS accepts.
  • B12 — To get back the files which were produced, or where they are.
  • B13 — To see which files were grouped together, and what they produced.
  • B14 — To correct what one has fed, before giving it.
  • B15 — To know where one stands against what is accepted, while feeding.

B5 is the need which holds the two situations together without naming either: where SPPAS runs on the machine of the person the file is already there and there is nothing to do; where it does not, the file has to get there — and the place it gets to is asked of a neighbour, which is all this domain knows of it.

B9 and B12 are two moments of one thing, and this domain serves both: what an app produced is added to the files which are known and checked among them, by this domain and never by the app, so that the next treatment finds it already designated; and it is reachable by the person wherever she reads it.

Scope

This document covers the provision of files to an app, and the return to the person of the files an app produced: where the files come from, what is handed over, when, and how what was produced is reached.

The two directions are one design and not two. A file is in place and the workspace says where it is, or it has to travel and it stands in a place a neighbour gave, bounded and perishable, which the person reaches at an address. An app says what it has produced and says when it has finished, and the delivery holds to those two.

What is not covered: the workspaces, whose functioning is established and which belong to their own domain; the place where a file stands when it had to travel — what names it, how long it lasts, who may reach it — which is an API of its own with a dossier of its own; and what an app does with the files it receives, and whether they suffice it.

Modelling

Data dictionary

Six things are handled, and they are all that is handled. The person and the apps are not among them: they are actors, and they belong to the model of communication. The words are those of the SPPAS code, and no others — save one, which the code does not carry yet, and which is said where it stands.

  • D1. The file — an object stored on a machine, identified by its name where it stands. A workspace retains its name, not its content: the content is read at the moment of the treatment. What is manipulated here is its name and its size.
  • D2. The state — one single value, carried by every file of a workspace and taken from States(): MISSING, UNUSED, CHECKED or LOCKED, and these four only.
  • D3. Checked — the CHECKED value of the state. It alone says that a file is to be treated.
  • D4. The workspace — the set of the files which are known, held on three levels — the path, the root, the file — each one carrying its state, together with the references. It is what carries the set to be treated, and what is handed to an app is made from it. One is active at a time.
  • D5. The copy — a duplicate of a file, made where the app works, because the original is not there. It is a file in the sense of D1, and it stands in a place the deposit API gave: bounded and perishable, on that domain's terms and not on ours. A file an app produced is not a copy: it is an original, and it perishes because it stands there too.
  • D6. The deposit — the copies given at one time. It exists while it is fed, and it knows the place the deposit API gave it once it is given. It is what a total volume is counted on, and what tells two copies of one name apart. This is the word the code does not carry yet.

Conceptual model of communication

The domain studied does two things: it gives an app the files it is to treat, and it gives the person back what that app produced. Nothing else. Four actors border it, two of which are neighbours it calls. The interfaces through which the person acts are not actors: they are what this document designs — the one where she feeds what she gives, and the one where she reaches what was made.

Actors

  • A1. The person — she gives her files, says which of them are to be treated, asks for an app, and gets back what was produced.
  • A2. An app — it asks for what it needs in order to work, judges whether what it received suffices it, and produces files.
  • A3. The domain of the workspaces — the neighbouring system which holds the files that are known and their states.
  • A4. The deposit API — an API, and no face: it gives a bounded and perishable place where a file may stand when it is not on the machine of the person, says what it accepts, gives an address at which one of them is reached, and forgets what is out of date without being asked.

Flows

  • F1. A1 → domain — her files, and which of them are to be treated (B2, B5).
  • F2. A2 → domain — the request for the files it is to treat (B1).
  • F3. domain → A1 — what is accepted, before anything is given, and that nothing is kept (B6, B7, B8, B11).
  • F4. domain → A3 — the files to be known, their checking, and the states this domain sets on them (B2).
  • F5. A3 → domain — the workspace and the states of its files (B1).
  • F6. domain → A2 — a workspace holding the files to be treated, and them only (B1).
  • F7. A2 → domain — what it has produced, in the workspace it was given, as often as it has something to give back (B12).
  • F8. A2 → domain — the treatment is over.
  • F9. domain → A3 — the files produced, added and checked (B9).
  • F10. domain → A1 — the files produced, reached where they are or at an address, and what was grouped with what (B12, B13).
  • F11. domain → A1 — what was not taken in, and why; and where she stands against what is accepted (B14, B15).
  • F12. domain → A4 — the request for a place, the files to put there, and the request for an address.
  • F13. A4 → domain — what it accepts, the place it gives or its refusal with when to come back, and the address at which a file is reached.
  • F14. A2 → domain — the request for files, when what it received does not suffice it.

It is the domain which writes into the workspace — what it was given to make known, and what an app produced, on the word of that app (F7, F9). The app never writes there itself, for it never holds it. RO9

The deposit API has no face, and that is what makes the two interfaces this domain's. A place knows neither workspace, nor root, nor app: it holds bytes and forgets them. What the person is shown — what may be given, what was refused and why, which produced file goes with which given one — is knowledge of this domain, so the containers where she reads it are of this domain too.

Conceptual model of data

Four classes. The workspace is one of them without being modelled here: its functioning is established, and it belongs to the domain of the workspaces. It appears with its identifier and no property. What it holds — the three levels, the states, the references — is read where it is written, and this document adds nothing to it.

The classes of entities

ClassPropertiesWhat it is
FILE # machine, # name, size A file in place, where it is (D1). A file an app produced is one of them: it stands beside the file it was made from, under the same root, and it perishes with the deposit which holds them both when that deposit is what it stands in
COPY # deposit, # name, size A duplicate made where the app works, because the original is not there (D5). It exists only inside its deposit, and is identified relatively to it
DEPOSIT # deposit, place The copies given at one time. It exists while it is fed, and it holds the place the deposit API gave it once it is given
WORKSPACE # workspace The files which are known and their states (D4). One is active at a time, and it is the only one this domain sees

A copy is in its deposit from the moment the file is taken in, and before the deposit is given it carries a name and a size and no content: that is what the verifications of T08 are made on. The dossier has no word for a file designated and not yet duplicated, and none is invented here: it is the word which is still to be fixed.

The relations

No.VerbLeg 1Leg 2
R1belongs toCOPY (1,1)DEPOSIT (1,n)
R3is known toFILE (0,1)WORKSPACE (0,n)
R4is added toDEPOSIT (1,1)WORKSPACE (0,1)

R1 is an aggregation: a copy is named inside the deposit which carries it, and two deposits name a copy the same way without naming the same copy. It is also what identifies a copy — its name inside its deposit — the first rule below making sure that two of them never share one.

A copy is known to a workspace as well, and that is not a relation: it follows from R1 then R4, a copy being known to the workspace its deposit was added to. Written as a relation it would repeat what the keys already say.

R4 is the case where the files have to be brought, and nothing else. Where they are already reachable nothing is added to a workspace, whether it pre-existed or T02 made it; where they are brought, a deposit is added to the workspace T02 makes, with the names of the copies. One deposit and one only: a deposit carries the moment it was made at, so a second deposit is another deposit, standing elsewhere, and the workspace which takes the name of what holds the copies is another workspace.

FILE and COPY carry the same verb towards the workspace, and that is what is not written here: a copy is a file which perishes, D5 saying so in as many words, and the two ought to be one class and its specialisation. They are written as two classes for want of it.

Computed, and never held

  • The volume of a deposit, which is the sum of the sizes of its copies, and which is compared to what the deposit API accepts (C4).
  • That a file is reachable: it is, when it is in place, or when it is a copy (T01).
  • The address at which a produced file is reached, which follows from the file and lives as long as it does (T05).
  • What is handed to an app, which is made from the workspace when an app asks and is never kept (T03).

What the keys do not hold

  • Two copies of one deposit never bear the same name: a file whose name is already taken is not deposited, and what was refused is said (F10). C12
  • A copy bears the name of the file it duplicates: a deposit renames nothing, the workspace being made with the names which were deposited.
  • The copies of one deposit stay within what the deposit API accepts, which that domain says and this one relays (C4).
  • Only a deposit is added to a workspace: what is delivered to the person is added to none.

What is not modelled, and why

  • The state and checked (D2, D3), which the workspace carries at its three levels. This domain asks for the checking (T02) and reads it (T03); it does not hold it.
  • The bounds and the duration, which belong to the deposit API; and the extensions, which are SPPAS's (C4, C10).
  • What names a place and what authorises reaching it, which are the deposit API's and are never read here.
  • What was not deposited, and why (F10): said to the person, and not kept (B6).
  • The apps, which are actors (A2): an app asks this domain for what it needs and treats what it receives, so nothing of them is held here.

Conceptual model of treatments

Eleven treatments, and they are all that the domain does. They say what is done, on what, and on which event — not when, not where, not by whom, which belongs to the organisational level. Nothing here says which case one is in: the conceptual model is the same in all of them, and that is what makes them one design and not three.

The chain runs thus: an app asks, and either it receives the workspace or there is none and files are asked for; the person is told what she may give, she composes what she gives and gives it, the files are made reachable and made known, and the app is answered. When it has finished, what it produced is made known and made reachable by the person. What was made only to be handed over does not last, and it is the deposit API which sees to that.

The events

No.EventKindComes from
E1An app asks for the files it is to treatexternalAn app (A2)
E2An app asks for filesexternalAn app (A2)
E3The person gives what she has composed, and says which of them are to be treatedexternalF1
E4An app gives back what it has producedexternalF8
E5There is no workspaceinternalT03
E6The files given are reachableinternalT01
E7The workspace is readyinternalT02
E8Files have been producedinternalT04
E10The person designates a file, to be givenexternalF1
E11The person takes back a file she designatedexternalF1
E12An app takes a file it was given, to work on itexternalAn app (A2)
E13An app gives a file backexternalAn app (A2)
E14An app has finished treatingexternalF12

Deleting what is out of date is no treatment of this domain, and no event of it either: the deposit API empties itself, nobody asking it to. What this domain has to know is that a place does not last.

T01 — Make a file reachable

Purpose: that a file given by the person exists where an app will read it.

WhatSays
SynchronisationE3
ActionsMake reachable, where an app will read it, every file of what is given which is not; verify its type on its bytes
ResultOne copy for every file which was not reachable. When its type is accepted
ResultWhat was not deposited, and why (F10). When a type is refused
ResultE6, the files given are reachable. When at least one of them is
ResultThat nothing can be deposited now, and when to come back (F10). When the deposit API refuses a place — and nothing of what was given is deposited

What is verified here is what needs the content: the type of a file, read on its bytes and not on its name, an executable or a script not being deposited. The name, the size and the volume were verified when the file was taken in, on what was known of it before anything travelled. T08

T02 — Make the files known, and check those to be treated

Purpose: that the workspace knows the files, and that those to be treated are checked in it.

WhatSays
SynchronisationE6
ActionsMake a workspace when none exists; make it know the files which are reachable; check those the person said are to be treated
ResultThe files to be known, and their checking (F4). Always
ResultE7, the workspace is ready. Always

It examines no content.

Making a workspace when none exists belongs here and nowhere else. A deposit does not make one: it makes files reachable, which is another thing, and there are files to be made known which never went through a deposit — those a person picks on the disk of the machine where SPPAS runs, when nothing is installed to manage workspaces for her. Tying the making to the deposit would leave that case with no workspace at all, and it is the case of whoever has only a browser.

T03 — Hand to an app the files it is to treat

Purpose: to give an app what it needs in order to work.

WhatSays
SynchronisationE1 OR E7
ActionsRead the workspace; make a workspace holding the files to be treated and them only; hand it to the app which asked
ResultA workspace holding the files to be treated (F6). When a workspace exists
ResultE5, there is no workspace. When none exists

What is handed is a workspace made for the app, holding the files to be treated and nothing else — possibly nothing at all. The one the person composed stays where it is: an app never holds it, so it cannot touch what it was not given, and « an app does not check the files it treats » stops being a rule to respect and becomes a thing it cannot do. RO9

What is handed may hold nothing. An app reads what may be empty and says itself what it needs: the domain cannot say it in its place, knowing neither how many files an app wants nor of which kind.

T04 — Add the produced files to the workspace

Purpose: that the files produced by an app are known to the workspace and checked.

WhatSays
SynchronisationE4
ActionsTake from what the app gives back the files it produced, write them into the workspace with the grouping they carry, and check them
ResultThe files produced, added and checked (F7). Always
ResultE8, files have been produced. When the app produced any

Adding them does not uncheck what was treated. The app never wrote in the workspace of the person: it never held it. RO9

An app gives back as often as it has something to give back, and nothing obliges it to wait until it has finished: a design which forbade that would forbid what no need asks to forbid, and the person would wait for her first result until the last one was made.

The app gives back the workspace it was given, enriched with what it produced. Grouping files — a path, a root, a name — is the workspace's own work, and the domain does not redo it in its place: it takes what came back and writes it where it belongs. It is also what lets the person see, at the delivery, which files were grouped together and what they produced.

T05 — Make the produced files reachable by the person

Purpose: that the person gets back what was produced without knowing where it was written.

WhatSays
SynchronisationE8
ActionsMake every produced file reachable by the person, where an app wrote it: beside the file it was made from
ResultThe produced files (F9). When the person reaches them where they are
ResultAn address at which every produced file is reached (F9). When she cannot reach it where it is

What is handed over is an address and not a file: the copy the person ends up with is made by what fetches it, and this domain knows nothing of it, which is what B6 asks. The address lives as long as the file it names.

T07 — Announce what is accepted

Purpose: that the person knows what she may give, before she gives.

WhatSays
SynchronisationE2 OR E5
ActionsSay the bounds, the extensions which are accepted, and that nothing of what is given is kept
ResultThe announcement (F3). Always
ResultThat nothing can be deposited now, and when to come back (F3). When the deposit API says it has no place

The announcement precedes any deposit, and it depends on no file.

Neither the bounds nor the hour to come back are decided here: they are asked of the deposit API and said as they were given. What is of this domain is that the person is told before she gives, and not after.

T08 — Take a file into what is to be given

Purpose: that what the person is about to give is known to be acceptable before anything travels.

WhatSays
SynchronisationE10
ActionsRead the name and the size of the file designated; verify that the name is not already taken, that the size does not exceed what the machine accepts, and that the volume of what is to be given stays within its bound; take it in
ResultThe file is in what is to be given, and the volume it now makes. When the three verifications pass
ResultWhat was not taken in, and why (F10). When one of them fails

Nothing of the content is read here. A name and a size are known before anything travels, and they are enough for these three verifications; what needs the content is T01's. It is also why the person is told at the moment she adds a file, and not once everything has travelled.

What came with a refused file may fall in the root of the one which stays, and nothing shows it: the domain cannot tell them apart, the folder the person took them from not travelling with them. What groups the files is read at the delivery, where the associations are seen.

T09 — Take a file back out of what is to be given

Purpose: that the person can correct what she is about to give, before she gives it.

WhatSays
SynchronisationE11
ActionsTake it out of what is to be given
ResultWhat is to be given, without it, and the volume it now makes. Always

Nothing of the file had travelled when it was taken in, so taking it back undoes the taking in and nothing more. RO8

T10 — Lock a file for the app which takes it

Purpose: that a file an app is working on is known to be in use, and is not given to another.

WhatSays
SynchronisationE12
ActionsPass the file from checked to locked, in the workspace
ResultThe file is locked (F4). Always

Nothing more is needed to keep a file from being given twice. A state has one single value (D2), so a locked file is no longer a checked one, and what is handed to an app holds the files to be treated — that is, the checked ones. The exclusion is in the state, not in a rule.

An app takes and gives back as it works: one file at a time for whoever reads a content and produces a result, a file held for as long as it is open for whoever edits one. The domain does not choose between the two; it marks what the app says it is doing.

T11 — Give a file back

Purpose: that a file an app has done with is available again.

WhatSays
SynchronisationE13
ActionsPass the file from locked to checked, in the workspace
ResultThe file is free (F4). Always

A file given back one by one is what an app does as it works. What it still holds when it has finished is released by T12.

T12 — Release what an app still holds

Purpose: that nothing stays locked for an app which has finished.

WhatSays
SynchronisationE14
ActionsRelease every file the app still holds
ResultThose files are free (F4). Always

An app which gave everything back one by one leaves nothing to release, and this treatment does nothing. It is what makes an app which stops halfway harmless all the same, as far as the locks go.

Organisational level

Organisational model of treatments

One procedure per treatment, numbered as it is, and each one triggered by one event. What decides which procedures have anything to do is not where the software happens to be installed, but two questions, and they are independent: are the files already reachable, and does a workspace exist.

That makes three cases and not two. The files are in place and a workspace is there; the files are in place and there is none; the files are not in place. The fourth — files to be brought, and a workspace already there — is not a case: a deposit carries its own moment, so it stands in a folder of its own and makes a workspace of its own, and it behaves as the third.

The first two cases share every operator: what separates them is that a workspace has to be made, which T02 does when it finds none. They are one table. The third is the other.

When the files are already reachable

PFWhat it doesTriggered byIn chargeWhereWhenNature
PF1 (T01)Makes a file reachableE3——nevernone
PF2 (T02)Makes the files known, and checks those to be treatedE6the short path, or what manages the workspacesthe machine where SPPAS runs, which is herswhen the person asksconversational
PF3 (T03)Hands to an app the files it is to treatE1 or E7the domainthe same machineat every request of an appautomated
PF4 (T04)Writes the produced files into the workspaceE4the domain, on the word of the appthe same machineeach time an app gives something backautomated
PF5 (T05)Makes the produced files reachable by the personE8——nevernone
PF7 (T07)Announces what is acceptedE2 or E5——nevernone
PF8 (T08)Takes a file into what is to be givenE10the short path, or what manages the workspacesthe same machinewhen the person designates a fileconversational
PF9 (T09)Takes a file back outE11the samethe same machinewhen the person takes one backconversational
PF10 (T10)Locks a file for the app which takes itE12the domain, on the word of the appthe same machineeach time an app takes a fileautomated
PF11 (T11)Gives a file backE13the domain, on the word of the appthe same machineeach time an app gives one backautomated
PF12 (T12)Releases what an app still holdsE14the domain, on the word of the appthe same machinewhen an app has finishedautomated

PF1 has nothing to do because a file the person points at is already where SPPAS reads it; PF5 because the workspace says where the produced files are; PF7 because the announcement exists only where there is a refusal, and nothing is refused here. Three procedures, two modules.

When there is no workspace, the only difference is in PF2, which makes one. That is the case of a person who has on her machine a browser and nothing else, and it is served by the short path alone.

When the files are not reachable

PFWhat it doesTriggered byIn chargeWhereWhenNature
PF1 (T01)Makes a file reachableE3the interface of deposit, and the serverthe serverwhen the person givesautomated
PF2 (T02)Makes the files known, and checks those to be treatedE6the serverthe serveras soon as PF1 is doneautomated
PF3 (T03)Hands to an app the files it is to treatE1 or E7the domainthe serverat every request of an appautomated
PF4 (T04)Writes the produced files into the workspaceE4the domain, on the word of the appthe servereach time an app gives something backautomated
PF5 (T05)Makes the produced files reachable by the personE8the interface of deliverythe server, then the machine of the personeach time files have been produced, then when she follows an addressautomated, then conversational
PF7 (T07)Announces what is acceptedE2 or E5the interface of depositthe machine of the personbefore she gives anythingautomated
PF8 (T08)Takes a file into what is to be givenE10the domain, on the request of the personthe browser of the person, then the serverwhen the person designates a fileconversational
PF9 (T09)Takes a file back outE11the domain, on the request of the personthe browser of the person, then the serverwhen she takes one backconversational
PF10 (T10)Locks a file for the app which takes itE12the domain, on the word of the appthe servereach time an app takes a fileautomated
PF11 (T11)Gives a file backE13the domain, on the word of the appthe servereach time an app gives one backautomated
PF12 (T12)Releases what an app still holdsE14the domain, on the word of the appthe serverwhen an app has finishedautomated

What the two tables say

PF3, PF4, PF10, PF11 and PF12 are the same procedure in both, word for word: everything an app asks of this domain is indifferent to where the files came from. PF2 is the same work with two operators and two natures. What differs is the whole of what a deposit brings with it.

PF8 and PF9 are the only procedures which stand in two places. What the person handles is in her browser — the button, the file, its name and its size — and what decides is on the server, SPPAS being alone in knowing what it reads. What travels to be verified is a name and a size; the content stays where it is until she gives. RO8

PF8 and PF9 are already served, in the first table, by page_files of the wx interface, which will one day become app_wkps. What that page does is not modelled here: the code exists, and it is handled. The short path does the poor version of it, which is what it is for.

The resources differ for one procedure only, PF1: where files have to be brought it works on the contents which travelled and on the bounds; where they are in place there is nothing to bring.

No procedure refuses anything before an app is entered, and none appears in either table for that: an app which cannot work with what it received asks for files, and that is PF7 and PF8, not a refusal at the door. RO3

When files are asked for

A person clicks on an app. The app is entered, and it asks the domain for the files it is to treat. Two questions follow, and they do not belong to the same one.

The first is the domain's: is there a workspace? There is none as long as nothing has made one — remotely before any deposit, and on the machine of the person as long as nothing has been installed to manage workspaces for her. The domain then asks the person for her files — having first said what it accepts — and answers the app with the files it asked for.

The second is the app's: is what it received enough? A workspace may be there with nothing checked in it, or with files which are not the ones that app needs. The domain cannot answer that question in its place, knowing neither how many files an app wants nor of which kind. So the app says it, and asks for files.

In both cases what the person is shown is an interface of the domain: the short path locally, the interface of deposit remotely. She is not taken away from the app she asked for — where that interface is shown, beside the app or inside its page, is settled below the organisational level and changes nothing here.

An app must not check the files it treats. Asking for files is not checking them: the interface which asks belongs to the domain, and it is the domain which writes into the workspace, wherever that interface is shown.

The short path

Locally, T02 has two operators, and they do not merge. The short path adds a few files and checks them, nothing more. What manages the workspaces will come beside it, not over it.

The poverty of the short path is not a stage to be passed: it is a strength. Whoever has one file to treat does not want to find herself in a complete interface for managing workspaces and references. The axis is therefore not the deployment but what the person intends: one file to treat now, or a corpus to organise. The occasional use exists locally too, and the short path is it.

The short path also makes the local use possible for whoever has not installed wxpython: without it, T02 has no operator locally, and an app which asks for files asks nobody — the person learns that files are missing and has no way of adding any. It is also the short path which makes the workspace in that case, T02 making one when none exists.

Where the short path is shown — beside the apps, or inside the one which asked for files — changes nothing of what it is. The interface belongs to the domain, and it is the domain which checks.

Locally, the short path browses the disk on the side of the server, which it may, the server running on the machine of the person. The field of a browser does not give a path, it gives a content to upload — and a local file has no need of a copy (T01). That, and not the deployment, is the reason why the two interfaces are two.

Rules of organisation

  • RO1 — The checking is done by the domain, and never by an app which treats files: in the short path, or in what manages the workspaces.
  • RO2 — Remotely, everything which is deposited is checked: one does not deposit in order to keep, one deposits in order to have it treated.
  • RO3 — An app says for itself whether what it received is enough, and asks for files when it is not. The domain judges nothing in its place.
  • RO4 — Remotely, the deposit and the answer to the app are one single request: what carries the files is what hands the workspace over.
  • RO5 — The deletion of the copies which are out of date is done by the server at every request, nobody having asked for it.
  • RO6 — Two questions decide what there is to do, and they are independent: whether the files are already reachable, and whether a workspace exists. The first is answered by the interface the person gives through — the short path gives paths, the interface of deposit gives contents; the second is answered by looking.
  • RO7 — An interface of the domain requires no place of its own, and does not require the person to leave what she is doing. Where it is shown belongs to whoever assembles the software, and changes nothing of whose it is.
  • RO8 — Remotely, the contents travel at the moment the person gives, and not before: nothing of what she composed is kept on the server until then. What travels while she feeds is a name and a size, which is what it takes to accept or refuse a file. In how many goes the contents travel, and under what wrapping, is not of this level.
  • RO9 — No app which treats files receives the workspace of the person: what it receives is made for it, and holds the files it is to treat and nothing else. What manages the workspaces is not one of them — it belongs to that domain, and holds what is its own.

Constraints

What the code holds to

These follow from no need on their own: they are what the code has to hold to in order to serve the needs. They say nothing of the means, which belong to the decisions.

What imposes them is not one thing but four, and the difference matters, a constraint being revised where it comes from: the needs of the person; the model itself, a treatment, a relation or a rule of organisation; the neighbouring domain which gives the place; and whoever runs SPPAS on the machine, who will not have anything written there.

The deposit API is an actor, and it exchanges: it says what it accepts. The last is not one and has not to be — he exchanges nothing, he imposes; he becomes an actor the day what is accepted is said in a setting instead of being written in the code.

B7 and B8 are named nowhere below, and that is not an oversight: they are needs to know what quantity and what size are accepted, and the announcement serves them (T07, F3). A need to know is never what imposes a bound. The same holds of B11, which C10 answers for the announcing, and not for the refusing.

No.ConstraintImposed by
C4What is deposited stays within what the deposit API accepts — a size, a volume, a number of places, a lifetime. None of it is fixed here: it is asked of that domain and relayed to the person.A4
C5The choice of the files gives paths where SPPAS runs on the machine of the person, and contents otherwise. It is what says whether a file has to be brought.T01, and the two interfaces which offer the choice
C6No setting says which case one is in: whether a workspace exists is read, and whether the files are reachable follows from what the interface gives — a path or a content.RO6, C5
C7A deposit does not rename the files.B12, and the workspace being made with the names which were deposited
C8Only the files whose extension SPPAS reads are deposited.Whoever runs SPPAS on the machine
C9The type of a deposited file is verified on its bytes and not on its name: an executable or a script is not deposited.Whoever runs SPPAS on the machine
C10The domain announces the extensions it accepts; what it does not accept is not deposited.B11, C8, C9, F3
C12A file whose name is already taken is not deposited: the first of the name stays, the others are refused.The root: the workspace is made with the names which were deposited, and two files of one name would fall in one root
C14A file an app produced is a sibling of the one it was made from: same path, same root, the extension the person asked for. Remotely, that is the folder of the deposit.The apps, every one of which writes there — the workspace giving the notion of sibling files, not the obligation

Not one of these constraints carries a number, and none of the bounds of the place is written here any more. What they are worth is the deposit API's to say, and this domain's to relay before the person gives anything.

Logical level

The tables

Each class of entities becomes a table, and its identifier becomes its key.

TableColumnsComes from
FILEmachine, name, size, workspaceThe class FILE, and R3
COPYdeposit, name, sizeThe class COPY, and R1
DEPOSITdeposit, moment, workspaceThe class DEPOSIT, and R4
WORKSPACEworkspaceThe class WORKSPACE

R1 is an aggregation: the aggregated class takes the key of the aggregating one, so a copy carries the name of its deposit, and the two together tell one copy from another. Two deposits carry a copy under one name without carrying the same copy.

R3 has its low cardinality on the side of FILE, which is (0,1): the table takes the key of WORKSPACE, and it may be empty — a file in place is known to the workspace, or to none. R4 has its own on the side of DEPOSIT, which is (1,1): the table takes it too, and it is never empty.

A copy holds no workspace of its own. It is known to the one its deposit was added to, which R1 and R4 already say: a column would repeat two keys and would have to be kept true.

WORKSPACE is a key and nothing else. The table exists so that the others may name it; what it holds is written elsewhere, in the domain which owns it.

Not in the tables: the volume of a deposit, whether a deposit is out of date, whether a file is reachable, the address at which a produced file is reached, and what is handed to an app. All five are computed, and none of them would stay true if it were held.

Physical level

Where each table stands

Here the machines are named, and not before. There is no database: the tables are borne by the disks where the files stand, by what runs between two requests, and by the domain of the workspaces.

TableWhere it standsWhile it runsWhat the person sees
FILE A file on the disk of the machine where it is What the domain of the workspaces holds of it Her file, where she put it
COPY A file written in the place the API gave to its deposit The same Nothing: she sees the name she gave, never where it went
DEPOSIT The place the API gave, holding its copies. It is asked for only at the moment the person gives Before she gives, what is to be given is held where she stands; from the deposit on, the place and what it holds Nothing of the place. While she feeds, the volume she has fed
WORKSPACE What the domain of the workspaces writes. Remotely it takes the name of the folder which holds the copies, as a workspace of SPPAS takes the name of its own Its object The file manager, and what an app shows of it

What is handed to an app stands nowhere: it is made when the app asks, and it is written down by nobody.

A deposit has two halves and only the second stands anywhere. While the person feeds it, what she has fed is held where she is, the volume is counted there, and nothing is written — RO8 says so, and nothing here may say otherwise. The place is asked of the API, and the copies written in it, at the moment she gives.

Where a place is, what names it, how long it lasts and when it is emptied are not written here. They belong to the API which gives it. This domain knows a place by what that API gave, and knows that it does not last.

Two files of one name, deposited twice, stand side by side without meeting, because two deposits are two places. Within one deposit they cannot meet, C12 seeing to it.

How the domain of the workspaces writes a workspace is not said here: it is its own, it is established, and this document reads it without naming what it holds.

Where the code goes

One module per kind of knowledge, and every procedure has one module and one only. What a module is alone in knowing is what says where a change will have to be made, and what can be tested without the rest.

ModuleWhat it doesProcedure
placeAsks the API for a place, puts the copies there, asks it for an address. The only one which calls itPF1, PF5
acceptanceKnows what SPPAS reads, and relays what the API accepts. It says both, and refusesPF7, and what PF1 and PF8 ask of it
feedingHolds what is to be given, feeds it, takes back from it, and counts the volumePF8, PF9
workspaceMakes files known and checks them, locks and releases, and writes what an app producedPF2, PF4, PF10, PF11
handingMakes the workspace an app receives, and gives itPF3
deliveryMakes the address of a produced file, and serves it when it is followedPF5

What each one promises, which is the reason for the cutting:

  • The place module is the only one which calls the API, so it is the only one to read again the day that API changes.
  • Acceptance decides nothing about what it has not been given: it answers on a name and on bytes, and relays what the API said of a size, a volume and a count. That is what makes it testable with no disk at all.
  • Feeding is in two halves: the browser holds the file and knows its name and its size, the server says whether it is accepted. Nothing of the content crosses before the person gives, which is RO8 written as a module.
  • The workspace module is the only one which speaks to the domain of the workspaces, so it is the only place to read again the day that domain changes.
  • Handing is the only one which makes a workspace for an app, and that is where the door holds.
  • The delivery is the only one which makes an address.

This domain is a service, not an app. Five of these modules speak only to apps: an app calls them, and there is neither a screen nor a person behind what they answer. Two face a person — where a deposit is fed, and where what was produced is fetched — and those two carry an interface.

An interface here is not an app, and not a page: it is a piece of page, a container an app places in its own. That is what RO7 says in the language of organisation — the domain requires no place of its own — and this is the same thing said in the language of the code.

Where the files are already reachable, three modules have nothing to do — the place, acceptance and the delivery. They carry exactly the three procedures the organisational model leaves empty there.

The architecture of the code

An app holds the page and receives the request: it is the only one which can, and there is no alternative. A task which belongs to this domain, it dispatches. What is behind that dispatch is this domain's own, and the app sees none of it.

What the app sees of this domain is one object — its manager — and what that object answers: the files it is to treat, whether an event was for it, and a tree to put in its page. It never holds the façade, never holds a deposit, never knows a place.

Three kinds of class, and what each may do

KindWhat it doesWhat it may not do
A view Builds an object — a tree — which whatever answers the request bakes. It is given what it shows Decide anything, count anything, refuse anything, reach a disk or a neighbour, or write a string of its own
The controller Reads the task the request carries, rebuilds a record from what the page transmits, calls the façade, and has a view populate its tree Hold anything between two requests, build a tree, know a place or a workspace — and assemble anything: it is given what it uses, and building the objects of a domain is not the work of what reads a task
The model The façade and its sub-models, which are the whole of chapter on the classes Know that a page exists, or that anything is shown at all

One controller for the two views. They never overlap in time — one deposits before, one fetches after — and a domain which holds no state between two requests would gain nothing from a second dispatch.

What assembles, and what an app holds

An app is assembled by its maker: it builds the fixed part of the page, then the view, then the controller, and it hands the controller the model and the view. This domain is not an app and has no page of its own, so it has no maker. It has an entry class — a manager — which does the same work for it: it builds the model, the two views and the controller, and it is the only thing an app holds of this domain.

That is the counterpart of the rule above. The controller assembles nothing because something else does, and the app holds no façade because it holds the manager instead. What is behind the manager is never named outside it.

How an app knows a task is ours

By asking, and by no convention of names. An app receives the events of a request and consumes what is its own; what it does not recognise, it offers to its services, and a service either consumes it or says it did not. What nobody consumed is an error, and the request is answered as such.

No prefix, no agreed vocabulary of event names between an app and its services: the manager answers whether the event was for it. An app which gains a second service adds one line and nothing else.

Which of the two views

The record says what is known, and the view follows from that and not from the task: what has been fed and not yet given is shown as a deposit; what an app has produced is shown as a delivery. It is the same mechanism as the pathway of an app which has several pages — the state of what is known chooses.

What a view owes the next request

A record serialises itself for transport and parses itself back. What a view builds therefore carries the serialised record with it, so that the next request brings it back. A view which omits it breaks the request which follows — the controller would rebuild an empty record, and a person would see her list vanish without having touched it.

The first request

There is no record. The controller makes one at its default values — nothing fed, no task, no place asked for — and what is shown is the announcement and an empty list. Of the model, only what is accepted is called.

A request which carries a task but no record is a first request as well. A record which did not come back is a record which was never made, and inventing one would show a person a state she never composed.

The record

What one request holds is an object, and it has a name: the record. It carries what the page transmitted — the names and the sizes fed so far, the task, what is to be shown — and it is rebuilt at every request from what came back with it.

That is what lets the two sides find their context again, and the alternative is to keep the state of a person on the machine between two requests — which is exactly what B6 refuses. A record which travels is not a convenience of the code: it is the promise that nothing of her is held.

A request, in order

  1. The app receives the request and reads the event it carries. It belongs to this domain, so it dispatches it.
  2. The controller starts from nothing and rebuilds its record from what the page transmitted: the names and the sizes, and no content.
  3. It reads the task — designate a file, take one back, give, ask for the files to treat, here is what I produced, I have finished — and checks what has to be true before it.
  4. It calls the façade, once. The façade calls what it has to, and answers.
  5. The controller puts in its record what is to be shown: a list, a volume, a refusal and its reason, an hour, addresses.
  6. The view populates its tree from that record.
  7. The app puts that tree in its page, where it chose, and bakes the whole.

Step 4 is the only one which reaches anything: a disk, a workspace, an API. Steps 2, 3, 5 and 6 run on what they were given, which is what makes them testable without a machine.

And the request which carries a content is the one which gives, and that one only. Every other request of this domain carries names, sizes and a task. RO8

UML

The classes

Those which carry the data come from the tables, one per table which needs one. Those which work come from the modules, one per module. A name says what the class handles — files, and the means by which they are exchanged — and nothing of how the application happens to be arranged.

What carries the data

ClassFromWhat it is
DepositDEPOSITWhat is to be given, then what was given: the files fed into it, and the place the API gave it
DepositedFileCOPYOne file of a deposit: a name, a size, and a content which arrives only when the deposit is given
FilesRecord—What one request holds: the task it carries, what has been fed so far, and what is to be shown. It serialises itself for transport and parses itself back, and it is held by nobody between two requests
noneFILEA file in place is named by the domain of the workspaces, which has a class for it already
noneWORKSPACEIts own domain's

What does the work

ClassModuleWhat it is alone in knowing
FileProvision—The façade. It is what an app and what answers a request see, and neither of them knows what is behind it
DepositAcceptanceacceptanceWhat may be deposited, and how many deposits the space takes. Reads nothing, writes nothing, knows no workspace
FilePlaceplaceHow the deposit API is called: a place asked for, copies put there, an address obtained
WorkspaceFilesworkspaceHow the domain of the workspaces is spoken to
AppExchangehandingWhat an app receives, and what comes back from it
ResultDeliverydeliveryHow a produced file is reached by the person

The feeding module has no class of its own: what it holds is a deposit being fed, rebuilt from what the page transmits at every request, and kept between none of them. It is the controller which rebuilds it.

What shows, and what dispatches

ClassWhat it does
DepositViewBuilds the tree of what a person feeds: what is accepted, the button, the list, the volume against the bound, what gives
DeliveryViewBuilds the tree of what was produced: the files grouped by root, their addresses, the hour at which they go, and whether the app has finished
FilesManagerBuilds the model, the two views and the controller, and answers an app: the files it is to treat, whether an event was for this domain, and a tree to put in a page. It is the only object of this domain an app holds
FilesControllerReads the task the app dispatched, rebuilds a record from what the page transmitted, calls the façade, and has a view populate its tree from that record

A view builds a tree and does nothing else — it decides nothing, counts nothing, refuses nothing, and reaches neither a disk nor a neighbour. What it shows was decided before it was called.

The class diagram

/ marks what is derived and held by nobody. What the operations promise is the chapter on the contracts; what they are called is a proposal, and one pass renames them all.

ClassAttributesOperations
Depositplace, files, /volumefeed(), take_back(), volume()
DepositedFilename, size, content—
FileProvision—what_is_accepted(), feed(), take_back(), give(), files_for_app(), produced(), finished()
DepositAcceptance—what_is_accepted(), accepts(), accepts_volume(), accepts_one_more_deposit(), accepts_content()
FilePlace—what_is_accepted(), ask_for_a_place(), put(), address_of()
WorkspaceFiles—make_workspace(), make_known(), check(), checked_files(), lock(), release(), write_produced()
AppExchange—for_app(), back_from_app()
ResultDelivery—address_of(), serve()
FilesManager—files_for_app(), consumes(events), populate_view()
FilesControllerrecordhandle(data), populate_view()
FilesRecordtask, fed, to_be_shownserialize(), parse(data)
DepositView—populate_tree_content(record)
DeliveryView—populate_tree_content(record)

Deposit.feed() adds and counts; it does not accept. Whether a file may be fed in is DepositAcceptance's answer, and the façade asks it first. A data class which decided what it may hold would hold the rules as well as the data, and the rules would then be in two places.

What is tied to what

TieLegsWhat it is
holdsFileProvision 1 — 1 each of the five othersA composition: the façade makes them, and they go when it goes
holdsDeposit 1 — 1..n DepositedFileA composition: a file of a deposit exists only inside it
usesFilePlace → DepositA dependency: it writes them and forgets them, and keeps none
usesAppExchange → WorkspaceFilesA dependency: it asks for what is checked, and for the workspace it will hand over
usesWorkspaceFiles → sppasWorkspaceA dependency, and the only tie of this domain to the neighbouring one
usesResultDelivery → FilePlaceA dependency: what an app produced is a sibling of what it read, so it stands in the folder of the deposit
holdsFilesManager 1 — 1 the façade, the two views, the controllerA composition: it builds them, and they go when it goes. It is what the rule « the controller assembles nothing » leans on
holdsFilesController 1 — 1 FilesRecordA composition: one record per request, made by the controller and kept by nobody
usesthe two views → FilesRecordA dependency: they are given it and build from it
usesFilesController → FileProvisionA dependency: it calls the façade, once per request
usesFilesController → the two viewsA dependency: it hands them what to build from, and reads nothing back but HTML
noneDepositAcceptanceTied to nothing at all: it answers on names and numbers handed to it
nonethe two viewsTied to nothing: they are given a state and give back HTML

AppExchange does not speak to the domain of the workspaces, and that is deliberate: the promise that one class alone speaks to it would be false the moment two did. It asks WorkspaceFiles for the files which are checked and for a workspace holding them, and it holds the rule that the one of the person never leaves.

One class holds a state, and it is Deposit. The others are given what they work on and give back what they made. That is why nothing here has to be invalidated when something changes upstream, and why each of them is tested on its own.

In yUML

To be read at yuml.me, class diagram.

[FileProvision|what_is_accepted();feed();take_back();give();files_for_app();produced();finished()]

[FileProvision]++1-1>[DepositAcceptance|what_is_accepted();accepts();accepts_volume();accepts_one_more_deposit();accepts_content()]
[FileProvision]++1-1>[FilePlace|what_is_accepted();ask_for_a_place();put();address_of()]
[FileProvision]++1-1>[WorkspaceFiles|make_workspace();make_known();check();checked_files();lock();release();write_produced()]
[FileProvision]++1-1>[AppExchange|for_app();back_from_app()]
[FileProvision]++1-1>[ResultDelivery|address_of();serve()]

[Deposit|place;files;/volume|feed();take_back();volume()]++1-1..*>[DepositedFile|name;size;content]

[FilesManager|files_for_app();consumes();populate_view()]++1-1>[FileProvision]
[FilesManager]++1-1>[FilesController|handle();populate_view()]
[FilesManager]++1-1>[DepositView|populate_tree_content()]
[FilesManager]++1-1>[DeliveryView|populate_tree_content()]
[FilesController]++1-1>[FilesRecord|task;fed;to_be_shown|serialize();parse()]
[DepositView]-.->[FilesRecord]
[DeliveryView]-.->[FilesRecord]

[FilesController]-.->[FileProvision]

[FilePlace]-.->[Deposit]
[AppExchange]-.->[WorkspaceFiles]
[WorkspaceFiles]-.->[sppasWorkspace]
[ResultDelivery]-.->[FilePlace]

[sppasWorkspace]-[note:class of the neighbouring domain. Only WorkspaceFiles speaks to it]
[FilesController]-[note:called once per request. Holds nothing between two, and assembles nothing]
[FilesRecord]-[note:what one request holds. It travels with the page, which is what keeps nothing of a person on the machine]
[DepositView]-[note:builds a tree and nothing else. Decides nothing, counts nothing, refuses nothing]
[Deposit]-[note:volume is the sum of the sizes and is not held. place is what the API gave. content is absent until the person gives]
[ResultDelivery]-[note:a produced file is a sibling of the one it was made from. Same path, same root, so it stands in the folder of the deposit]

The states

A deposit
StateWhat is true
FedIt holds names and sizes, it makes a volume, and it stands where the person stands. Nothing of it is on the server
GivenIt holds the place the API gave, and its copies are written there
GoneIts place did not last. The API emptied it, and nothing here was asked

A deposit which is fed and never given leaves nothing: it was never anywhere but where the person was. That is why an abandoned deposit is not a case to be treated.

A file of the workspace, as this domain sees it
StateWhat is true
CheckedIt is to be treated, and it is in what is handed to an app which asks
LockedAn app has taken it. It is no longer checked, so it is in nothing that is handed

The two other states belong to the domain of the workspaces, and this one neither reads nor writes them.

The sequence, when an app asks

  1. The app asks for the files it is to treat.
  2. A workspace exists: what is handed is made from it, holding the checked files and them only, and the app receives it. The sequence ends here.
  3. No workspace exists: what is accepted is said, and what is not — the space being full — is said as well, with when to come back.
  4. The person feeds what she is about to give, and is answered on each file as she adds it: the name, the size, the volume so far.
  5. She gives. The contents travel then, and not before.
  6. The types are verified on the bytes, the copies are written in the folder of the deposit, and what was refused is said.
  7. The files are made known to a workspace, which takes the name of that folder, and those to be treated are checked in it.
  8. The app is answered, as in step 2.
  9. It takes a file, which is locked; it gives it back, which unlocks it; as many times as it works.
  10. It gives back the workspace it was given, as often as it has something to give back: what it produced is written into the workspace of the person, and checked there.
  11. It says it has finished, and what it still held is released.
  12. What was produced is made reachable: it is already where the person reads it, or an address is made for each file.

Steps 3 to 7 happen only where the files have to be brought. Where they are already reachable the person feeds a workspace outside of any app, and step 2 is the whole of it.

The error policy

LevelWhat happensWhat is done
1Nothing can be done: the deposit API gives no placeNothing is deposited. The person is told, and told when to come back
2One file is concerned: a name already taken, a size beyond what the machine accepts, a type refused on its bytesThat file is not deposited, the others are, and what was refused is said with its reason
3Whoever runs the machine has to know: a folder which cannot be written, a workspace which cannot be madeSaid where he reads, and the person is told that nothing could be deposited

What is raised is caught by whatever answers a request, and by nothing below it. A person is never shown what a machine says to itself, and never left before a page which does nothing without a reason.

The contracts

How to read them

pre is what has to be true on the way in, and what the operation does not check; post is what the caller can count on without looking. The operations are named by what they do and not by a signature: a signature invented before the code is a name nobody will use, and the modules are named here as the level above named them.

What holds everywhere

  • What is absent gives back an empty thing — an empty name, an empty list, a volume of zero — and never nothing at all.
  • What is handed to an app shares nothing with the workspace of the person: no object, no file, no way back to it. Every other promise of this domain rests on that one.
  • Only the workspace module speaks to the domain of the workspaces. No other class of this domain knows it exists.
  • What is raised is caught by whatever answers a request. No module below it writes a catch.

Class by class

acceptance
OperationContract
Say what is acceptedpre: none. post: the bounds, the extensions which are read, and that nothing of what is given is kept. It depends on no file and on no deposit
Answer on a namepre: none. post: refused when the name is already taken in what is being fed, or when the extension is not one SPPAS reads, and the reason is given with the refusal
Answer on a size, and on a volumepre: a size and a volume of zero or more. post: refused beyond what the machine accepts, and beyond the volume of one deposit
Answer on a count of depositspre: none. post: what the deposit API answered, relayed as it was given, with the hour to come back
Answer on a contentpre: the bytes are those of the file. post: refused when what they say of the type is an executable or a script. The only operation of this class which needs a content

This class reads no disk, writes nothing, and knows no workspace. Every rule of what is accepted is therefore checked without anything being installed, which is what makes it the first to be tested and the last to surprise.

feeding
OperationContract
Feed a file inpre: a name and a size. post: the file is in what is to be given, and the volume is that much greater — or nothing has changed and the refusal is said with its reason. Nothing of the file has travelled
Take a file back outpre: none. post: it is no longer in what is to be given, and the volume is that much less. Taking back what is not there does nothing wrong
Give the volumepost: the sum of the sizes fed, zero when nothing was fed
Give what is to be givenpost: the names and the sizes, in the order they were fed. May be empty

This class holds nothing between two requests: what is to be given is rebuilt from what the page transmits, each time. It decides on the server, on a name and a size, the content staying where it is until the person gives. What she fed is lost if she goes away, and an abandoned deposit leaves nothing behind.

place
OperationContract
Say what the API acceptspre: none. post: a size, a volume, a number of places, as that API says them. Nothing is fixed here
Ask for a placepre: none. post: a place, or a refusal with the hour at which there will be room. Neither is invented here
Put a copy in a placepre: the place was given. post: the copy stands there under the name the person gave it
Ask for an addresspre: the file stands in a place. post: an address which leads to it and dies with it
handing
OperationContract
Make what an app receivespre: none. post: a workspace holding the files to be treated and them only, sharing nothing with the one of the person; empty when nothing is checked, and never nothing at all
Take back what an app givespre: what is given back was made by this class. post: the files the app added, and nothing of what it may have changed elsewhere

« Sharing nothing » is the one promise a test has to hold on to: a change made in what an app received is never seen in the workspace of the person, whatever the app does with it.

workspace
OperationContract
Make files known, and check those to be treatedpre: the files are reachable. post: every one of them is known, and those to be treated are checked. No content is read
Lock a filepre: the file is known. post: it is locked, therefore no longer checked, therefore in nothing that is handed
Release a filepre: none. post: it is checked again. Releasing what is not locked does nothing wrong
Write what an app producedpre: the files come from what the app gave back. post: they are known and checked, and nothing which was checked before has been unchecked
delivery
OperationContract
Make the address of a produced filepre: the file exists where the app wrote it. post: an address which leads to it, and which lives exactly as long as the file does
Serve what an address namespre: none. post: the file, or nothing at all when it is out of date or when the address names none. Nothing else of the machine is ever reached through an address

The last clause is not a nicety: an address the domain makes is followed by whoever holds it, and what it can reach is what the domain is answerable for.

the controller
OperationContract
Be builtpre: a model and a view are given to it. post: a record with its default values, nothing read and nothing called
Handle what the page sentpre: none — what carries no task of this domain gives the record back to its default values. post: the record holds what the page transmitted, the façade has been called at most once, and nothing is held after it answered
Rebuild what is fedpre: none. post: the record holds exactly the names and the sizes the page transmitted, in the order they were fed; empty when it transmitted nothing. No content, ever
Populate the viewpre: what the page sent has been handled. post: the view has built its tree from the record, and the controller has changed nothing meanwhile

It never raises. What goes wrong is put in the record and written where whoever runs the machine reads it — a refusal with its reason, an hour to come back — because a person is never left before a page which does nothing without a reason. That is what the controllers of the apps already do, and this one does not invent another way.

the manager
OperationContract
Be builtpre: none. post: the model, the two views and the controller exist and are tied; nothing has been read, called or shown
Answer whether an event was for this domainpre: none. post: true when it was consumed, false when it was not — and nothing is changed in that second case. It is never an error here: what nobody consumed is the app's to answer
Give an app the files it is to treatpre: none. post: what the façade answers, handed on untouched
Populate a viewpre: an event was consumed, or it is a first request. post: the tree is built from the record
the record
OperationContract
Serialise itselfpre: none. post: what a page can carry and a next request bring back, holding names, sizes, a task and what is to be shown — and no content, ever
Parse what came backpre: none. post: the record holds what was transmitted; what was not transmitted takes its default value, and what is not understood is ignored rather than guessed
Be made with nothingpre: none. post: no task, nothing fed, nothing to show — which is a first request

A record parses what came back and never trusts it further than that: it is a page which sends it, and a page is not a place this domain holds. What is not understood is dropped, and the person sees a state she can still correct.

That shape holds wherever the app runs. One of the apps it was read from is served on a machine and nowhere else; the other is served both ways. Their controllers are written the same, which says that this one has no reason to differ either.

the two views
OperationContract
Populate the tree of a depositpre: the record comes from the controller. post: what is accepted, what has been fed, the volume against the bound, every refusal with its reason, and what gives — and nothing the record did not say
Populate it when no deposit can be madepre: the record says there is no place. post: no control which gives is built at all. Not one which is built and disabled: one which is not there
Populate the tree of a deliverypre: the record comes from the controller. post: the produced files grouped as the record groups them, one address for each, the hour at which they go, and whether the app has finished
Populate it with nothing in itpre: the record holds no produced file. post: the tree of nothing yet, and never an empty one
Carry the record backpre: none. post: what is built holds the serialised record, so that the next request brings it back. A tree without it breaks the request which follows

A view builds a tree, which is baked into HTML by whatever answers the request. It is not given a page to write into and it writes no string of its own: that is the shape the apps already have.

Three promises hold for both, and they are what a test holds on to. A view is called with everything it needs and asks for nothing. The same record gives the same tree — no clock read, no order which shifts. And a view never writes what it was not given: no path, no place, no name of a folder, nothing of the machine. What the person may see was chosen before the view was called.

What is tested, and where

Without a disk

On a machine where nothing is installed: no place, no API, no workspace, no server, no person.

No.What is checkedWhat it holds
TE1What is accepted is said before anything is given, and depends on no file and on no depositB7, B8
TE2A name already taken in what is being fed is refused, and the reason is given with the refusalC12
TE3An extension SPPAS does not read is refused, with its reasonC10
TE4A size beyond what the machine accepts is refused; the size one under it passesC4
TE5A volume beyond that of one deposit is refused; the volume one under it passesC4
TE6A count beyond the number of deposits is refused, and the refusal says when to come backC4, relayed and not invented
TE7A handful of bytes which say an executable or a script is refused. The only check which needs a contentT01
TE8A file fed in raises the volume by its sizeT08
TE9A file taken back lowers it, and taking back what was never fed does nothing wrongT09
TE10What is to be given comes back in the order it was fedT08
TE11Nothing of a content travels while the person feeds: what is held is a name and a sizeRO8
TE12A state handed to a view gives a tree which holds what that state said and nothing more: no refusal it invented, no total it countedD1
TE13A state which says nothing gives a tree which says nothingD1
TE14What is handed to an app holds the checked files and them onlyB1, RO9
TE15Everything in what was handed is changed, emptied and added to — and the workspace of the person has not movedRO9

TE1 to TE7 are the whole of what acceptance does. It holds every rule of what is accepted and reads nothing, so all of them are checked with no place and no API at all. Each refusal gives its reason, and the refusal on a count gives when to come back.

TE11 is RO8 written as a test. A test which found a file written on a server before the person gave would be a test which found that rule broken.

TE12 and TE13 catch a view which decided something. A view which counted a total or invented a refusal is caught by a state which says nothing at all.

TE15 is the one test the whole design rests on. A door which is not tested is a consigne.

With a disk

No.What is checkedWhat it holds
TE16A place is asked of the deposit API and obtained; a copy is put there under the name it was given; an address leads to itT01, T05
TE17A refusal of that API is relayed as it was given, with its hour, and nothing of it is invented hereF13, D2
TE18An address reaches its file, and nothing else of the machineB13
TE19Nothing at all when the file is out of date, and when the address names noneB13

TE16 and TE17 are the only tests which need that API, the place module being the only module which calls it.

With the domain of the workspaces

No.What is checkedWhat it holds
TE20Locking a file makes it no longer checked, so it is absent from what is handed next: checked by handing twice around a lockT10
TE21Releasing it puts it back among what is handedT11, T12
TE22Writing what an app produced unchecks nothing of what was checked beforeT04

The workspace module is the only one which needs that domain to run, and these three are the only tests which do.

What no test covers, and where they stand

  • What an app does with what it received: it is the app's, and this domain is answerable only for what it handed and for what came back.
  • How the domain of the workspaces writes a workspace: it is established, and it has its own tests or it has not.
  • The page which feeds a workspace in the wx interface: it exists, it is in production, and it is handled.

TE1 to TE15 are the ones to write first. They need nothing to run, and they hold the whole of what was decided: what is accepted, what is counted, and the door. The seven others need a disk or a neighbour, and they check that what was decided was also done.

They stand beside the code, in the folder of this service.

The decisions of the tool

What is decided here

The bounds of a place and how long it lasts are not decided here: they are the deposit API's, and its dossier holds them with the reason for each. What this domain decides of the tool is what follows.

D1. No business logic in the view. What says whether a file is accepted is SPPAS, which alone knows what it reads, and the deposit API, which alone knows what it takes. Deciding it in the page would put half the rules in one language and half in the other, and would have to be written twice the day one of them changes.

D2. One module calls the deposit API, and one only. The day that API changes, there is one file to read again. It is the same reason which keeps the domain of the workspaces behind a single module.

Decided elsewhere

Two decisions of the tool are written where they are read, and are named here so that this chapter is the place one looks: a workspace takes the name of the place which holds the copies, said where each table stands; and the bounds, the duration, what names a place and when it is emptied, which are the deposit API's and are written in its dossier.

What was set aside

Considered, and decided against

These are not missing. Each was written, weighed, and left out for the reason beside it — which is what keeps the question from being reopened in six months, and answered the other way for want of the reason.

WhatWhy
Sending the contents as the person feeds, rather than when she gives A composition which takes an hour would expire under the person making it, and be deleted by the request of somebody else. A deposit cannot begin to age before it exists
Refusing a whole deposit because two of its files bear one name The domain cannot see how files group in any case, the folder they were taken from not travelling with them. Refusing everything would cost two hundred files for one collision, and would not buy what it was meant to buy
Refusing to enter an app, before it is entered, for want of files Only an app knows what it needs — one file, a sound, two of them. A launcher can ask whether anything is checked and nothing more, which never relieves the app of the case. It doubles a responsibility instead of taking one
Handing an app the workspace of the person A rule an app is asked to respect is not a door. What is handed is made for it, so what it can damage is its own
Offering an app a list of files or a workspace, whichever suits it Two contracts to hold for one need, two ways of giving back, and no gain: the apps already speak the workspace, and those which work by root need what a list does not carry
Deciding in the page whether a file is accepted The rules would live half in one language and half in the other, and would be written twice the day one of them changes. What is read online is the exception, and the logic has no reason to emigrate for it
Waiting for an app to have finished before giving back what it produced A design which forbade giving back as one goes would forbid what no need asks to forbid, and the person would wait for the last result to see the first
Making this domain the gate through which anything touching a workspace must pass A gate one can walk around is not a gate: nothing obliges an app to call it. What makes the door hold is what is handed, not a rule — and each writes what it is responsible for

Left open

These are neither decided nor dropped. They are known, and they wait.

  • One word is not settled: the one for a file designated and not yet duplicated. What is given at one time is written deposit throughout, and that one is settled.

Annexes

Annex: Legal notices

  • Author: Brigitte Bigi
  • Document License: GNU Free Documentation License (GFDL) 1.3
  • Copyright (C) 2026 Brigitte Bigi, CNRS
  • Creation Date: 2026-09-11
  • Last update: 2026-09-13